pax_global_header00006660000000000000000000000064132321535430014513gustar00rootroot0000000000000052 comment=da1ac1ec03352332616849de8d947d2f9de20ce5 manila-ui-2.13.0/000077500000000000000000000000001323215354300134525ustar00rootroot00000000000000manila-ui-2.13.0/.coveragerc000066400000000000000000000001761323215354300155770ustar00rootroot00000000000000[run] branch = True source = manila_ui omit = manila_ui/enabled*,manila_ui/test* [report] precision = 2 ignore_errors = True manila-ui-2.13.0/.gitignore000066400000000000000000000010761323215354300154460ustar00rootroot00000000000000*.py[cod] # C extensions *.so # Packages *.egg* dist build eggs parts bin var sdist develop-eggs .installed.cfg lib lib64 # Installer logs pip-log.txt # Unit test / coverage reports .coverage .tox nosetests.xml .testrepository .venv # Translations *.mo # Mr Developer .mr.developer.cfg .project .pydevproject # Complexity output/*.html output/*/index.html # Sphinx doc/build # Files created by releasenotes build releasenotes/build # pbr generates these AUTHORS ChangeLog # Editors *~ .*.swp .*sw? # Unit test artifacts *.secret_key_store.lock .secret_key_store manila-ui-2.13.0/.gitreview000066400000000000000000000001161323215354300154560ustar00rootroot00000000000000[gerrit] host=review.openstack.org port=29418 project=openstack/manila-ui.git manila-ui-2.13.0/.mailmap000066400000000000000000000001301323215354300150650ustar00rootroot00000000000000# Format is: # # manila-ui-2.13.0/.testr.conf000066400000000000000000000004761323215354300155470ustar00rootroot00000000000000[DEFAULT] test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ ${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--listmanila-ui-2.13.0/CONTRIBUTING.rst000066400000000000000000000010251323215354300161110ustar00rootroot00000000000000If you would like to contribute to the development of OpenStack, you must follow the steps in this page: https://docs.openstack.org/infra/manual/developers.html Once those steps have been completed, changes to OpenStack should be submitted for review via the Gerrit tool, following the workflow documented at: https://docs.openstack.org/infra/manual/developers.html#development-workflow Pull requests submitted through GitHub will be ignored. Bugs should be filed on Launchpad, not GitHub: https://bugs.launchpad.net/manila-ui manila-ui-2.13.0/HACKING.rst000066400000000000000000000002361323215354300152510ustar00rootroot00000000000000manila-ui Style Commandments =============================================== Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/manila-ui-2.13.0/LICENSE000066400000000000000000000236361323215354300144710ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. manila-ui-2.13.0/README.rst000066400000000000000000000007761323215354300151530ustar00rootroot00000000000000======================================= manila-ui - Manila Management Dashboard ======================================= * Free software: Apache license * Documentation: https://docs.openstack.org/manila-ui/latest/ * Source: https://git.openstack.org/cgit/openstack/manila-ui * Bugs: https://bugs.launchpad.net/manila-ui Team and repository tags ------------------------ .. image:: https://governance.openstack.org/badges/manila-ui.svg :target: https://governance.openstack.org/reference/tags/index.html manila-ui-2.13.0/babel-django.cfg000066400000000000000000000002041323215354300164340ustar00rootroot00000000000000[extractors] django = django_babel.extract:extract_django [python: **.py] [django: templates/**.html] [django: **/templates/**.csv]manila-ui-2.13.0/babel-djangojs.cfg000066400000000000000000000010571323215354300170000ustar00rootroot00000000000000[extractors] # We use a custom extractor to find translatable strings in AngularJS # templates. The extractor is included in horizon.utils for now. # See http://babel.pocoo.org/docs/messages/#referencing-extraction-methods for # details on how this works. angular = horizon.utils.babel_extract_angular:extract_angular [javascript: **.js] # We need to look into all static folders for HTML files. # The **/static ensures that we also search within # .../dashboards/XYZ/static which will ensure # that plugins are also translated. [angular: **/static/**.html]manila-ui-2.13.0/babel.cfg000066400000000000000000000000201323215354300151700ustar00rootroot00000000000000[python: **.py] manila-ui-2.13.0/devstack/000077500000000000000000000000001323215354300152565ustar00rootroot00000000000000manila-ui-2.13.0/devstack/plugin.sh000066400000000000000000000032741323215354300171160ustar00rootroot00000000000000# plugin.sh - DevStack plugin.sh dispatch script manila-ui function install_manila_ui { # NOTE(vponomaryov): workaround for devstack bug: 1540328 # where devstack install 'test-requirements' but should not do it # for manila-ui project as it installs Horizon from url. # Remove following two 'mv' commands when mentioned bug is fixed. mv $MANILA_UI_DIR/test-requirements.txt $MANILA_UI_DIR/_test-requirements.txt setup_develop ${MANILA_UI_DIR} mv $MANILA_UI_DIR/_test-requirements.txt $MANILA_UI_DIR/test-requirements.txt } # check for service enabled if is_service_enabled horizon && is_service_enabled manila && is_service_enabled manila-ui; then if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then # Set up system services # no-op : elif [[ "$1" == "stack" && "$2" == "install" ]]; then # Perform installation of service source echo_summary "Installing Manila UI" install_manila_ui elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then # Configure after the other layer 1 and 2 services have been configured echo_summary "Configuring Manila UI" cp -a ${MANILA_UI_DIR}/manila_ui/local/enabled/* ${DEST}/horizon/openstack_dashboard/local/enabled/ cp -a ${MANILA_UI_DIR}/manila_ui/local/local_settings.d/* ${DEST}/horizon/openstack_dashboard/local/local_settings.d/ elif [[ "$1" == "stack" && "$2" == "extra" ]]; then # no-op : fi if [[ "$1" == "unstack" ]]; then # no-op : fi if [[ "$1" == "clean" ]]; then # Remove state and transient data # Remember clean.sh first calls unstack.sh # no-op : fi fi manila-ui-2.13.0/devstack/settings000066400000000000000000000002141323215354300170360ustar00rootroot00000000000000# settings file for manila-ui plugin enable_service manila-ui # set up default directories MANILA_UI_DIR=${MANILA_UI_DIR:=$DEST/manila-ui} manila-ui-2.13.0/doc/000077500000000000000000000000001323215354300142175ustar00rootroot00000000000000manila-ui-2.13.0/doc/source/000077500000000000000000000000001323215354300155175ustar00rootroot00000000000000manila-ui-2.13.0/doc/source/admin/000077500000000000000000000000001323215354300166075ustar00rootroot00000000000000manila-ui-2.13.0/doc/source/admin/index.rst000066400000000000000000000102571323215354300204550ustar00rootroot00000000000000==================== Administration Guide ==================== Shares are file storage that instances can access. Users can allow or deny a running instance to have access to a share at any time. For information about using the Dashboard to create and manage shares as an end user, see the :doc:`User Guide `. As an administrative user, you can manage shares and share types for users in various projects. You can create and delete share types, and view or delete shares. Create a share type ------------------- #. Log in to the Dashboard and choose the :guilabel:`admin` project from the drop-down list. #. On the :guilabel:`Admin` tab, open the :guilabel:`System` tab and click the :guilabel:`Shares` category. #. Click the :guilabel:`Share Types` tab, and click :guilabel:`Create Share Type` button. In the :guilabel:`Create Share Type` window, enter or select the following values. :guilabel:`Name`: Enter a name for the share type. :guilabel:`Driver handles share servers`: Choose True or False :guilabel:`Extra specs`: To add extra specs, use key=value. #. Click :guilabel:`Create Share Type` button to confirm your changes. .. note:: A message indicates whether the action succeeded. Update share type ----------------- #. Log in to the Dashboard and choose the :guilabel:`admin` project from the drop-down list. #. On the :guilabel:`Admin` tab, open the :guilabel:`System` tab and click the :guilabel:`Shares` category. #. Click the :guilabel:`Share Types` tab, select the share type that you want to update. #. Select :guilabel:`Update Share Type` from Actions. #. In the :guilabel:`Update Share Type` window, update extra specs. :guilabel:`Extra specs`: To add extra specs, use key=value. To unset extra specs, use key. #. Click :guilabel:`Update Share Type` button to confirm your changes. .. note:: A message indicates whether the action succeeded. Delete share types ------------------ When you delete a share type, shares of that type are not deleted. #. Log in to the Dashboard and choose the :guilabel:`admin` project from the drop-down list. #. On the :guilabel:`Admin` tab, open the :guilabel:`System` tab and click the :guilabel:`Shares` category. #. Click the :guilabel:`Share Types` tab, select the share type or types that you want to delete. #. Click :guilabel:`Delete Share Types` button. #. In the :guilabel:`Confirm Delete Share Types` window, click the :guilabel:`Delete Share Types` button to confirm the action. .. note:: A message indicates whether the action succeeded. Delete shares ------------- #. Log in to the Dashboard and choose the :guilabel:`admin` project from the drop-down list. #. On the :guilabel:`Admin` tab, open the :guilabel:`System` tab and click the :guilabel:`Shares` category. #. Select the share or shares that you want to delete. #. Click :guilabel:`Delete Shares` button. #. In the :guilabel:`Confirm Delete Shares` window, click the :guilabel:`Delete Shares` button to confirm the action. .. note:: A message indicates whether the action succeeded. Delete share server ------------------- #. Log in to the Dashboard and choose the :guilabel:`admin` project from the drop-down list. #. On the :guilabel:`Admin` tab, open the :guilabel:`System` tab and click the :guilabel:`Share Servers` category. #. Select the share that you want to delete. #. Click :guilabel:`Delete Share Server` button. #. In the :guilabel:`Confirm Delete Share Server` window, click the :guilabel:`Delete Share Server` button to confirm the action. .. note:: A message indicates whether the action succeeded. Delete share networks --------------------- #. Log in to the Dashboard and choose the :guilabel:`admin` project from the drop-down list. #. On the :guilabel:`Admin` tab, open the :guilabel:`System` tab and click the :guilabel:`Share Networks` category. #. Select the share network or share networks that you want to delete. #. Click :guilabel:`Delete Share Networks` button. #. In the :guilabel:`Confirm Delete Share Networks` window, click the :guilabel:`Delete Share Networks` button to confirm the action. .. note:: A message indicates whether the action succeeded. manila-ui-2.13.0/doc/source/conf.py000066400000000000000000000052311323215354300170170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # 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 os import sys import openstackdocstheme sys.path.insert(0, os.path.abspath('../..')) # -- General configuration ---------------------------------------------------- # 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', #'sphinx.ext.intersphinx', 'openstackdocstheme', ] # openstackdocstheme options repository_name = 'openstack/manila-ui' bug_project = 'manila-ui' bug_tag = 'docs' html_last_updated_fmt = '%Y-%m-%d %H:%M' # autodoc generation is a bit aggressive and a nuisance when doing heavy # text edit cycles. # execute "export SPHINX_DEBUG=1" in your terminal to disable # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. project = u'manila-ui' copyright = u'2013, OpenStack Foundation' # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). add_module_names = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # -- Options for HTML output -------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. # html_theme_path = ["."] html_theme = 'openstackdocs' html_theme_path = [openstackdocstheme.get_html_theme_path()] # html_static_path = ['static'] # Output file base name for HTML help builder. htmlhelp_basename = '%sdoc' % project # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass # [howto/manual]). latex_documents = [ ('index', '%s.tex' % project, u'%s Documentation' % project, u'OpenStack Foundation', 'manual'), ] # Example configuration for intersphinx: refer to the Python standard library. #intersphinx_mapping = {'http://docs.python.org/': None} manila-ui-2.13.0/doc/source/configuration/000077500000000000000000000000001323215354300203665ustar00rootroot00000000000000manila-ui-2.13.0/doc/source/configuration/index.rst000066400000000000000000000022051323215354300222260ustar00rootroot00000000000000============= Configuration ============= It is possible to enable or disable some Manila UI features. To do so, look for files located in "manila_ui/local/local_settings.d/" directory, where you can redefine the values of the OPENSTACK_MANILA_FEATURES dict: * enable_share_groups * enable_replication * enable_migration * enable_public_share_type_creation * enable_public_share_group_type_creation * enable_public_shares * enabled_share_protocols By default, enabled_share_protocols within the OPENSTACK_MANILA_FEATURES dict contains a list with all the supported protocols. The operator can change this to display to users only those protocols that has been deployed and are available to use. E.g. if only NFS is available, the operator is expected to redefine enabled_share_protocols as follows: .. code-block:: python OPENSTACK_MANILA_FEATURES = { 'enable_share_groups': True, 'enable_replication': True, 'enable_migration': True, 'enable_public_share_type_creation': True, 'enable_public_share_group_type_creation': True, 'enable_public_shares': True, 'enabled_share_protocols': ['NFS'], } manila-ui-2.13.0/doc/source/contributor/000077500000000000000000000000001323215354300200715ustar00rootroot00000000000000manila-ui-2.13.0/doc/source/contributor/contributing.rst000066400000000000000000000001161323215354300233300ustar00rootroot00000000000000============ Contributing ============ .. include:: ../../../CONTRIBUTING.rst manila-ui-2.13.0/doc/source/contributor/features.rst000066400000000000000000000020331323215354300224370ustar00rootroot00000000000000============ New Features ============ When implementing a new feature, you may think about making it optional, so it could be enabled or disabled in different deployments. How to use it: .. code-block:: python from django.conf import settings manila_config = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {}) manila_config.get('your_new_config_option', 'value_of_config_option') See :doc:`/configuration/index` section for more configuration details. It is also expected that each addition of new logic to Manila UI is covered by unit tests. Test modules should be located under "manila_ui/tests", satisfying the following template when tests are written for a specific module: .. code-block:: none manila_ui[/tests]/path/to/[test_]modulename.py However, when testing the flow between different modules (using test app), the tests can be added to a test module that can satisfy the following template: .. code-block:: none manila_ui[/tests]/path/to/directory/tests.py Manila UI tests use the mock library for testing. manila-ui-2.13.0/doc/source/contributor/index.rst000066400000000000000000000002241323215354300217300ustar00rootroot00000000000000========================= Contributor Documentation ========================= .. toctree:: :maxdepth: 2 contributing testing features manila-ui-2.13.0/doc/source/contributor/testing.rst000066400000000000000000000017121323215354300223010ustar00rootroot00000000000000======= Testing ======= Starting the app ---------------- If everything has gone according to plan, you should be able to run: .. code-block:: console ./run_tests.sh --runserver 0.0.0.0:8080 and have the application start on port 8080. The horizon dashboard will be located at http://localhost:8080/ Running unit tests ------------------ The unit tests can be executed directly from within this Manila UI plugin project directory by using:: $ cd ../manila-ui $ tox This is made possible by the dependency in test-requirements.txt upon the horizon source, which pulls down all of the horizon and openstack_dashboard modules that the plugin uses. To run only py27 unit tests, use following command:: $ tox -e py27 To run only py34 unit tests, use following command:: $ tox -e py34 To run unit tests using specific Django version use the following:: $ tox -e py27dj17 $ tox -e py27dj18 $ tox -e py27dj19 $ tox -e py27dj110 manila-ui-2.13.0/doc/source/index.rst000066400000000000000000000010001323215354300173470ustar00rootroot00000000000000.. manila-ui documentation master file, created by sphinx-quickstart on Tue Jul 9 22:26:36 2013. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. .. the main title comes from README.rst .. include:: ../../README.rst Contents -------- .. toctree:: :maxdepth: 2 install/installation configuration/index user/index admin/index contributor/index Indices and tables ------------------ * :ref:`genindex` * :ref:`search` manila-ui-2.13.0/doc/source/install/000077500000000000000000000000001323215354300171655ustar00rootroot00000000000000manila-ui-2.13.0/doc/source/install/installation.rst000066400000000000000000000035421323215354300224240ustar00rootroot00000000000000============ Installation ============ Manual Installation ------------------- For Manila UI installation in RDO, see: :ref:`install-rdo`. For other distributions, begin by cloning the Horizon and Manila UI repositories:: git clone https://github.com/openstack/horizon git clone https://github.com/openstack/manila-ui Create a virtual environment and install Horizon dependencies:: cd horizon python tools/install_venv.py Set up your ``local_settings.py`` file:: cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py Open up the copied ``local_settings.py`` file in your preferred text editor. You will want to customize several settings: - ``OPENSTACK_HOST`` should be configured with the hostname of your OpenStack server. Verify that the ``OPENSTACK_KEYSTONE_URL`` and ``OPENSTACK_KEYSTONE_DEFAULT_ROLE`` settings are correct for your environment. (They should be correct unless you modified your OpenStack server to change them.) Install Manila UI with all dependencies in your virtual environment:: tools/with_venv.sh pip install -e ../manila-ui/ And enable it in Horizon:: cp ../manila-ui/manila_ui/local/enabled/_*.py openstack_dashboard/local/enabled cp ../manila-ui/manila_ui/local/local_settings.d/_90_manila_*.py openstack_dashboard/local/local_settings.d .. _install-rdo: Installing Manila UI in RDO --------------------------- In order to install Manila UI in `RDO `__, please follow the steps below (you may need to use `sudo` privileges if you are not root):: # yum install -y openstack-manila-ui # systemctl restart httpd # systemctl restart memcached Manila UI will now be available through OpenStack Horizon; look for the Shares tab under Project > Compute. You can access Horizon with Manila UI using the same URL and port as before. manila-ui-2.13.0/doc/source/user/000077500000000000000000000000001323215354300164755ustar00rootroot00000000000000manila-ui-2.13.0/doc/source/user/index.rst000066400000000000000000000152031323215354300203370ustar00rootroot00000000000000========== User Guide ========== Shares are file storage that you provide access to instances. You can allow access to a share to a running instance or deny access to a share and allow access to it to another instance at any time. You can also delete a share. You can create snapshot from a share if the driver supports it. Only administrative users can create share types. Create a share -------------- #. Log in to the dashboard, choose a project, and click :guilabel:`Shares`. #. Click :guilabel:`Create Share`. In the dialog box that opens, enter or select the following values. :guilabel:`Share Name`: Specify a name for the share. :guilabel:`Description`: Optionally, provide a brief description for the share. :guilabel:`Share Type`: Choose a share type. :guilabel:`Size (GB)`: The size of the share in gibibytes (GiB). :guilabel:`Share Protocol`: Select NFS, CIFS, GlusterFS, or HDFS. :guilabel:`Share Network`: Choose a share network. :guilabel:`Metadata`: Enter metadata for the share creation if needed. #. Click :guilabel:`Create Share`. The dashboard shows the share on the :guilabel:`Shares` tab. Delete a share -------------- #. Log in to the dashboard, choose a project, and click :guilabel:`Shares`. #. Select the check boxes for the shares that you want to delete. #. Click :guilabel:`Delete Shares` and confirm your choice. A message indicates whether the action was successful. Allow access ------------ #. Log in to the dashboard, choose a project, and click :guilabel:`Shares`. #. Go to the share that you want to allow access and choose :guilabel:`Manage Rules` from Actions. #. Click :guilabel:`Add rule`. :guilabel:`Access Type`: Choose ip, user, or cert. :guilabel:`Access Level`: Choose read-write or read-only. :guilabel:`Access To`: Fill in Access To field. #. Click :guilabel:`Add Rule`. A message indicates whether the action was successful. Deny access ----------- #. Log in to the dashboard, choose a project, and click :guilabel:`Shares`. #. Go to the share that you want to deny access and choose :guilabel:`Manage Rules` from Actions. #. Choose the rule you want to delete. #. Click :guilabel:`Delete rule` and confirm your choice. A message indicates whether the action was successful. Edit share metadata ------------------- #. Log in to the dashboard, choose a project, and click :guilabel:`Shares`. #. Go to the share that you want to edit and choose :guilabel:`Edit Share Metadata` from Actions. #. :guilabel:`Metadata`: To add share metadata, use key=value. To unset metadata, use key. #. Click :guilabel:`Edit Share Metadata`. A message indicates whether the action was successful. Edit share ---------- #. Log in to the dashboard, choose a project, and click :guilabel:`Shares`. #. Go to the share that you want to edit and choose :guilabel:`Edit Share` from Actions. #. :guilabel:`Share Name`: Enter a new share name. #. :guilabel:`Description`: Enter a new description. #. Click :guilabel:`Edit Share`. A message indicates whether the action was successful. Extend share ------------ #. Log in to the dashboard, choose a project, and click :guilabel:`Shares`. #. Go to the share that you want to edit and choose :guilabel:`Extend Share` from Actions. #. :guilabel:`New Size (GB)`: Enter new size. #. Click :guilabel:`Extend Share`. A message indicates whether the action was successful. Create share network -------------------- #. Log in to the dashboard, choose a project, click :guilabel:`Shares`, and click :guilabel:`Share Networks`. #. Click :guilabel:`Create Share Network`. In the dialog box that opens, enter or select the following values. :guilabel:`Name`: Specify a name for the share network. :guilabel:`Description`: Optionally, provide a brief description for the share network. :guilabel:`Neutron Net`: Choose a neutron network. :guilabel:`Neutron Subnet`: Choose a neutron subnet. #. Click :guilabel:`Create Share Network`. The dashboard shows the share network on the :guilabel:`Share Networks` tab. Delete a share network ---------------------- #. Log in to the dashboard, choose a project, click :guilabel:`Shares`, and click :guilabel:`Share Networks`. #. Select the check boxes for the share networks that you want to delete. #. Click :guilabel:`Delete Share Networks` and confirm your choice. A message indicates whether the action was successful. Edit share network ------------------ #. Log in to the dashboard, choose a project, click :guilabel:`Shares`, and click :guilabel:`Share Networks`. #. Go to the share network that you want to edit and choose :guilabel:`Edit Share Network` from Actions. #. :guilabel:`Name`: Enter a new share network name. #. :guilabel:`Description`: Enter a new description. #. Click :guilabel:`Edit Share Network`. A message indicates whether the action was successful. Create security service ----------------------- #. Log in to the dashboard, choose a project, click :guilabel:`Shares`, and click :guilabel:`Security Services`. #. Click :guilabel:`Create Security Service`. In the dialog box that opens, enter or select the following values. :guilabel:`Name`: Specify a name for the security service. :guilabel:`DNS IP`: Enter the DNS IP address. :guilabel:`Server`: Enter the server name. :guilabel:`Domain`: Enter the domain name. :guilabel:`User`: Enter the user name. :guilabel:`Password`: Enter the password. :guilabel:`Confirm Password`: Enter the password again to confirm. :guilabel:`Type`: Choose the type from Active Directory, LDAP, or Kerberos. :guilabel:`Description`: Optionally, provide a brief description for the security service. #. Click :guilabel:`Create Security Service`. The dashboard shows the security service on the :guilabel:`Security Services` tab. Delete a security service ------------------------- #. Log in to the dashboard, choose a project, click :guilabel:`Shares`, and click :guilabel:`Security Services`. #. Select the check boxes for the security services that you want to delete. #. Click :guilabel:`Delete Security Services` and confirm your choice. A message indicates whether the action was successful. Edit security service --------------------- #. Log in to the dashboard, choose a project, click :guilabel:`Shares`, and click :guilabel:`Security Services`. #. Go to the security service that you want to edit and choose :guilabel:`Edit Security Service` from Actions. #. :guilabel:`Name`: Enter a new security service name. #. :guilabel:`Description`: Enter a new description. #. Click :guilabel:`Edit Security Service`. A message indicates whether the action was successful. manila-ui-2.13.0/manage.py000077500000000000000000000014721323215354300152630ustar00rootroot00000000000000#!/usr/bin/env python # 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 os import sys from django.core.management import execute_from_command_line if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "manila_ui.tests.settings") execute_from_command_line(sys.argv) manila-ui-2.13.0/manila_ui/000077500000000000000000000000001323215354300154105ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/__init__.py000066400000000000000000000012311323215354300175160ustar00rootroot00000000000000# -*- coding: utf-8 -*- # 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 pbr.version __version__ = pbr.version.VersionInfo( 'manila_ui').version_string() manila-ui-2.13.0/manila_ui/api/000077500000000000000000000000001323215354300161615ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/api/__init__.py000066400000000000000000000000001323215354300202600ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/api/manila.py000066400000000000000000000512051323215354300177770ustar00rootroot00000000000000# Copyright 2012 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # Copyright 2012 OpenStack Foundation # Copyright 2012 Nebula, Inc. # Copyright (c) 2012 X.commerce, a business unit of eBay Inc. # # 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 __future__ import absolute_import from django.conf import settings from horizon import exceptions import logging from openstack_dashboard.api import base import six from manilaclient import client as manila_client LOG = logging.getLogger(__name__) MANILA_UI_USER_AGENT_REPR = "manila_ui_plugin_for_horizon" # NOTE(vponomaryov): update version to 2.34 when manilaclient is released with # its support. It will allow to show 'availability zones' for share groups. MANILA_VERSION = "2.32" # requires manilaclient 1.13.0 or newer MANILA_SERVICE_TYPE = "sharev2" # API static values SHARE_STATE_AVAILABLE = "available" DEFAULT_QUOTA_NAME = 'default' def manilaclient(request): insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False) cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None) manila_url = "" try: manila_url = base.url_for(request, MANILA_SERVICE_TYPE) except exceptions.ServiceCatalogException: LOG.debug('no share service configured.') return None LOG.debug('manilaclient connection created using token "%s" and url "%s"' % (request.user.token.id, manila_url)) c = manila_client.Client( MANILA_VERSION, username=request.user.username, input_auth_token=request.user.token.id, project_id=request.user.tenant_id, service_catalog_url=manila_url, insecure=insecure, cacert=cacert, http_log_debug=settings.DEBUG, user_agent=MANILA_UI_USER_AGENT_REPR, ) c.client.auth_token = request.user.token.id c.client.management_url = manila_url return c def share_list(request, search_opts=None): return manilaclient(request).shares.list(search_opts=search_opts) def share_get(request, share_id): share_data = manilaclient(request).shares.get(share_id) return share_data def share_create(request, size, name, description, proto, snapshot_id=None, metadata=None, share_network=None, share_type=None, is_public=None, availability_zone=None, share_group_id=None): return manilaclient(request).shares.create( proto, size, name=name, description=description, share_network=share_network, snapshot_id=snapshot_id, metadata=metadata, share_type=share_type, is_public=is_public, availability_zone=availability_zone, share_group_id=share_group_id, ) def share_delete(request, share_id, share_group_id=None): return manilaclient(request).shares.delete( share_id, share_group_id=share_group_id, ) def share_update(request, share_id, name, description, is_public=''): share_data = {'display_name': name, 'display_description': description} if not isinstance(is_public, six.string_types): is_public = six.text_type(is_public) if is_public and is_public.lower() != 'none': share_data['is_public'] = is_public return manilaclient(request).shares.update(share_id, **share_data) def share_rules_list(request, share_id): return manilaclient(request).shares.access_list(share_id) def share_export_location_list(request, share_id): return manilaclient(request).share_export_locations.list(share_id) def share_instance_export_location_list(request, share_instance_id): return manilaclient(request).share_instance_export_locations.list( share_instance_id) def share_allow(request, share_id, access_type, access_to, access_level): return manilaclient(request).shares.allow( share_id, access_type, access_to, access_level) def share_deny(request, share_id, rule_id): return manilaclient(request).shares.deny(share_id, rule_id) def share_manage(request, service_host, protocol, export_path, driver_options=None, share_type=None, name=None, description=None, is_public=False): return manilaclient(request).shares.manage( service_host=service_host, protocol=protocol, export_path=export_path, driver_options=driver_options, share_type=share_type, name=name, description=description, is_public=is_public, ) def migration_start(request, share, dest_host, force_host_assisted_migration, writable, preserve_metadata, preserve_snapshots, nondisruptive, new_share_network_id, new_share_type_id): return manilaclient(request).shares.migration_start( share, host=dest_host, force_host_assisted_migration=force_host_assisted_migration, writable=writable, preserve_metadata=preserve_metadata, preserve_snapshots=preserve_snapshots, nondisruptive=nondisruptive, new_share_network_id=new_share_network_id, new_share_type_id=new_share_type_id ) def migration_complete(request, share): return manilaclient(request).shares.migration_complete(share) def migration_get_progress(request, share): return manilaclient(request).shares.migration_get_progress(share) def migration_cancel(request, share): return manilaclient(request).shares.migration_cancel(share) def share_unmanage(request, share): # Param 'share' can be either string with ID or object with attr 'id'. return manilaclient(request).shares.unmanage(share) def share_extend(request, share_id, new_size): return manilaclient(request).shares.extend(share_id, new_size) def share_revert(request, share, snapshot): """Sends request to revert share to specific snapshot. This API available only since 2.27 microversion. :param share: Share class instance or share ID :param snapshot: ShareSnapshot class instance or share snapshot ID """ return manilaclient(request).shares.revert_to_snapshot(share, snapshot) def share_snapshot_get(request, snapshot_id): return manilaclient(request).share_snapshots.get(snapshot_id) def share_snapshot_update(request, snapshot_id, name, description): snapshot_data = {'display_name': name, 'display_description': description} return manilaclient(request).share_snapshots.update( snapshot_id, **snapshot_data) def share_snapshot_list(request, detailed=True, search_opts=None, sort_key=None, sort_dir=None): # Example of 'search_opts' value: # {'share_id': 'id_of_existing_share'} return manilaclient(request).share_snapshots.list( detailed=detailed, search_opts=search_opts, sort_key=sort_key, sort_dir=sort_dir, ) def share_snapshot_create(request, share_id, name=None, description=None, force=False): return manilaclient(request).share_snapshots.create( share_id, force=force, name=name, description=description) def share_snapshot_delete(request, snapshot_id): return manilaclient(request).share_snapshots.delete(snapshot_id) def share_snapshot_allow(request, snapshot_id, access_type, access_to): return manilaclient(request).share_snapshots.allow( snapshot_id, access_type, access_to) def share_snapshot_deny(request, snapshot_id, rule_id): return manilaclient(request).share_snapshots.deny(snapshot_id, rule_id) def share_snapshot_rules_list(request, snapshot_id): return manilaclient(request).share_snapshots.access_list(snapshot_id) def share_snap_export_location_list(request, snapshot): return manilaclient(request).share_snapshot_export_locations.list( snapshot=snapshot) def share_snap_instance_export_location_list(request, snapshot_instance): return manilaclient(request).share_snapshot_export_locations.list( snapshot_instance=snapshot_instance) def share_server_list(request, search_opts=None): return manilaclient(request).share_servers.list(search_opts=search_opts) def share_server_get(request, share_serv_id): return manilaclient(request).share_servers.get(share_serv_id) def share_server_delete(request, share_serv_id): return manilaclient(request).share_servers.delete(share_serv_id) def share_network_list(request, detailed=False, search_opts=None): return manilaclient(request).share_networks.list(detailed=detailed, search_opts=search_opts) def share_network_create(request, neutron_net_id=None, neutron_subnet_id=None, name=None, description=None): return manilaclient(request).share_networks.create( neutron_net_id=neutron_net_id, neutron_subnet_id=neutron_subnet_id, name=name, description=description) def share_network_get(request, share_net_id): return manilaclient(request).share_networks.get(share_net_id) def share_network_update(request, share_net_id, name=None, description=None): return manilaclient(request).share_networks.update( share_net_id, name=name, description=description) def share_network_delete(request, share_network_id): return manilaclient(request).share_networks.delete(share_network_id) def security_service_list(request, search_opts=None): return manilaclient(request).security_services.list( detailed=True, search_opts=search_opts) def security_service_get(request, sec_service_id, search_opts=None): return manilaclient(request).security_services.get(sec_service_id) def security_service_create(request, type, dns_ip=None, server=None, domain=None, user=None, password=None, name=None, description=None): return manilaclient(request).security_services.create( type, dns_ip=dns_ip, server=server, domain=domain, user=user, password=password, name=name, description=description) def security_service_update(request, security_service_id, dns_ip=None, server=None, domain=None, user=None, password=None, name=None, description=None): return manilaclient(request).security_services.update( security_service_id, dns_ip=dns_ip, server=server, domain=domain, user=user, password=password, name=name, description=description, ) def security_service_delete(request, security_service_id): return manilaclient(request).security_services.delete(security_service_id) def share_network_security_service_add(request, share_network_id, security_service_id): return manilaclient(request).share_networks.add_security_service( share_network_id, security_service_id) def share_network_security_service_remove(request, share_network_id, security_service_id): return manilaclient(request).share_networks.remove_security_service( share_network_id, security_service_id) def share_network_security_service_list(request, share_network_id): return manilaclient(request).security_services.list( search_opts={'share_network_id': share_network_id}) def share_set_metadata(request, share_id, metadata): return manilaclient(request).shares.set_metadata(share_id, metadata) def share_delete_metadata(request, share_id, keys): return manilaclient(request).shares.delete_metadata(share_id, keys) def tenant_quota_get(request, tenant_id): return base.QuotaSet(manilaclient(request).quotas.get(tenant_id)) def _map_quota_names_for_update(data): mapping = { 'share_gigabytes': 'gigabytes', 'share_snapshots': 'snapshots', 'share_snapshot_gigabytes': 'snapshot_gigabytes', } for k, v in mapping.items(): if k in data: data[v] = data.pop(k) return data def tenant_quota_update(request, tenant_id, **kwargs): _map_quota_names_for_update(kwargs) return manilaclient(request).quotas.update(tenant_id, **kwargs) def default_quota_get(request, tenant_id): return base.QuotaSet(manilaclient(request).quotas.defaults(tenant_id)) def default_quota_update(request, **kwargs): _map_quota_names_for_update(kwargs) manilaclient(request).quota_classes.update(DEFAULT_QUOTA_NAME, **kwargs) def share_type_list(request): return manilaclient(request).share_types.list() def share_type_get(request, share_type_id): return manilaclient(request).share_types.get(share_type_id) def share_type_create(request, name, spec_driver_handles_share_servers, spec_snapshot_support=True, is_public=True): return manilaclient(request).share_types.create( name=name, spec_driver_handles_share_servers=spec_driver_handles_share_servers, spec_snapshot_support=spec_snapshot_support, is_public=is_public) def share_type_delete(request, share_type_id): return manilaclient(request).share_types.delete(share_type_id) def share_type_get_extra_specs(request, share_type_id): return manilaclient(request).share_types.get(share_type_id).get_keys() def share_type_set_extra_specs(request, share_type_id, extra_specs): return manilaclient(request).share_types.get( share_type_id).set_keys(extra_specs) def share_type_unset_extra_specs(request, share_type_id, keys): return manilaclient(request).share_types.get( share_type_id).unset_keys(keys) def share_type_access_list(request, share_type_id): return manilaclient(request).share_type_access.list(share_type_id) def share_type_access_add(request, share_type_id, project_id): return manilaclient(request).share_type_access.add_project_access( share_type_id, project_id) def share_type_access_remove(request, share_type_id, project_id): return manilaclient(request).share_type_access.remove_project_access( share_type_id, project_id) def share_replica_list(request, share=None): return manilaclient(request).share_replicas.list(share) def share_replica_create(request, share, availability_zone, share_network=None): return manilaclient(request).share_replicas.create( share, availability_zone=availability_zone, share_network=share_network) def share_replica_get(request, replica): return manilaclient(request).share_replicas.get(replica) def share_replica_delete(request, replica): return manilaclient(request).share_replicas.delete(replica) def share_replica_promote(request, replica): return manilaclient(request).share_replicas.promote(replica) def share_replica_reset_status(request, replica, status): return manilaclient(request).share_replicas.reset_state( replica, status) def share_replica_reset_state(request, replica, state): return manilaclient(request).share_replicas.reset_replica_state( replica, state) def share_replica_resync(request, replica): return manilaclient(request).share_replicas.resync(replica) def tenant_absolute_limits(request): limits = manilaclient(request).limits.get().absolute limits_dict = {} for limit in limits: # -1 is used to represent unlimited quotas if limit.value == -1: limits_dict[limit.name] = float("inf") else: limits_dict[limit.name] = limit.value return limits_dict def share_instance_list(request): return manilaclient(request).share_instances.list() def share_instance_get(request, share_instance_id): return manilaclient(request).share_instances.get(share_instance_id) def availability_zone_list(request): return manilaclient(request).availability_zones.list() def pool_list(request, detailed=False): return manilaclient(request).pools.list(detailed=detailed) # ####### Share Groups # ####### def share_group_create(request, name, description=None, share_group_type=None, share_types=None, share_network=None, source_share_group_snapshot=None, availability_zone=None): return manilaclient(request).share_groups.create( name=name, description=description, share_group_type=share_group_type, share_types=share_types, share_network=share_network, source_share_group_snapshot=source_share_group_snapshot, availability_zone=availability_zone, ) def share_group_get(request, share_group): return manilaclient(request).share_groups.get(share_group) def share_group_update(request, share_group, name, description): return manilaclient(request).share_groups.update( share_group, name=name, description=description, ) def share_group_delete(request, share_group, force=False): return manilaclient(request).share_groups.delete(share_group, force=force) def share_group_reset_state(request, share_group, state): return manilaclient(request).share_groups.reset_state(share_group, state) def share_group_list(request, detailed=True, search_opts=None, sort_key=None, sort_dir=None): return manilaclient(request).share_groups.list( detailed=detailed, search_opts=search_opts, sort_key=sort_key, sort_dir=sort_dir, ) # ####### Share Group Snapshots # ####### def share_group_snapshot_create(request, share_group, name, description=None): return manilaclient(request).share_group_snapshots.create( share_group=share_group, name=name, description=description, ) def share_group_snapshot_get(request, share_group_snapshot): return manilaclient(request).share_group_snapshots.get( share_group_snapshot) def share_group_snapshot_update(request, share_group_snapshot, name, description): return manilaclient(request).share_group_snapshots.update( share_group_snapshot, name=name, description=description, ) def share_group_snapshot_delete(request, share_group_snapshot, force=False): return manilaclient(request).share_group_snapshots.delete( share_group_snapshot, force=force) def share_group_snapshot_reset_state(request, share_group_snapshot, state): return manilaclient(request).share_group_snapshots.reset_state( share_group_snapshot, state) def share_group_snapshot_list(request, detailed=True, search_opts=None, sort_key=None, sort_dir=None): return manilaclient(request).share_group_snapshots.list( detailed=detailed, search_opts=search_opts, sort_key=sort_key, sort_dir=sort_dir, ) # ####### Share Group Types # ######## def share_group_type_create(request, name, share_types, is_public=False, group_specs=None): return manilaclient(request).share_group_types.create( name=name, share_types=share_types, is_public=is_public, group_specs=group_specs) def share_group_type_get(request, share_group_type): return manilaclient(request).share_group_types.get(share_group_type) def share_group_type_list(request, show_all=True): return manilaclient(request).share_group_types.list(show_all=show_all) def share_group_type_delete(request, share_group_type): return manilaclient(request).share_group_types.delete(share_group_type) def share_group_type_access_list(request, share_group_type): return manilaclient(request).share_group_type_access.list(share_group_type) def share_group_type_access_add(request, share_group_type, project): return manilaclient(request).share_group_type_access.add_project_access( share_group_type, project) def share_group_type_access_remove(request, share_group_type, project): return manilaclient(request).share_group_type_access.remove_project_access( share_group_type, project) def share_group_type_set_specs(request, share_group_type, group_specs): return manilaclient(request).share_group_types.get( share_group_type).set_keys(group_specs) def share_group_type_unset_specs(request, share_group_type, keys): return manilaclient(request).share_group_types.get( share_group_type).unset_keys(keys) def share_group_type_get_specs(request, share_group_type): return manilaclient(request).share_group_types.get( share_group_type).get_keys() manila-ui-2.13.0/manila_ui/api/network.py000066400000000000000000000015001323215354300202200ustar00rootroot00000000000000# Copyright (c) 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 openstack_dashboard.api import neutron def network_list(request): return neutron.network_list(request) def network_get(request, net_id): return neutron.network_get(request, net_id) manila-ui-2.13.0/manila_ui/dashboards/000077500000000000000000000000001323215354300175225ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/__init__.py000066400000000000000000000000001323215354300216210ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/000077500000000000000000000000001323215354300206125ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/__init__.py000066400000000000000000000000001323215354300227110ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/000077500000000000000000000000001323215354300243645ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/__init__.py000066400000000000000000000000001323215354300264630ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/panel.py000066400000000000000000000016701323215354300260410ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class SecurityServices(horizon.Panel): name = _("Security Services") slug = 'security_services' permissions = ( 'openstack.services.share', ) dashboard.Admin.register(SecurityServices) manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/tables.py000066400000000000000000000043411323215354300262120ustar00rootroot00000000000000# 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 django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import tables from manila_ui.api import manila class DeleteSecurityService(tables.DeleteAction): policy_rules = (("share", "security_service:delete"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Security Service", u"Delete Security Services", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Security Service", u"Deleted Security Services", count ) def delete(self, request, obj_id): manila.security_service_delete(request, obj_id) class SecurityServicesTable(tables.DataTable): name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:admin:security_services:security_service_detail") project = tables.Column("project_name", verbose_name=_("Project")) dns_ip = tables.Column("dns_ip", verbose_name=_("DNS IP")) server = tables.Column("server", verbose_name=_("Server")) domain = tables.Column("domain", verbose_name=_("Domain")) user = tables.Column("user", verbose_name=_("Sid")) def get_object_display(self, security_service): return security_service.name def get_object_id(self, security_service): return str(security_service.id) class Meta(object): name = "security_services" verbose_name = _("Security Services") table_actions = ( tables.NameFilterAction, DeleteSecurityService, ) row_actions = ( DeleteSecurityService, ) manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/tabs.py000066400000000000000000000021541323215354300256710ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class SecurityServiceOverviewTab(tabs.Tab): name = _("Security Service Overview") slug = "security_service_overview_tab" template_name = "admin/security_services/_detail.html" def get_context_data(self, request): return {"sec_service": self.tab_group.kwargs["sec_service"]} class SecurityServiceDetailTabs(tabs.TabGroup): slug = "security_service_details" tabs = ( SecurityServiceOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/templates/000077500000000000000000000000001323215354300263625ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/templates/security_services/000077500000000000000000000000001323215354300321345ustar00rootroot00000000000000_detail.html000066400000000000000000000020171323215354300343440ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/templates/security_services{% load i18n sizeformat parse_date %}

{% trans "Security Service Overview" %}


{% trans "Type" %}
{{ sec_service.type }}
{% trans "Name" %}
{{ sec_service.name }}
{% trans "ID" %}
{{ sec_service.id }}
{% if sec_service.description %}
{% trans "Description" %}
{{ sec_service.description }}
{% endif %}
{% trans "Created at" %}
{{ sec_service.created_at|parse_date }}

{% trans "Security Service Details" %}


{% trans "DNS IP" %}
{{ sec_service.dns_ip }}
{% trans "Server" %}
{{ sec_service.server }}
{% trans "Domain" %}
{{ sec_service.domain }}
{% trans "User" %}
{{ sec_service.user }}
detail.html000066400000000000000000000003461323215354300342100ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/templates/security_services{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Security Service Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/templates/security_services/index.html000066400000000000000000000003551323215354300341340ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Security Services" %}{% endblock %} {% block main %}
{{ security_services_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/urls.py000066400000000000000000000016071323215354300257270ustar00rootroot00000000000000# 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 django.conf import urls from manila_ui.dashboards.admin.security_services import views urlpatterns = [ urls.url( r'^$', views.SecurityServicesView.as_view(), name='index'), urls.url( r'^(?P[^/]+)$', views.SecurityServiceDetailView.as_view(), name='security_service_detail'), ] manila-ui-2.13.0/manila_ui/dashboards/admin/security_services/views.py000066400000000000000000000040621323215354300260750ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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. """ Admin views for managing security services. """ from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import tables from horizon.utils import memoized from manila_ui.api import manila import manila_ui.dashboards.admin.security_services.tables as ss_tables import manila_ui.dashboards.admin.security_services.tabs as ss_tabs from manila_ui.dashboards.admin import utils import manila_ui.dashboards.project.security_services.views as ss_views class SecurityServicesView(tables.MultiTableView): table_classes = ( ss_tables.SecurityServicesTable, ) template_name = "admin/security_services/index.html" page_title = _("Security Services") @memoized.memoized_method def get_security_services_data(self): try: security_services = manila.security_service_list( self.request, search_opts={'all_tenants': True}) utils.set_project_name_to_objects(self.request, security_services) except Exception: security_services = [] exceptions.handle( self.request, _("Unable to retrieve security services")) return security_services class SecurityServiceDetailView(ss_views.Detail): tab_group_class = ss_tabs.SecurityServiceDetailTabs template_name = "admin/security_services/detail.html" redirect_url = reverse_lazy('horizon:admin:security_services:index') manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/000077500000000000000000000000001323215354300252325ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/__init__.py000066400000000000000000000000001323215354300273310ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/forms.py000066400000000000000000000037351323215354300267420ustar00rootroot00000000000000# Copyright (c) 2017 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 django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from manila_ui.api import manila class ResetShareGroupSnapshotStatusForm(forms.SelfHandlingForm): status = forms.ChoiceField( label=_("Status"), required=True, choices=( ('available', 'available'), ('error', 'error'), ) ) def handle(self, request, data): s_id = self.initial['share_group_snapshot_id'] try: manila.share_group_snapshot_reset_state( request, s_id, data["status"]) message = _( "Reseting share group snapshot ('%(id)s') status " "from '%(from)s' to '%(to)s'.") % { "id": self.initial['share_group_snapshot_name'] or s_id, "from": self.initial['share_group_snapshot_status'], "to": data["status"]} messages.success(request, message) return True except Exception: redirect = reverse("horizon:admin:share_group_snapshots:index") exceptions.handle( request, _("Unable to reset status of share group snapshot " "'%s'.") % s_id, redirect=redirect) return False manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/panel.py000066400000000000000000000017331323215354300267070ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class ShareGroupSnapshots(horizon.Panel): name = _("Share Group Snapshots") slug = 'share_group_snapshots' permissions = ( 'openstack.services.share', ) dashboard.Admin.register(ShareGroupSnapshots) manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/tables.py000066400000000000000000000107601323215354300270620ustar00rootroot00000000000000# Copyright 2017 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 django.core.urlresolvers import reverse from django.template.defaultfilters import title # noqa from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import tables from horizon.utils import filters from manila_ui.api import manila class ShareGroupSnapshotShareGroupNameColumn(tables.Column): def get_link_url(self, snapshot): return reverse(self.link, args=(snapshot.share_group_id,)) class DeleteShareGroupSnapshot(tables.DeleteAction): @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Group Snapshot", u"Delete Share Group Snapshots", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Group Snapshot", u"Deleted Share Group Snapshots", count ) def delete(self, request, obj_id): obj = self.table.get_object_by_id(obj_id) name = self.table.get_object_display(obj) try: manila.share_group_snapshot_delete(request, obj_id) except Exception: msg = _('Unable to delete share group snapshot "%s". ' 'One or more share groups depend on it.') exceptions.check_message(["snapshots", "dependent"], msg % name) raise def allowed(self, request, snapshot=None): if snapshot: return snapshot.status.lower() in ('available', 'error') return True class ResetShareGroupSnapshotStatus(tables.LinkAction): name = "reset_share_group_snapshot_status" verbose_name = _("Reset status") url = "horizon:admin:share_group_snapshots:reset_status" classes = ("ajax-modal", "btn-create") def allowed(self, request, share_group=None): return True class UpdateShareGroupSnapshotRow(tables.Row): ajax = True def get_data(self, request, share_group_snapshot_id): snapshot = manila.share_group_snapshot_get( request, share_group_snapshot_id) if not snapshot.name: snapshot.name = share_group_snapshot_id return snapshot class ShareGroupSnapshotsTable(tables.DataTable): STATUS_CHOICES = ( ("available", True), ("creating", None), ("error", False), ) STATUS_DISPLAY_CHOICES = ( ("available", pgettext_lazy("Current status of snapshot", u"Available")), ("creating", pgettext_lazy("Current status of snapshot", u"Creating")), ("error", pgettext_lazy("Current status of snapshot", u"Error")), ) name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:admin:share_group_snapshots:detail") description = tables.Column( "description", verbose_name=_("Description"), truncate=40) created_at = tables.Column( "created_at", verbose_name=_("Created at"), filters=( filters.parse_isotime, )) status = tables.Column( "status", filters=(title,), verbose_name=_("Status"), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES) source = ShareGroupSnapshotShareGroupNameColumn( "share_group", verbose_name=_("Source"), link="horizon:admin:share_groups:detail") def get_object_display(self, obj): return obj.name class Meta(object): name = "share_group_snapshots" verbose_name = _("Share Group Snapshots") status_columns = ["status"] row_class = UpdateShareGroupSnapshotRow table_actions = ( tables.NameFilterAction, DeleteShareGroupSnapshot, ) row_actions = ( ResetShareGroupSnapshotStatus, DeleteShareGroupSnapshot, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/tabs.py000066400000000000000000000022731323215354300265410ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareGroupSnapshotOverviewTab(tabs.Tab): name = _("Share Group Snapshot Overview") slug = "share_group_snapshot_overview_tab" template_name = "admin/share_group_snapshots/_detail.html" def get_context_data(self, request): return {"share_group_snapshot": self.tab_group.kwargs[ "share_group_snapshot"]} class ShareGroupSnapshotDetailTabs(tabs.TabGroup): slug = "share_group_snapshot_details" tabs = ( ShareGroupSnapshotOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/templates/000077500000000000000000000000001323215354300272305ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/templates/share_group_snapshots/000077500000000000000000000000001323215354300336505ustar00rootroot00000000000000_detail.html000066400000000000000000000016011323215354300360560ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/templates/share_group_snapshots{% load i18n sizeformat parse_date %}

{% trans "Share Group Snapshot Overview" %}


{% trans "Name" %}
{{ share_group_snapshot.name }}
{% trans "ID" %}
{{ share_group_snapshot.id }}
{% url 'horizon:admin:share_groups:detail' share_group_snapshot.share_group_id as sg_url %}
{% trans "Source Share Group" %}
{{ share_group_snapshot.sg_name_or_id }}
{% if share_group_snapshot.description %}
{% trans "Description" %}
{{ share_group_snapshot.description }}
{% endif %}
{% trans "Status" %}
{{ share_group_snapshot.status|capfirst }}
{% trans "Created" %}
{{ share_group_snapshot.created_at|parse_date }}
_reset_status.html000066400000000000000000000003101323215354300373350ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/templates/share_group_snapshots{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

"Reset status of '{{ share_group_snapshot_name }}' share group snapshot."

{% endblock %} detail.html000066400000000000000000000003521323215354300357210ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/templates/share_group_snapshots{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Group Snapshot Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} index.html000066400000000000000000000003651323215354300355720ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/templates/share_group_snapshots{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Group Snapshots" %}{% endblock %} {% block main %}
{{ share_group_snapshots_table.render }}
{% endblock %} reset_status.html000066400000000000000000000003351323215354300372050ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/templates/share_group_snapshots{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Reset Share Group Snapshot Status" %}{% endblock %} {% block main %} {% include 'admin/share_group_snapshots/_reset_status.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/urls.py000066400000000000000000000023461323215354300265760ustar00rootroot00000000000000# Copyright 2017 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 django.conf import urls from manila_ui.dashboards.admin.share_group_snapshots import views from manila_ui import features if features.is_share_groups_enabled(): urlpatterns = [ urls.url( r'^$', views.ShareGroupSnapshotsView.as_view(), name='index'), urls.url( r'^(?P[^/]+)/$', views.ShareGroupSnapshotDetailView.as_view(), name='detail'), urls.url( r'^(?P[^/]+)/reset_status$', views.ResetShareGroupSnapshotStatusView.as_view(), name='reset_status'), ] manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_snapshots/views.py000066400000000000000000000131541323215354300267450ustar00rootroot00000000000000# Copyright 2017 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. """ Admin views for managing share group snapshots. """ from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon import tabs from horizon.utils import memoized from manila_ui.api import manila import manila_ui.dashboards.admin.share_group_snapshots.forms as sgs_forms import manila_ui.dashboards.admin.share_group_snapshots.tables as sgs_tables import manila_ui.dashboards.admin.share_group_snapshots.tabs as sgs_tabs class ShareGroupSnapshotsView(tables.MultiTableView): table_classes = ( sgs_tables.ShareGroupSnapshotsTable, ) template_name = "admin/share_group_snapshots/index.html" page_title = _("Share Group Snapshots") @memoized.memoized_method def get_share_group_snapshots_data(self): share_group_snapshots = [] try: share_group_snapshots = manila.share_group_snapshot_list( self.request, search_opts={'all_tenants': True}) share_groups = manila.share_group_list(self.request) sg_names = dict([(sg.id, sg.name or sg.id) for sg in share_groups]) for snapshot in share_group_snapshots: snapshot.share_group = sg_names.get(snapshot.share_group_id) except Exception: msg = _("Unable to retrieve share group snapshot list.") exceptions.handle(self.request, msg) return share_group_snapshots class ShareGroupSnapshotDetailView(tabs.TabView): tab_group_class = sgs_tabs.ShareGroupSnapshotDetailTabs template_name = "admin/share_group_snapshots/detail.html" redirect_url = reverse_lazy("horizon:admin:share_group_snapshots:index") def get_context_data(self, **kwargs): context = super(ShareGroupSnapshotDetailView, self).get_context_data( **kwargs) snapshot = self.get_data() snapshot_display_name = snapshot.name or snapshot.id context["snapshot"] = snapshot context["snapshot_display_name"] = snapshot_display_name context["page_title"] = _( "Share Group Snapshot Details: %(sgs_display_name)s") % ( {'sgs_display_name': snapshot_display_name}) return context @memoized.memoized_method def get_data(self): try: share_group_snapshot = manila.share_group_snapshot_get( self.request, self.kwargs['share_group_snapshot_id']) sg = manila.share_group_get( self.request, share_group_snapshot.share_group_id) share_group_snapshot.sg_name_or_id = sg.name or sg.id except Exception: exceptions.handle( self.request, _('Unable to retrieve share group snapshot details.'), redirect=self.redirect_url) return share_group_snapshot def get_tabs(self, request, *args, **kwargs): return self.tab_group_class( request, share_group_snapshot=self.get_data(), **kwargs) class ResetShareGroupSnapshotStatusView(forms.ModalFormView): form_class = sgs_forms.ResetShareGroupSnapshotStatusForm form_id = "reset_share_group_snapshot_status" template_name = 'admin/share_group_snapshots/reset_status.html' modal_header = _("Reset Status") modal_id = "reset_share_group_snapshot_status_modal" submit_label = _("Reset status") submit_url = "horizon:admin:share_group_snapshots:reset_status" success_url = reverse_lazy("horizon:admin:share_group_snapshots:index") page_title = _("Reset Share Group Snapshot Status") def get_object(self): if not hasattr(self, "_object"): s_id = self.kwargs["share_group_snapshot_id"] try: self._object = manila.share_group_snapshot_get( self.request, s_id) except Exception: msg = _("Unable to retrieve share group snapshot '%s'.") % s_id url = reverse('horizon:admin:share_group_snapshots:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) sgs = self.get_object() context['share_group_snapshot_id'] = self.kwargs[ 'share_group_snapshot_id'] context['share_group_snapshot_name'] = sgs.name or sgs.id context['share_group_snapshot_status'] = sgs.status context['share_group_id'] = sgs.share_group_id context['submit_url'] = reverse( self.submit_url, args=(context['share_group_snapshot_id'], )) return context def get_initial(self): sgs = self.get_object() return { "share_group_snapshot_id": self.kwargs["share_group_snapshot_id"], "share_group_snapshot_name": sgs.name or sgs.id, "share_group_snapshot_status": sgs.status, "share_group_id": sgs.share_group_id, } manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/000077500000000000000000000000001323215354300243545ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/__init__.py000066400000000000000000000000001323215354300264530ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/forms.py000066400000000000000000000130501323215354300260530ustar00rootroot00000000000000# Copyright 2017 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 django.conf import settings from django.forms import ValidationError # noqa from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from manila_ui.api import manila from manila_ui.dashboards import utils SGT_GROUP_SPECS_FORM_ATTRS = { "rows": 5, "cols": 40, "style": "height: 135px; width: 100%;", # in case 'rows' not picked up } class CreateShareGroupTypeForm(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Name"), required=True) group_specs = forms.CharField( required=False, label=_("Group specs"), widget=forms.widgets.Textarea(attrs=SGT_GROUP_SPECS_FORM_ATTRS)) share_types = forms.MultipleChoiceField( label=_("Share Types"), required=True, widget=forms.SelectMultiple(attrs={ "style": "height: 155px;", }), error_messages={ 'required': _("At least one share type must be specified.") }) is_public = forms.BooleanField( label=_("Public"), required=False, initial=True, help_text=("Defines whether this share group type is available for " "all or not. List of allowed tenants should be set " "separately.")) def __init__(self, request, *args, **kwargs): super(self.__class__, self).__init__(request, *args, **kwargs) manila_features = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {}) self.enable_public_share_group_type_creation = manila_features.get( 'enable_public_share_group_type_creation', True) if not self.enable_public_share_group_type_creation: self.fields.pop('is_public') share_type_choices = manila.share_type_list(request) self.fields['share_types'].choices = [ (choice.id, choice.name) for choice in share_type_choices] def clean(self): cleaned_data = super(CreateShareGroupTypeForm, self).clean() return cleaned_data def handle(self, request, data): try: set_dict, unset_list = utils.parse_str_meta(data['group_specs']) if unset_list: msg = _("Expected only pairs of key=value.") raise ValidationError(message=msg) is_public = ( self.enable_public_share_group_type_creation and data["is_public"]) share_group_type = manila.share_group_type_create( request, data["name"], share_types=data['share_types'], is_public=is_public) if set_dict: manila.share_group_type_set_specs( request, share_group_type.id, set_dict) msg = _("Successfully created share group type: " "%s") % share_group_type.name messages.success(request, msg) return True except ValidationError as e: # handle error without losing dialog self.api_error(e.messages[0]) return False except Exception: exceptions.handle(request, _('Unable to create share group type.')) return False class UpdateShareGroupTypeForm(forms.SelfHandlingForm): def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) # NOTE(vponomaryov): parse existing group specs # to str view for textarea html element es_str = "" for k, v in self.initial["group_specs"].items(): es_str += "%s=%s\r\n" % (k, v) self.initial["group_specs"] = es_str group_specs = forms.CharField( required=False, label=_("Group specs"), widget=forms.widgets.Textarea(attrs=SGT_GROUP_SPECS_FORM_ATTRS)) def handle(self, request, data): try: set_dict, unset_list = utils.parse_str_meta(data['group_specs']) if set_dict: manila.share_group_type_set_specs( request, self.initial["id"], set_dict) if unset_list: get = manila.share_group_type_get_specs( request, self.initial["id"]) # NOTE(vponomaryov): skip keys that are already unset to_unset = set(unset_list).intersection(set(get.keys())) if to_unset: manila.share_group_type_unset_specs( request, self.initial["id"], to_unset) msg = _( "Successfully updated group specs for share group type '%s'.") msg = msg % self.initial['name'] messages.success(request, msg) return True except ValidationError as e: # handle error without losing dialog self.api_error(e.messages[0]) return False except Exception: msg = _("Unable to update group_specs for share group type.") exceptions.handle(request, msg) return False manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/panel.py000066400000000000000000000017131323215354300260270ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class ShareGroupTypes(horizon.Panel): name = _("Share Group Types") slug = 'share_group_types' permissions = ( 'openstack.services.share', ) dashboard.Admin.register(ShareGroupTypes) manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/tables.py000066400000000000000000000070551323215354300262070ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import tables import six from manila_ui.api import manila class CreateShareGroupType(tables.LinkAction): name = "create" verbose_name = _("Create Share Group Type") url = "horizon:admin:share_group_types:create" classes = ("ajax-modal", "btn-create") icon = "plus" class DeleteShareGroupType(tables.DeleteAction): @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Group Type", u"Delete Share Group Types", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Group Type", u"Deleted Share Group Types", count ) def delete(self, request, obj_id): manila.share_group_type_delete(request, obj_id) class ManageShareGroupTypeAccess(tables.LinkAction): name = "manage" verbose_name = _("Manage Share Group Type Access") url = "horizon:admin:share_group_types:manage_access" classes = ("ajax-modal", "btn-create") def allowed(self, request, obj_id): sgt = manila.share_group_type_get(request, obj_id) # Enable it only for private share group types return not sgt.is_public def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None) return {"project_id": project_id} class UpdateShareGroupType(tables.LinkAction): name = "update share group type" verbose_name = _("Update Share group Type") url = "horizon:admin:share_group_types:update" classes = ("ajax-modal", "btn-create") def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None) return {"project_id": project_id} class ShareGroupTypesTable(tables.DataTable): name = tables.WrappingColumn("name", verbose_name=_("Name")) group_specs = tables.Column("group_specs", verbose_name=_("Group specs")) share_types = tables.Column("share_types", verbose_name=_("Share types")) visibility = tables.Column( "is_public", verbose_name=_("Visibility"), filters=(lambda d: 'public' if d is True else 'private', ), ) def get_object_display(self, share_group_type): return share_group_type.name def get_object_id(self, share_group_type): return six.text_type(share_group_type.id) class Meta(object): name = "share_group_types" verbose_name = _("Share Group Types") table_actions = ( tables.NameFilterAction, CreateShareGroupType, DeleteShareGroupType, ) row_actions = ( UpdateShareGroupType, ManageShareGroupTypeAccess, DeleteShareGroupType, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/templates/000077500000000000000000000000001323215354300263525ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/templates/share_group_types/000077500000000000000000000000001323215354300321145ustar00rootroot00000000000000_create.html000066400000000000000000000007021323215354300343240ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/templates/share_group_types{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "The share group type defines the characteristics of a share group backend." %}

Extra specs field:
{% trans "One line - one action. Empty strings will be ignored." %}
{% trans "To add group-specs use:" %}

key=value

{% endblock %} _manage_access.html000066400000000000000000000032671323215354300356430ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/templates/share_group_types{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block form_id %}{% endblock %} {% block form_action %}{% url 'horizon:admin:share_group_types:manage_access' share_group_type.id %}{% endblock %} {% block modal_id %}manage_share_group_type_access_modal{% endblock %} {% block modal-header %}{% trans "Manage Share Group Type Access" %}{% endblock %} {% block modal-body %}
{% include "horizon/common/_form_fields.html" %}

{% trans "Description" %}:

{% blocktrans %} Placeholder for description of share group type access managing form. {% endblocktrans %}

{% include "horizon/common/_form_fields.html" %}
{{ step.get_help_text }}
{% endblock %} {% block modal-footer %} {% trans "Cancel" %} {% endblock %} _update.html000066400000000000000000000010541323215354300343440ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/templates/share_group_types{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "Here can be modified group-specs for share group type." %}
{% trans "One line - one action. Empty strings will be ignored." %}
{% trans "To add group-specs use:" %}

key=value
{% trans "To unset group-specs use:" %}
key
{% trans "All pairs that are in field for left are set for this share group type." %}

{% endblock %} create.html000066400000000000000000000003111323215354300341610ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/templates/share_group_types{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Group Share Type" %}{% endblock %} {% block main %} {% include 'admin/share_group_types/_create.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/templates/share_group_types/index.html000066400000000000000000000003551323215354300341140ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Group Types" %}{% endblock %} {% block main %}
{{ share_group_types_table.render }}
{% endblock %} manage_access.html000066400000000000000000000003271323215354300354760ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/templates/share_group_types{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Manage Share Group Type Access" %}{% endblock %} {% block main %} {% include 'admin/share_group_types/_manage_access.html' %} {% endblock %} update.html000066400000000000000000000003111323215354300342000ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/templates/share_group_types{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Update Share Group Type" %}{% endblock %} {% block main %} {% include 'admin/share_group_types/_update.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/urls.py000066400000000000000000000025241323215354300257160ustar00rootroot00000000000000# Copyright 2017 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 django.conf import urls from manila_ui.dashboards.admin.share_group_types import views from manila_ui import features if features.is_share_groups_enabled(): urlpatterns = [ urls.url( r'^$', views.ShareGroupTypesView.as_view(), name='index'), urls.url( r'^create$', views.CreateShareGroupTypeView.as_view(), name='create'), urls.url( r'^(?P[^/]+)/update$', views.UpdateShareGroupTypeView.as_view(), name='update'), urls.url( r'^(?P[^/]+)/manage_access$', views.ManageShareGroupTypeAccessView.as_view(), name='manage_access'), ] manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/views.py000066400000000000000000000115431323215354300260670ustar00rootroot00000000000000# Copyright 2017 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. """ Admin views for managing share group types. """ from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon.utils import memoized from horizon import workflows from manila_ui.api import manila from manila_ui.dashboards.admin.share_group_types import forms as sgt_forms from manila_ui.dashboards.admin.share_group_types import tables as sgt_tables import manila_ui.dashboards.admin.share_group_types.workflows as sgt_workflows from manila_ui.dashboards import utils as common_utils class ShareGroupTypesView(tables.MultiTableView): table_classes = ( sgt_tables.ShareGroupTypesTable, ) template_name = "admin/share_group_types/index.html" page_title = _("Share Group Types") @memoized.memoized_method def get_share_group_types_data(self): try: share_group_types = manila.share_group_type_list(self.request) except Exception: exceptions.handle( self.request, _('Unable to retrieve share group types.')) return [] share_types = manila.share_type_list(self.request) st_mapping = {} for st in share_types: st_mapping[st.id] = st.name for sgt in share_group_types: sgt.group_specs = common_utils.metadata_to_str( sgt.group_specs, 8, 45) sgt.share_types = ", ".join( [st_mapping[st] for st in sgt.share_types]) return share_group_types class CreateShareGroupTypeView(forms.ModalFormView): form_class = sgt_forms.CreateShareGroupTypeForm form_id = "create_share_group_type" template_name = 'admin/share_group_types/create.html' modal_header = _("Create Share Group Type") modal_id = "create_share_group_type_modal" submit_label = _("Create") submit_url = reverse_lazy("horizon:admin:share_group_types:create") success_url = reverse_lazy("horizon:admin:share_group_types:index") page_title = _("Create Share Group Type") class ManageShareGroupTypeAccessView(workflows.WorkflowView): workflow_class = sgt_workflows.ManageShareGroupTypeAccessWorkflow template_name = "admin/share_group_types/manage_access.html" success_url = 'horizon:admin:share_group_types:index' page_title = _("Manage Share Group Type Access") def get_initial(self): return {'id': self.kwargs["share_group_type_id"]} def get_context_data(self, **kwargs): context = super(ManageShareGroupTypeAccessView, self).get_context_data( **kwargs) context['id'] = self.kwargs['share_group_type_id'] return context class UpdateShareGroupTypeView(forms.ModalFormView): form_class = sgt_forms.UpdateShareGroupTypeForm form_id = "update_share_group_type" template_name = "admin/share_group_types/update.html" modal_header = _("Update Share Group Type") modal_id = "update_share_group_type_modal" submit_label = _("Update") submit_url = "horizon:admin:share_group_types:update" success_url = reverse_lazy("horizon:admin:share_group_types:index") page_title = _("Update Share Group Type") def get_object(self): if not hasattr(self, "_object"): sgt_id = self.kwargs["share_group_type_id"] try: self._object = manila.share_group_type_get( self.request, sgt_id) except Exception: msg = _("Unable to retrieve share_gruop_type.") url = reverse("horizon:admin:share_group_types:index") exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(UpdateShareGroupTypeView, self).get_context_data( **kwargs) args = ( self.get_object().id, ) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): share_group_type = self.get_object() return { "id": self.kwargs["share_group_type_id"], "name": share_group_type.name, "group_specs": share_group_type.group_specs, } manila-ui-2.13.0/manila_ui/dashboards/admin/share_group_types/workflows.py000066400000000000000000000110171323215354300267630ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import workflows from openstack_dashboard.api import keystone from manila_ui.api import manila class AddProjectAction(workflows.MembershipAction): def __init__(self, request, *args, **kwargs): super(AddProjectAction, self).__init__(request, *args, **kwargs) default_role_field_name = self.get_default_role_field_name() self.fields[default_role_field_name] = forms.CharField(required=False) self.fields[default_role_field_name].initial = 'member' field_name = self.get_member_field_name('member') self.fields[field_name] = forms.MultipleChoiceField(required=False) share_group_type_id = self.initial['id'] # Get list of existing projects try: projects, __ = keystone.tenant_list(request) except Exception: err_msg = _('Unable to get list of projects.') exceptions.handle(request, err_msg) # Get list of projects with access to this Share Group Type try: share_group_type = manila.share_group_type_get( request, share_group_type_id) self.share_group_type_name = share_group_type.name projects_initial = manila.share_group_type_access_list( request, share_group_type) except Exception: err_msg = _( 'Unable to get information about share group type access.') exceptions.handle(request, err_msg) self.fields[field_name].choices = [ (project.id, project.name or project.id) for project in projects] self.fields[field_name].initial = [ pr.project_id for pr in projects_initial] self.projects_initial = set(self.fields[field_name].initial) class Meta(object): name = _("Projects with access to share group type") slug = "update_members" def handle(self, request, context): context.update({ 'name': self.share_group_type_name, 'projects_add': self.projects_allow - self.projects_initial, 'projects_remove': self.projects_initial - self.projects_allow, }) return context def clean(self): cleaned_data = super(AddProjectAction, self).clean() self.projects_allow = set( cleaned_data[self.get_member_field_name('member')]) return cleaned_data class AddProjectStep(workflows.UpdateMembersStep): action_class = AddProjectAction available_list_title = _("Available projects") help_text = _("Allow project access to share group type.") members_list_title = _("Selected projects") no_available_text = _("No projects found.") no_members_text = _("No projects selected.") depends_on = ("id", ) show_roles = False class ManageShareGroupTypeAccessWorkflow(workflows.Workflow): slug = "manage_share_group_type_access" name = _("Manage Share Group Type Access") finalize_button_name = _("Manage Share Group Type Access") success_message = _('Updated access for share group type "%s".') failure_message = _('Unable to update access for share group type "%s".') success_url = 'horizon:admin:share_group_types:index' default_steps = (AddProjectStep, ) def format_status_message(self, message): return message % self.context['name'] def handle(self, request, context): try: for project in self.context['projects_remove']: manila.share_group_type_access_remove( request, self.context['id'], project) for project in self.context['projects_add']: manila.share_group_type_access_add( request, self.context['id'], project) return True except Exception: exceptions.handle(request, _('Unable to update share group type.')) return False manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/000077500000000000000000000000001323215354300233135ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/__init__.py000066400000000000000000000000001323215354300254120ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/forms.py000066400000000000000000000036521323215354300250210ustar00rootroot00000000000000# Copyright (c) 2017 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 django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from manila_ui.api import manila class ResetShareGroupStatusForm(forms.SelfHandlingForm): status = forms.ChoiceField( label=_("Status"), required=True, choices=( ('available', 'available'), ('error', 'error'), ) ) def handle(self, request, data): sg_id = self.initial['share_group_id'] try: manila.share_group_reset_state(request, sg_id, data["status"]) message = _( "Reseting share group ('%(id)s') status from '%(from)s' " "to '%(to)s'.") % { "id": (self.initial['share_group_name'] or self.initial['share_group_id']), "from": self.initial['share_group_status'], "to": data["status"]} messages.success(request, message) return True except Exception: redirect = reverse("horizon:admin:share_groups:index") exceptions.handle( request, _("Unable to reset status of share group '%s'.") % sg_id, redirect=redirect) return False manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/panel.py000066400000000000000000000016711323215354300247710ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class ShareGroups(horizon.Panel): name = _("Share Groups") slug = 'share_groups' permissions = ( 'openstack.services.share', ) dashboard.Admin.register(ShareGroups) manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/tables.py000066400000000000000000000075131323215354300251450ustar00rootroot00000000000000# Copyright 2017 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 django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import tables import six from manila_ui.api import manila class DeleteShareGroup(tables.DeleteAction): @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Group", u"Delete Share Groups", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Group", u"Deleted Share Groups", count ) def delete(self, request, obj_id): manila.share_group_delete(request, obj_id) class ResetShareGroupStatus(tables.LinkAction): name = "reset_share_group_status" verbose_name = _("Reset status") url = "horizon:admin:share_groups:reset_status" classes = ("ajax-modal", "btn-create") def allowed(self, request, share_group=None): return True class ShareGroupsTable(tables.DataTable): def get_share_network_link(share_group): if getattr(share_group, 'share_network_id', None): return reverse("horizon:admin:share_networks:share_network_detail", args=(share_group.share_network_id,)) else: return None def get_share_server_link(share_group): if getattr(share_group, 'share_server_id', None): return reverse("horizon:admin:share_servers:share_server_detail", args=(share_group.share_server_id,)) else: return None STATUS_CHOICES = ( ("available", True), ("creating", None), ("deleting", None), ("error", False), ("error_deleting", False), ) STATUS_DISPLAY_CHOICES = ( ("available", u"Available"), ("creating", u"Creating"), ("deleting", u"Deleting"), ("error", u"Error"), ("error_deleting", u"Error deleting"), ) name = tables.Column( "name", verbose_name=_("Name"), link="horizon:admin:share_groups:detail") host = tables.Column("host", verbose_name=_("Host")) status = tables.Column( "status", verbose_name=_("Status"), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES, ) availability_zone = tables.Column( "availability_zone", verbose_name=_("Availability Zone")) share_network_id = tables.Column( "share_network_id", verbose_name=_("Share Network"), link=get_share_network_link) share_server_id = tables.Column( "share_server_id", verbose_name=_("Share Server"), link=get_share_server_link) def get_object_display(self, share_group): return six.text_type(share_group.id) def get_object_id(self, share_group): return six.text_type(share_group.id) class Meta(object): name = "share_groups" verbose_name = _("Share Groups") status_columns = ("status", ) table_actions = ( tables.NameFilterAction, DeleteShareGroup, ) row_actions = ( ResetShareGroupStatus, DeleteShareGroup, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/tabs.py000066400000000000000000000021401323215354300246130ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareGroupOverviewTab(tabs.Tab): name = _("Share Group Overview") slug = "share_group_overview_tab" template_name = "admin/share_groups/_detail.html" def get_context_data(self, request): return {"share_group": self.tab_group.kwargs["share_group"]} class ShareGroupDetailTabs(tabs.TabGroup): slug = "share_group_details" tabs = ( ShareGroupOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/templates/000077500000000000000000000000001323215354300253115ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/templates/share_groups/000077500000000000000000000000001323215354300300125ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/templates/share_groups/_detail.html000066400000000000000000000045321323215354300323050ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Group Overview" %}


{% trans "ID" %}
{{ share_group.id }}
{% trans "Name" %}
{{ share_group.name }}
{% trans "Description" %}
{{ share_group.description }}
{% trans "Status" %}
{{ share_group.status|capfirst }}
{% trans "Created" %}
{{ share_group.created_at|parse_date }}
{% trans "Host" %}
{{ share_group.host}}
{% if share_group.source_share_group_snapshot_id %}
{% trans "Source share group snapshot" %}
{{ share_group.source_share_group_snapshot_id}}
{% endif %}
{% trans "Share Group Type" %}
{{ share_group.share_group_type_id}}
{% if share_group.availability_zone %}
{% trans "Availability Zone" %}
{{ share_group.availability_zone }}
{% endif %} {% if share_group.share_network_id %}
{% trans "Share network" %}
{% url 'horizon:admin:share_networks:share_network_detail' share_group.share_network_id as sn_url%}
{{ share_group.share_network_id }}
{% endif %} {% if share_group.share_server_id %}
{% trans "Share server" %}
{% url 'horizon:admin:share_servers:share_server_detail' share_group.share_server_id as share_server_url%}
{{ share_group.share_server_id }}
{% endif %} {% if share_group.share_types %}
{% trans "Share Types" %}
{% for st in share_group.share_types %}

Share Type Name: {{ st.name }}
Share Type Visibility: {% if st.is_public %}Public{% else %}Private{% endif %}
Network handling enabled: {{ st.dhss }}

{% endfor %} {% endif %} {% if share_group.members %}
{% trans "Shares" %}
{% for m in share_group.members %} {% url 'horizon:admin:shares:detail' m.id as share_url%}
{% endfor %} {% endif %}
manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/templates/share_groups/_reset_status.html000066400000000000000000000002661323215354300335700ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

"Reset status of '{{ share_group_name }}' share group."

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/templates/share_groups/detail.html000066400000000000000000000003411323215354300321400ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Group Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/templates/share_groups/index.html000066400000000000000000000003431323215354300320070ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Groups" %}{% endblock %} {% block main %}
{{ share_groups_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/templates/share_groups/reset_status.html000066400000000000000000000003131323215354300334220ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Reset Share Group Status" %}{% endblock %} {% block main %} {% include 'admin/share_groups/_reset_status.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/urls.py000066400000000000000000000022621323215354300246540ustar00rootroot00000000000000# Copyright 2017 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 django.conf import urls from manila_ui.dashboards.admin.share_groups import views from manila_ui import features if features.is_share_groups_enabled(): urlpatterns = [ urls.url( r'^$', views.ShareGroupsView.as_view(), name='index'), urls.url( r'^(?P[^/]+)/$', views.ShareGroupDetailView.as_view(), name='detail'), urls.url( r'^(?P[^/]+)/reset_status$', views.ResetShareGroupStatusView.as_view(), name='reset_status'), ] manila-ui-2.13.0/manila_ui/dashboards/admin/share_groups/views.py000066400000000000000000000120121323215354300250160ustar00rootroot00000000000000# Copyright 2017 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. """ Admin views for managing share groups. """ from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon import tabs from horizon.utils import memoized from manila_ui.api import manila from manila_ui.dashboards.admin.share_groups import forms as sg_forms from manila_ui.dashboards.admin.share_groups import tables as sg_tables from manila_ui.dashboards.admin.share_groups import tabs as sg_tabs class ShareGroupsView(tables.MultiTableView): table_classes = ( sg_tables.ShareGroupsTable, ) template_name = "admin/share_groups/index.html" page_title = _("Share Groups") @memoized.memoized_method def get_share_groups_data(self): try: share_groups = manila.share_group_list( self.request, detailed=True) except Exception: share_groups = [] exceptions.handle( self.request, _("Unable to retrieve share groups.")) return share_groups class ShareGroupDetailView(tabs.TabView): tab_group_class = sg_tabs.ShareGroupDetailTabs template_name = 'admin/share_groups/detail.html' def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) share_group = self.get_data() context["share_group"] = share_group context["page_title"] = ( _("Share Group Details: %s") % share_group.id) return context @memoized.memoized_method def get_data(self): try: share_group_id = self.kwargs['share_group_id'] share_group = manila.share_group_get(self.request, share_group_id) members = manila.share_list( self.request, search_opts={"share_group_id": share_group_id}) share_group.members = members share_types = manila.share_type_list(self.request) share_group.share_types = [ {"id": st.id, "name": st.name, "is_public": getattr(st, 'share_type_access:is_public'), "dhss": st.extra_specs.get('driver_handles_share_servers')} for st in share_types if st.id in share_group.share_types ] return share_group except Exception: redirect = reverse('horizon:admin:share_groups:index') exceptions.handle( self.request, _('Unable to retrieve share group details.'), redirect=redirect) def get_tabs(self, request, *args, **kwargs): share_group = self.get_data() return self.tab_group_class(request, share_group=share_group, **kwargs) class ResetShareGroupStatusView(forms.ModalFormView): form_class = sg_forms.ResetShareGroupStatusForm form_id = "reset_share_group_status" template_name = 'admin/share_groups/reset_status.html' modal_header = _("Reset Status") modal_id = "reset_share_group_status_modal" submit_label = _("Reset status") submit_url = "horizon:admin:share_groups:reset_status" success_url = reverse_lazy("horizon:admin:share_groups:index") page_title = _("Reset Share Group Status") def get_object(self): if not hasattr(self, "_object"): sg_id = self.kwargs["share_group_id"] try: self._object = manila.share_group_get(self.request, sg_id) except Exception: msg = _("Unable to retrieve share group '%s'.") % sg_id url = reverse('horizon:admin:share_groups:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) sg = self.get_object() context['share_group_id'] = self.kwargs['share_group_id'] context['share_group_name'] = sg.name or sg.id context['share_group_status'] = sg.status context['submit_url'] = reverse( self.submit_url, args=(context['share_group_id'], )) return context def get_initial(self): sg = self.get_object() return { "share_group_id": self.kwargs["share_group_id"], "share_group_name": sg.name or sg.id, "share_group_status": sg.status, } manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/000077500000000000000000000000001323215354300237635ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/__init__.py000066400000000000000000000000001323215354300260620ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/panel.py000066400000000000000000000016561323215354300254440ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class ShareInstances(horizon.Panel): name = _("Share Instances") slug = 'share_instances' permissions = ( 'openstack.services.share', ) dashboard.Admin.register(ShareInstances) manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/tables.py000066400000000000000000000063101323215354300256070ustar00rootroot00000000000000# 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 django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import tables import six class ShareInstancesTable(tables.DataTable): STATUS_CHOICES = ( ("available", True), ("creating", None), ("deleting", None), ("error", False), ("error_deleting", False), ) STATUS_DISPLAY_CHOICES = ( ("available", u"Available"), ("creating", u"Creating"), ("deleting", u"Deleting"), ("error", u"Error"), ("error_deleting", u"Error deleting"), ) uuid = tables.Column( "id", verbose_name=_("ID"), link="horizon:admin:share_instances:share_instance_detail") host = tables.Column("host", verbose_name=_("Host")) status = tables.Column( "status", verbose_name=_("Status"), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES) availability_zone = tables.Column( "availability_zone", verbose_name=_("Availability Zone")) class Meta(object): name = "share_instances" verbose_name = _("Share Instances") status_columns = ("status", ) table_actions = ( tables.NameFilterAction,) multi_select = False def get_share_network_link(share_instance): if getattr(share_instance, 'share_network_id', None): return reverse("horizon:admin:share_networks:share_network_detail", args=(share_instance.share_network_id,)) else: return None def get_share_server_link(share_instance): if getattr(share_instance, 'share_server_id', None): return reverse("horizon:admin:share_servers:share_server_detail", args=(share_instance.share_server_id,)) else: return None def get_share_link(share_instance): if getattr(share_instance, 'share_id', None): return reverse("horizon:admin:shares:detail", args=(share_instance.share_id,)) else: return None share_net_id = tables.Column( "share_network_id", verbose_name=_("Share Network"), link=get_share_network_link) share_server_id = tables.Column( "share_server_id", verbose_name=_("Share Server Id"), link=get_share_server_link) share_id = tables.Column( "share_id", verbose_name=_("Share ID"), link=get_share_link) def get_object_display(self, share_instance): return six.text_type(share_instance.id) def get_object_id(self, share_instance): return six.text_type(share_instance.id) manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/tabs.py000066400000000000000000000021441323215354300252670ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareInstanceOverviewTab(tabs.Tab): name = _("Share Instance Overview") slug = "share_instance_overview_tab" template_name = "admin/share_instances/_detail.html" def get_context_data(self, request): return {"share_instance": self.tab_group.kwargs["share_instance"]} class ShareInstanceDetailTabs(tabs.TabGroup): slug = "share_instance_details" tabs = ( ShareInstanceOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/templates/000077500000000000000000000000001323215354300257615ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/templates/share_instances/000077500000000000000000000000001323215354300311325ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/templates/share_instances/_detail.html000066400000000000000000000037431323215354300334300ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Instance Overview" %}


{% trans "ID" %}
{{ share_instance.id }}
{% trans "Status" %}
{{ share_instance.status|capfirst }}
{% trans "Export locations" %}
{% if share_instance.export_locations %} {% for el in share_instance.export_locations %}

Path:
Preferred: {{ el.preferred }}
{% if el.is_admin_only == True or el.is_admin_only == False %}
Is admin only: {{ el.is_admin_only }}
{% endif %}

{% endfor %} {% endif %}
{% trans "Host" %}
{{ share_instance.host}}
{% trans "Availability Zone" %}
{{ share_instance.availability_zone}}
{% trans "Share ID" %}
{% url 'horizon:admin:shares:detail' share_instance.share_id as share_url %}
{{ share_instance.share_id }}
{% if share_instance.share_network_id %}
{% trans "Share network" %}
{% url 'horizon:admin:share_networks:share_network_detail' share_instance.share_network_id as sn_url%}
{{ share_instance.share_network_id }}
{% endif %} {% if share_instance.share_server_id %}
{% trans "Share server" %}
{% url 'horizon:admin:share_servers:share_server_detail' share_instance.share_server_id as share_server_url%}
{{ share_instance.share_server_id }}
{% endif %}
{% trans "Created" %}
{{ share_instance.created_at|parse_date }}
manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/templates/share_instances/detail.html000066400000000000000000000003441323215354300332630ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Instance Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/templates/share_instances/index.html000066400000000000000000000003511323215354300331260ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Instances" %}{% endblock %} {% block main %}
{{ share_instances_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/urls.py000066400000000000000000000016021323215354300253210ustar00rootroot00000000000000# 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 django.conf import urls from manila_ui.dashboards.admin.share_instances import views urlpatterns = [ urls.url( r'^$', views.ShareInstancesView.as_view(), name='index'), urls.url( r'^(?P[^/]+)$', views.ShareInstanceDetailView.as_view(), name='share_instance_detail'), ] manila-ui-2.13.0/manila_ui/dashboards/admin/share_instances/views.py000066400000000000000000000062761323215354300255050ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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. """ Admin views for managing share instances. """ from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import tables from horizon import tabs from horizon.utils import memoized from manila_ui.api import manila from manila_ui.dashboards.admin.share_instances import tables as si_tables from manila_ui.dashboards.admin.share_instances import tabs as si_tabs from manila_ui.dashboards import utils as ui_utils class ShareInstancesView(tables.MultiTableView): table_classes = ( si_tables.ShareInstancesTable, ) template_name = "admin/share_instances/index.html" page_title = _("Share Instances") @memoized.memoized_method def get_share_instances_data(self): try: share_instances = manila.share_instance_list(self.request) except Exception: share_instances = [] exceptions.handle( self.request, _("Unable to retrieve share instances.")) return share_instances class ShareInstanceDetailView(tabs.TabView): tab_group_class = si_tabs.ShareInstanceDetailTabs template_name = 'admin/share_instances/detail.html' def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) share_instance = self.get_data() context["share_instance"] = share_instance context["page_title"] = ( _("Share Instance Details: %s") % share_instance.id) return context @memoized.memoized_method def get_data(self): try: share_instance_id = self.kwargs['share_instance_id'] share_instance = manila.share_instance_get( self.request, share_instance_id) share_instance.export_locations = ( manila.share_instance_export_location_list( self.request, share_instance_id)) export_locations = [ exp['path'] for exp in share_instance.export_locations ] share_instance.el_size = ui_utils.calculate_longest_str_size( export_locations) return share_instance except Exception: redirect = reverse('horizon:admin:share_instances:index') exceptions.handle( self.request, _('Unable to retrieve share instance details.'), redirect=redirect) def get_tabs(self, request, *args, **kwargs): share_instance = self.get_data() return self.tab_group_class( request, share_instance=share_instance, **kwargs) manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/000077500000000000000000000000001323215354300236505ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/__init__.py000066400000000000000000000000001323215354300257470ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/panel.py000066400000000000000000000016521323215354300253250ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class ShareNetworks(horizon.Panel): name = _("Share Networks") slug = 'share_networks' permissions = ( 'openstack.services.share', ) dashboard.Admin.register(ShareNetworks) manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/tables.py000066400000000000000000000036051323215354300255000ustar00rootroot00000000000000# 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 django.utils.translation import ugettext_lazy as _ from horizon import tables import six import manila_ui.dashboards.project.share_networks.tables as sn_tables class ShareNetworksTable(tables.DataTable): name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:admin:share_networks:share_network_detail") project = tables.Column("project_name", verbose_name=_("Project")) neutron_net = tables.Column("neutron_net", verbose_name=_("Neutron Net")) neutron_subnet = tables.Column( "neutron_subnet", verbose_name=_("Neutron Subnet")) ip_version = tables.Column("ip_version", verbose_name=_("IP Version")) network_type = tables.Column( "network_type", verbose_name=_("Network Type")) segmentation_id = tables.Column( "segmentation_id", verbose_name=_("Segmentation Id")) def get_object_display(self, share_network): return share_network.name or six.text_type(share_network.id) def get_object_id(self, share_network): return six.text_type(share_network.id) class Meta(object): name = "share_networks" verbose_name = _("Share Networks") table_actions = ( tables.NameFilterAction, sn_tables.Delete, ) row_class = sn_tables.UpdateRow row_actions = ( sn_tables.Delete, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/tabs.py000066400000000000000000000021331323215354300251520ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareNetworkOverviewTab(tabs.Tab): name = _("Share Network Overview") slug = "share_network_overview_tab" template_name = "admin/share_networks/_detail.html" def get_context_data(self, request): return {"share_network": self.tab_group.kwargs["share_network"]} class ShareNetworkDetailTabs(tabs.TabGroup): slug = "share_network_details" tabs = ( ShareNetworkOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/templates/000077500000000000000000000000001323215354300256465ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/templates/share_networks/000077500000000000000000000000001323215354300307045ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/templates/share_networks/_detail.html000066400000000000000000000034421323215354300331760ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Network Overview" %}


{% trans "Name" %}
{{ share_network.name }}
{% trans "ID" %}
{{ share_network.id }}
{% if share_network.description %}
{% trans "Description" %}
{{ share_network.description }}
{% endif %} {% if share_network.share_servers %}
{% trans "Share Servers" %}
{% for server in share_network.share_servers %} {% url 'horizon:admin:share_servers:share_server_detail' server.id as server_url %}
{{ server.id }}
{% endfor %} {% endif %}

{% trans "Net Details" %}


{% trans "Network" %}
{% if share_network.neutron_net %}
{{ share_network.neutron_net }}
{% trans "Subnet" %}
{{ share_network.neutron_subnet}}
{% endif %} {% if share_network.nova_net %}
{{ share_network.nova_net }}
{% endif %}

{% trans "Security Services" %}


{% for sec_service in share_network.sec_services %} {% url 'horizon:admin:security_services:security_service_detail' sec_service.id as sec_service_url%}
{% trans "Id" %}
{{ sec_service.id }}
{% trans "Name" %}
{{ sec_service.name }}
{% trans "Type" %}
{{ sec_service.type }}

{% endfor %}
manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/templates/share_networks/detail.html000066400000000000000000000003431323215354300330340ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Network Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/templates/share_networks/index.html000066400000000000000000000003471323215354300327050ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Networks" %}{% endblock %} {% block main %}
{{ share_networks_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/urls.py000066400000000000000000000015751323215354300252170ustar00rootroot00000000000000# 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 django.conf import urls from manila_ui.dashboards.admin.share_networks import views urlpatterns = [ urls.url( r'^$', views.ShareNetworksView.as_view(), name='index'), urls.url( r'^(?P[^/]+)$', views.ShareNetworkDetailView.as_view(), name='share_network_detail'), ] manila-ui-2.13.0/manila_ui/dashboards/admin/share_networks/views.py000066400000000000000000000054151323215354300253640ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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. """ Admin views for managing share networks. """ from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import tables from horizon.utils import memoized from openstack_dashboard.api import base from openstack_dashboard.api import neutron from manila_ui.api import manila from manila_ui.dashboards.admin.share_networks import tables as sn_tables from manila_ui.dashboards.admin.share_networks import tabs as sn_tabs from manila_ui.dashboards.admin import utils from manila_ui.dashboards.project.share_networks import views as p_views class ShareNetworksView(tables.MultiTableView): table_classes = ( sn_tables.ShareNetworksTable, ) template_name = "admin/share_networks/index.html" page_title = _("Share Networks") @memoized.memoized_method def get_share_networks_data(self): try: share_networks = manila.share_network_list( self.request, detailed=True, search_opts={'all_tenants': True}) if base.is_service_enabled(self.request, 'network'): neutron_net_names = dict( (net.id, net.name) for net in neutron.network_list(self.request)) neutron_subnet_names = dict( (net.id, net.name) for net in neutron.subnet_list(self.request)) for sn in share_networks: sn.neutron_net = neutron_net_names.get( sn.neutron_net_id) or sn.neutron_net_id or "-" sn.neutron_subnet = neutron_subnet_names.get( sn.neutron_subnet_id) or sn.neutron_subnet_id or "-" except Exception: share_networks = [] exceptions.handle( self.request, _("Unable to retrieve share networks")) utils.set_project_name_to_objects(self.request, share_networks) return share_networks class ShareNetworkDetailView(p_views.Detail): tab_group_class = sn_tabs.ShareNetworkDetailTabs template_name = "admin/share_networks/detail.html" redirect_url = reverse_lazy("horizon:admin:share_networks:index") manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/000077500000000000000000000000001323215354300234655ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/__init__.py000066400000000000000000000000001323215354300255640ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/panel.py000066400000000000000000000016461323215354300251450ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class ShareServers(horizon.Panel): name = _("Share Servers") slug = 'share_servers' permissions = ( 'openstack.services.share', ) dashboard.Admin.register(ShareServers) manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/tables.py000066400000000000000000000076541323215354300253250ustar00rootroot00000000000000# 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 django.core.urlresolvers import reverse from django.template.defaultfilters import title # noqa from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import tables import six from manila_ui.api import manila class DeleteShareServer(tables.DeleteAction): policy_rules = (("share", "share_server:delete"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Server", u"Delete Share Server", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Server", u"Deleted Share Server", count ) def delete(self, request, obj_id): manila.share_server_delete(request, obj_id) def allowed(self, request, share_serv): if share_serv: share_search_opts = {'share_server_id': share_serv.id} shares_list = manila.share_list( request, search_opts=share_search_opts) if shares_list: return False return share_serv.status not in ("deleting", "creating") return True class UpdateShareServerRow(tables.Row): ajax = True def get_data(self, request, share_serv_id): share_serv = manila.share_server_get(request, share_serv_id) return share_serv class ShareServersTable(tables.DataTable): STATUS_CHOICES = ( ("active", True), ("deleting", None), ("creating", None), ("error", False), ) STATUS_DISPLAY_CHOICES = ( ("in-use", pgettext_lazy("Current status of share server", u"In-use")), ("active", pgettext_lazy("Current status of share server", u"Active")), ("creating", pgettext_lazy("Current status of share server", u"Creating")), ("error", pgettext_lazy("Current status of share server", u"Error")), ) uid = tables.Column( "id", verbose_name=_("Id"), link="horizon:admin:share_servers:share_server_detail") host = tables.Column("host", verbose_name=_("Host")) project = tables.Column("project_name", verbose_name=_("Project")) def get_share_server_link(share_serv): if hasattr(share_serv, 'share_network_id'): return reverse("horizon:admin:share_networks:share_network_detail", args=(share_serv.share_network_id,)) else: return None share_net_name = tables.Column( "share_network_name", verbose_name=_("Share Network"), link=get_share_server_link) status = tables.Column( "status", verbose_name=_("Status"), status=True, filters=(title,), status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES) def get_object_display(self, share_server): return six.text_type(share_server.id) def get_object_id(self, share_server): return six.text_type(share_server.id) class Meta(object): name = "share_servers" status_columns = ["status"] verbose_name = _("Share Server") table_actions = ( tables.NameFilterAction, DeleteShareServer, ) row_class = UpdateShareServerRow row_actions = ( DeleteShareServer, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/tabs.py000066400000000000000000000021301323215354300247640ustar00rootroot00000000000000# Copyright 2014 OpenStack Foundation # # 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareServerOverviewTab(tabs.Tab): name = _("Share Server Overview") slug = "share_server_overview_tab" template_name = "admin/share_servers/_detail.html" def get_context_data(self, request): return {"share_server": self.tab_group.kwargs["share_server"]} class ShareServerDetailTabs(tabs.TabGroup): slug = "share_server_details" tabs = ( ShareServerOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/templates/000077500000000000000000000000001323215354300254635ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/templates/share_servers/000077500000000000000000000000001323215354300303365ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/templates/share_servers/_detail.html000066400000000000000000000024201323215354300326230ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Server Overview" %}


{% trans "ID" %}
{{ share_server.id }}
{% trans "Status" %}
{{ share_server.status|capfirst }}
{% trans "Host" %}
{{ share_server.host}}
{% trans "Share Network" %}
{% if share_server.share_network_id %} {% url 'horizon:admin:share_networks:share_network_detail' share_server.share_network_id as share_net_url %}
{{ share_server.share_network_name }}
{% else %}
{{ share_server.share_network_name }}
{% endif %} {% if share_server.shares_list %}
{% trans "Shares on this server" %}
{% for share in share_server.shares_list %} {% url 'horizon:admin:shares:detail' share.id as share_url %}
{{ share.name_or_id }}
{% endfor %} {% endif %}

{% trans "Specs" %}


{% for key, value in share_server.backend_details.items %}
{{ key }}
{{ value }}
{% endfor %}
manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/templates/share_servers/detail.html000066400000000000000000000003421323215354300324650ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Server Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/templates/share_servers/index.html000066400000000000000000000003451323215354300323350ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Servers" %}{% endblock %} {% block main %}
{{ share_servers_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/urls.py000066400000000000000000000015701323215354300250270ustar00rootroot00000000000000# 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 django.conf import urls from manila_ui.dashboards.admin.share_servers import views urlpatterns = [ urls.url( r'^$', views.ShareServersView.as_view(), name='index'), urls.url( r'^(?P[^/]+)$', views.ShareServerDetailView.as_view(), name='share_server_detail'), ] manila-ui-2.13.0/manila_ui/dashboards/admin/share_servers/views.py000066400000000000000000000067421323215354300252050ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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. """ Admin views for managing share servers. """ from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import tables from horizon import tabs from horizon.utils import memoized from manila_ui.api import manila from manila_ui.dashboards.admin.share_servers import tables as ss_tables from manila_ui.dashboards.admin.share_servers import tabs as ss_tabs from manila_ui.dashboards.admin import utils class ShareServersView(tables.MultiTableView): table_classes = ( ss_tables.ShareServersTable, ) template_name = "admin/share_servers/index.html" page_title = _("Share Servers") @memoized.memoized_method def get_share_servers_data(self): try: share_servers = manila.share_server_list(self.request) except Exception: share_servers = [] exceptions.handle( self.request, _("Unable to retrieve share servers")) utils.set_project_name_to_objects(self.request, share_servers) return share_servers class ShareServerDetailView(tabs.TabView): tab_group_class = ss_tabs.ShareServerDetailTabs template_name = "admin/share_servers/detail.html" redirect_url = reverse_lazy('horizon:admin:share_servers:index') def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) share_server = self.get_data() share_server_display_name = share_server.id context["share_server"] = share_server context["share_server_display_name"] = share_server_display_name context["page_title"] = _("Share Server Details: %(server_name)s") % { 'server_name': share_server_display_name} return context @memoized.memoized_method def get_data(self): try: share_serv_id = self.kwargs['share_server_id'] share_serv = manila.share_server_get(self.request, share_serv_id) share_search_opts = {'share_server_id': share_serv.id} shares_list = manila.share_list( self.request, search_opts=share_search_opts) for share in shares_list: share.name_or_id = share.name or share.id share_serv.shares_list = shares_list if not hasattr(share_serv, 'share_network_id'): share_serv.share_network_id = None except Exception: redirect = reverse('horizon:admin:share_servers:index') exceptions.handle( self.request, _('Unable to retrieve share server details.'), redirect=redirect) return share_serv def get_tabs(self, request, *args, **kwargs): share_server = self.get_data() return self.tab_group_class( request, share_server=share_server, **kwargs) manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/000077500000000000000000000000001323215354300240165ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/__init__.py000066400000000000000000000000001323215354300261150ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/panel.py000066400000000000000000000016561323215354300254770ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class ShareSnapshots(horizon.Panel): name = _("Share Snapshots") slug = 'share_snapshots' permissions = ( 'openstack.services.share', ) dashboard.Admin.register(ShareSnapshots) manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/tables.py000066400000000000000000000100731323215354300256430ustar00rootroot00000000000000# 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 django.core.urlresolvers import reverse from django.template.defaultfilters import title # noqa from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import tables from manila_ui.api import manila import manila_ui.dashboards.project.share_snapshots.tables as ss_tables from manila_ui.dashboards.project.shares import tables as shares_tables def get_size(share): return _("%sGiB") % share.size class ShareSnapshotShareNameColumn(tables.Column): def get_link_url(self, snapshot): return reverse(self.link, args=(snapshot.share_id,)) class DeleteShareSnapshot(tables.DeleteAction): @staticmethod def action_present(count): return ungettext_lazy( u"Delete Snapshot", u"Delete Snapshots", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Snapshot", u"Deleted Snapshots", count ) def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "project_id", None) return {"project_id": project_id} def delete(self, request, obj_id): obj = self.table.get_object_by_id(obj_id) name = self.table.get_object_display(obj) try: manila.share_snapshot_delete(request, obj_id) except Exception: msg = _('Unable to delete snapshot "%s". One or more shares ' 'depend on it.') exceptions.check_message(["snapshots", "dependent"], msg % name) raise def allowed(self, request, snapshot=None): if snapshot: return snapshot.status.upper() in shares_tables.DELETABLE_STATES return True class ShareSnapshotsTable(tables.DataTable): STATUS_CHOICES = ( ("in-use", True), ("available", True), ("creating", None), ("error", False), ) STATUS_DISPLAY_CHOICES = ( ("in-use", pgettext_lazy("Current status of snapshot", u"In-use")), ("available", pgettext_lazy("Current status of snapshot", u"Available")), ("creating", pgettext_lazy("Current status of snapshot", u"Creating")), ("error", pgettext_lazy("Current status of snapshot", u"Error")), ) name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:admin:share_snapshots:share_snapshot_detail") description = tables.Column( "description", verbose_name=_("Description"), truncate=40) size = tables.Column( get_size, verbose_name=_("Size"), attrs={'data-type': 'size'}) status = tables.Column( "status", filters=(title,), verbose_name=_("Status"), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES) source = ShareSnapshotShareNameColumn( "share", verbose_name=_("Source"), link="horizon:admin:shares:detail") def get_object_display(self, obj): return obj.name class Meta(object): name = "share_snapshots" verbose_name = _("Share Snapshots") status_columns = ["status"] row_class = ss_tables.UpdateShareSnapshotRow table_actions = ( tables.NameFilterAction, DeleteShareSnapshot, ) row_actions = ( DeleteShareSnapshot, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/tabs.py000066400000000000000000000021231323215354300253170ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareSnapshotOverviewTab(tabs.Tab): name = _("Share Snapshot Overview") slug = "share_snapshot_overview_tab" template_name = "admin/share_snapshots/_detail.html" def get_context_data(self, request): return {"snapshot": self.tab_group.kwargs["snapshot"]} class SnapshotDetailTabs(tabs.TabGroup): slug = "share_snapshot_details" tabs = ( ShareSnapshotOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/templates/000077500000000000000000000000001323215354300260145ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/templates/share_snapshots/000077500000000000000000000000001323215354300312205ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/templates/share_snapshots/_detail.html000066400000000000000000000040411323215354300335060ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Snapshot Overview" %}


{% trans "Name" %}
{{ snapshot.name }}
{% trans "ID" %}
{{ snapshot.id }}
{% url 'horizon:admin:shares:detail' snapshot.share_id as share_url %}
{% trans "Source" %}
{{ snapshot.share_name_or_id }}
{% if snapshot.description %}
{% trans "Description" %}
{{ snapshot.description }}
{% endif %}
{% trans "Status" %}
{{ snapshot.status|capfirst }}
{% if snapshot.export_locations %}
{% trans "Export locations" %}
{% for el in snapshot.export_locations %}

Path:
{% if el.is_admin_only != None %}
Is admin only: {{ el.is_admin_only }}
{% endif %} {% if el.share_snapshot_instance_id %}
Snapshot Replica ID: {{ el.share_snapshot_instance_id }}
{% endif %}

{% endfor %} {% endif %}
{% if snapshot.rules != None %}

{% trans "Access Rules" %}


{% for rule in snapshot.rules %}
{{ rule.access_type }}

Access to: {{ rule.access_to }}
Status: {{ rule.state }}

{% endfor %}
{% endif %}

{% trans "Specs" %}


{% trans "Size" %}
{{ snapshot.size }} {% trans "GiB" %}
{% trans "Created" %}
{{ snapshot.created_at|parse_date }}
manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/templates/share_snapshots/detail.html000066400000000000000000000003331323215354300333470ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/templates/share_snapshots/index.html000066400000000000000000000003401323215354300332120ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Shares" %}{% endblock %} {% block main %}
{{ share_snapshots_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/urls.py000066400000000000000000000015741323215354300253640ustar00rootroot00000000000000# 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 django.conf import urls from manila_ui.dashboards.admin.share_snapshots import views urlpatterns = [ urls.url( r'^$', views.ShareSnapshotsView.as_view(), name='index'), urls.url( r'^(?P[^/]+)$', views.ShareSnapshotDetailView.as_view(), name='share_snapshot_detail'), ] manila-ui-2.13.0/manila_ui/dashboards/admin/share_snapshots/views.py000066400000000000000000000045521323215354300255330ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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. """ Admin views for managing share snapshots. """ from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import tables from horizon.utils import memoized from manila_ui.api import manila from manila_ui.dashboards.admin.share_snapshots import tables as ss_tables from manila_ui.dashboards.admin.share_snapshots import tabs as ss_tabs from manila_ui.dashboards.admin import utils import manila_ui.dashboards.project.share_snapshots.views as snapshot_views class ShareSnapshotsView(tables.MultiTableView): table_classes = ( ss_tables.ShareSnapshotsTable, ) template_name = "admin/share_snapshots/index.html" page_title = _("Share Snapshots") @memoized.memoized_method def get_share_snapshots_data(self): snapshots = [] try: snapshots = manila.share_snapshot_list( self.request, search_opts={'all_tenants': True}) shares = manila.share_list(self.request) share_names = dict([(share.id, share.name or share.id) for share in shares]) for snapshot in snapshots: snapshot.share = share_names.get(snapshot.share_id) except Exception: msg = _("Unable to retrieve share snapshot list.") exceptions.handle(self.request, msg) # Gather our projects to correlate against IDs utils.set_project_name_to_objects(self.request, snapshots) return snapshots class ShareSnapshotDetailView(snapshot_views.ShareSnapshotDetailView): tab_group_class = ss_tabs.SnapshotDetailTabs template_name = "admin/share_snapshots/detail.html" redirect_url = reverse_lazy("horizon:admin:share_snapshots:index") manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/000077500000000000000000000000001323215354300231405ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/__init__.py000066400000000000000000000000001323215354300252370ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/forms.py000066400000000000000000000126401323215354300246430ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, 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 django.conf import settings from django.forms import ValidationError # noqa from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from manila_ui.api import manila from manila_ui.dashboards import utils ST_EXTRA_SPECS_FORM_ATTRS = { "rows": 5, "cols": 40, "style": "height: 135px; width: 100%;", # in case 'rows' not picked up } class CreateShareType(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Name"), required=True) spec_driver_handles_share_servers = forms.ChoiceField( label=_("Driver handles share servers"), required=True, choices=(('False', 'False'), ('True', 'True'))) extra_specs = forms.CharField( required=False, label=_("Extra specs"), widget=forms.widgets.Textarea(attrs=ST_EXTRA_SPECS_FORM_ATTRS)) is_public = forms.BooleanField( label=_("Public"), required=False, initial=True, help_text=("Defines whether this share type is available for all " "or not. List of allowed tenants should be set " "separately.")) def __init__(self, *args, **kwargs): super(CreateShareType, self).__init__(*args, **kwargs) manila_features = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {}) self.enable_public_share_type_creation = manila_features.get( 'enable_public_share_type_creation', True) if not self.enable_public_share_type_creation: self.fields.pop('is_public') def handle(self, request, data): try: spec_dhss = data['spec_driver_handles_share_servers'].lower() allowed_dhss_values = ('true', 'false') if spec_dhss not in allowed_dhss_values: msg = _("Improper value set to required extra spec " "'spec_driver_handles_share_servers'. " "Allowed values are %s. " "Case insensitive.") % allowed_dhss_values raise ValidationError(message=msg) set_dict, unset_list = utils.parse_str_meta(data['extra_specs']) if unset_list: msg = _("Expected only pairs of key=value.") raise ValidationError(message=msg) is_public = (self.enable_public_share_type_creation and data["is_public"]) share_type = manila.share_type_create( request, data["name"], spec_dhss, is_public=is_public) if set_dict: manila.share_type_set_extra_specs( request, share_type.id, set_dict) msg = _("Successfully created share type: %s") % share_type.name messages.success(request, msg) return True except ValidationError as e: # handle error without losing dialog self.api_error(e.messages[0]) return False except Exception: exceptions.handle(request, _('Unable to create share type.')) return False class UpdateShareType(forms.SelfHandlingForm): def __init__(self, *args, **kwargs): super(UpdateShareType, self).__init__(*args, **kwargs) # NOTE(vponomaryov): parse existing extra specs # to str view for textarea html element es_str = "" for k, v in self.initial["extra_specs"].iteritems(): es_str += "%s=%s\r\n" % (k, v) self.initial["extra_specs"] = es_str extra_specs = forms.CharField( required=False, label=_("Extra specs"), widget=forms.widgets.Textarea(attrs=ST_EXTRA_SPECS_FORM_ATTRS)) def handle(self, request, data): try: set_dict, unset_list = utils.parse_str_meta(data['extra_specs']) if set_dict: manila.share_type_set_extra_specs( request, self.initial["id"], set_dict) if unset_list: get = manila.share_type_get_extra_specs( request, self.initial["id"]) # NOTE(vponomaryov): skip keys that are already unset to_unset = set(unset_list).intersection(set(get.keys())) if to_unset: manila.share_type_unset_extra_specs( request, self.initial["id"], to_unset) msg = _("Successfully updated extra specs for share type '%s'.") msg = msg % self.initial['name'] messages.success(request, msg) return True except ValidationError as e: # handle error without losing dialog self.api_error(e.messages[0]) return False except Exception: msg = _("Unable to update extra_specs for share type.") exceptions.handle(request, msg) return False manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/panel.py000066400000000000000000000016401323215354300246120ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class ShareTypes(horizon.Panel): name = _("Share Types") slug = 'share_types' permissions = ( 'openstack.services.share', ) dashboard.Admin.register(ShareTypes) manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/tables.py000066400000000000000000000065131323215354300247710ustar00rootroot00000000000000# 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 django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import tables import six from manila_ui.api import manila def get_size(share): return _("%sGiB") % share.size class CreateShareType(tables.LinkAction): name = "create" verbose_name = _("Create Share Type") url = "horizon:admin:share_types:create_type" classes = ("ajax-modal", "btn-create") icon = "plus" class DeleteShareType(tables.DeleteAction): @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Type", u"Delete Share Types", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Type", u"Deleted Share Types", count ) def delete(self, request, obj_id): manila.share_type_delete(request, obj_id) class ManageShareTypeAccess(tables.LinkAction): name = "manage" verbose_name = _("Manage Share Type Access") url = "horizon:admin:share_types:manage_share_type_access" classes = ("ajax-modal", "btn-create") def allowed(self, request, obj_id): st = manila.share_type_get(request, obj_id) # Enable it only for private share types return not st.is_public def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None) return {"project_id": project_id} class UpdateShareType(tables.LinkAction): name = "update share type" verbose_name = _("Update Share Type") url = "horizon:admin:share_types:update_type" classes = ("ajax-modal", "btn-create") def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None) return {"project_id": project_id} class ShareTypesTable(tables.DataTable): name = tables.WrappingColumn("name", verbose_name=_("Name")) extra_specs = tables.Column("extra_specs", verbose_name=_("Extra specs"), ) visibility = tables.Column( "is_public", verbose_name=_("Visibility"), filters=(lambda d: 'public' if d is True else 'private', ), ) def get_object_display(self, share_type): return share_type.name def get_object_id(self, share_type): return six.text_type(share_type.id) class Meta(object): name = "share_types" verbose_name = _("Share Types") table_actions = ( tables.NameFilterAction, CreateShareType, DeleteShareType, ) row_actions = ( UpdateShareType, ManageShareTypeAccess, DeleteShareType, ) manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/templates/000077500000000000000000000000001323215354300251365ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/templates/share_types/000077500000000000000000000000001323215354300274645ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/templates/share_types/_create.html000066400000000000000000000010431323215354300317520ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "The share type defines the characteristics of a share backend." %}

Extra specs field:
{% trans "One line - one action. Empty strings will be ignored." %}
{% trans "To add extra-specs use:" %}

key=value
{% trans "Extra spec 'driver_handles_share_servers' is required and should have boolean value." %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/templates/share_types/_manage_access.html000066400000000000000000000032361323215354300332660ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block form_id %}{% endblock %} {% block form_action %}{% url 'horizon:admin:share_types:manage_share_type_access' share_type.id %}{% endblock %} {% block modal_id %}manage_share_type_access_modal{% endblock %} {% block modal-header %}{% trans "Manage Share Type Access" %}{% endblock %} {% block modal-body %}
{% include "horizon/common/_form_fields.html" %}

{% trans "Description" %}:

{% blocktrans %} Placeholder for description of share type access managing form. {% endblocktrans %}

{% include "horizon/common/_form_fields.html" %}
{{ step.get_help_text }}
{% endblock %} {% block modal-footer %} {% trans "Cancel" %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/templates/share_types/_update.html000066400000000000000000000012201323215354300317660ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "Here can be modified extra-specs for share type." %}
{% trans "One line - one action. Empty strings will be ignored." %}
{% trans "To add extra-specs use:" %}

key=value
{% trans "To unset extra-specs use:" %}
key
{% trans "All pairs that are in field for left are set for this share type." %} {% trans "Extra spec 'driver_handles_share_servers' is required and should have boolean value." %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/templates/share_types/create.html000066400000000000000000000002751323215354300316210ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Share Type" %}{% endblock %} {% block main %} {% include 'admin/share_types/_create.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/templates/share_types/index.html000066400000000000000000000003411323215354300314570ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Types" %}{% endblock %} {% block main %}
{{ share_types_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/templates/share_types/manage_access.html000066400000000000000000000003131323215354300331200ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Manage Share Type Access" %}{% endblock %} {% block main %} {% include 'admin/share_types/_manage_access.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/templates/share_types/update.html000066400000000000000000000002751323215354300316400ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Update Share Type" %}{% endblock %} {% block main %} {% include 'admin/share_types/_update.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/urls.py000066400000000000000000000022351323215354300245010ustar00rootroot00000000000000# 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 django.conf import urls from manila_ui.dashboards.admin.share_types import views urlpatterns = [ urls.url( r'^$', views.ShareTypesView.as_view(), name='index'), urls.url( r'^create_type$', views.CreateShareTypeView.as_view(), name='create_type'), urls.url( r'^update_type/(?P[^/]+)/extra_specs$', views.UpdateShareTypeView.as_view(), name='update_type'), urls.url( r'^manage_share_type_access/(?P[^/]+)$', views.ManageShareTypeAccessView.as_view(), name='manage_share_type_access'), ] manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/views.py000066400000000000000000000104261323215354300246520ustar00rootroot00000000000000# 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. """ Admin views for managing share types. """ from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon.utils import memoized from horizon import workflows from manila_ui.api import manila from manila_ui.dashboards.admin.share_types import forms as project_forms from manila_ui.dashboards.admin.share_types import tables as st_tables import manila_ui.dashboards.admin.share_types.workflows as st_workflows from manila_ui.dashboards import utils as common_utils class ShareTypesView(tables.MultiTableView): table_classes = ( st_tables.ShareTypesTable, ) template_name = "admin/share_types/index.html" page_title = _("Share Types") @memoized.memoized_method def get_share_types_data(self): try: share_types = manila.share_type_list(self.request) except Exception: exceptions.handle( self.request, _('Unable to retrieve share types.')) return [] # Convert dict with extra specs to friendly view for st in share_types: st.extra_specs = common_utils.metadata_to_str( st.extra_specs, 8, 45) return share_types class CreateShareTypeView(forms.ModalFormView): form_class = project_forms.CreateShareType form_id = "create_share_type" template_name = 'admin/share_types/create.html' modal_header = _("Create Share Type") modal_id = "create_share_type_modal" submit_label = _("Create") submit_url = reverse_lazy("horizon:admin:share_types:create_type") success_url = reverse_lazy('horizon:admin:share_types:index') page_title = _("Create Share Type") class ManageShareTypeAccessView(workflows.WorkflowView): workflow_class = st_workflows.ManageShareTypeAccessWorkflow template_name = "admin/share_types/manage_access.html" success_url = 'horizon:project:share_types:index' page_title = _("Manage Share Type Access") def get_initial(self): return {'id': self.kwargs["share_type_id"]} def get_context_data(self, **kwargs): context = super(ManageShareTypeAccessView, self).get_context_data( **kwargs) context['id'] = self.kwargs['share_type_id'] return context class UpdateShareTypeView(forms.ModalFormView): form_class = project_forms.UpdateShareType form_id = "update_share_type" template_name = "admin/share_types/update.html" modal_header = _("Update Share Type") modal_id = "update_share_type_modal" submit_label = _("Update") submit_url = "horizon:admin:share_types:update_type" success_url = reverse_lazy("horizon:admin:share_types:index") page_title = _("Update Share Type") def get_object(self): if not hasattr(self, "_object"): st_id = self.kwargs["share_type_id"] try: self._object = manila.share_type_get(self.request, st_id) except Exception: msg = _("Unable to retrieve share_type.") url = reverse("horizon:admin:share_types:index") exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(UpdateShareTypeView, self).get_context_data(**kwargs) args = (self.get_object().id,) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): share_type = self.get_object() return { "id": self.kwargs["share_type_id"], "name": share_type.name, "extra_specs": share_type.extra_specs, } manila-ui-2.13.0/manila_ui/dashboards/admin/share_types/workflows.py000066400000000000000000000104551323215354300255540ustar00rootroot00000000000000# 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 django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import workflows from openstack_dashboard.api import keystone from manila_ui.api import manila class AddProjectAction(workflows.MembershipAction): def __init__(self, request, *args, **kwargs): super(AddProjectAction, self).__init__(request, *args, **kwargs) default_role_field_name = self.get_default_role_field_name() self.fields[default_role_field_name] = forms.CharField(required=False) self.fields[default_role_field_name].initial = 'member' field_name = self.get_member_field_name('member') self.fields[field_name] = forms.MultipleChoiceField(required=False) share_type_id = self.initial['id'] # Get list of existing projects try: projects, __ = keystone.tenant_list(request) except Exception: err_msg = _('Unable to get list of projects.') exceptions.handle(request, err_msg) # Get list of projects with access to this Share Type try: share_type = manila.share_type_get(request, share_type_id) self.share_type_name = share_type.name projects_initial = manila.share_type_access_list( request, share_type) except Exception: err_msg = _('Unable to get information about share type access.') exceptions.handle(request, err_msg) self.fields[field_name].choices = [ (project.id, project.name or project.id) for project in projects] self.fields[field_name].initial = [ pr.project_id for pr in projects_initial] self.projects_initial = set(self.fields[field_name].initial) class Meta(object): name = _("Projects with access to share type") slug = "update_members" def handle(self, request, context): context.update({ 'name': self.share_type_name, 'projects_add': self.projects_allow - self.projects_initial, 'projects_remove': self.projects_initial - self.projects_allow, }) return context def clean(self): cleaned_data = super(AddProjectAction, self).clean() self.projects_allow = set( cleaned_data[self.get_member_field_name('member')]) return cleaned_data class AddProjectStep(workflows.UpdateMembersStep): action_class = AddProjectAction available_list_title = _("Available projects") help_text = _("Allow project access to share type.") members_list_title = _("Selected projects") no_available_text = _("No projects found.") no_members_text = _("No projects selected.") depends_on = ("id", ) show_roles = False class ManageShareTypeAccessWorkflow(workflows.Workflow): slug = "manage_share_type_access" name = _("Manage Share Type Access") finalize_button_name = _("Manage Share Type Access") success_message = _('Updated access for share type "%s".') failure_message = _('Unable to update access for share type "%s".') success_url = 'horizon:admin:share_types:index' default_steps = (AddProjectStep, ) def format_status_message(self, message): return message % self.context['name'] def handle(self, request, context): try: for project in self.context['projects_remove']: manila.share_type_access_remove( request, self.context['id'], project) for project in self.context['projects_add']: manila.share_type_access_add( request, self.context['id'], project) return True except Exception: exceptions.handle(request, _('Unable to update share type.')) return False manila-ui-2.13.0/manila_ui/dashboards/admin/shares/000077500000000000000000000000001323215354300220775ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/__init__.py000066400000000000000000000000001323215354300241760ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/forms.py000066400000000000000000000320621323215354300236020ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, 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 django.conf import settings from django.core.urlresolvers import reverse from django.forms import ValidationError # noqa from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from oslo_utils import strutils import six from manila_ui.api import manila from manila_ui.dashboards import utils def _get_id_if_name_empty(data): result = data.get('name', None) if not result: result = data.get('id') if not result: result = '' return result class MigrationStart(forms.SelfHandlingForm): name = forms.CharField( label=_("Share Name"), widget=forms.TextInput(attrs={'readonly': 'readonly'})) share_id = forms.CharField( label=_("ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'})) host = forms.ChoiceField( label=_("Host to migrate share"), help_text=_("Destination host and pool where share will be migrated " "to.")) force_host_assisted_migration = forms.BooleanField( label=_("Force Host Assisted Migration"), required=False, initial=False, help_text=_("Enforces the use of the host-assisted migration approach," " which bypasses driver optimizations.")) nondisruptive = forms.BooleanField( label=_("Nondisruptive"), required=False, initial=True, help_text=_("Enforces migration to be nondisruptive. If set to True, " "host-assisted migration will not be attempted.")) writable = forms.BooleanField( label=_("Writable"), required=False, initial=True, help_text=_("Enforces migration to keep the share writable while " "contents are being moved. If set to True, host-assisted " "migration will not be attempted.")) preserve_metadata = forms.BooleanField( label=_("Preserve Metadata"), required=False, initial=True, help_text=_("Enforces migration to preserve all file metadata when " "moving its contents. If set to True, host-assisted " "migration will not be attempted.")) preserve_snapshots = forms.BooleanField( label=_("Preserve Snapshots"), required=False, initial=True, help_text=_("Enforces migration of the share snapshots to the " "destination. If set to True, host-assisted migration will" " not be attempted.")) new_share_network = forms.ChoiceField( label=_("New share network to be set in migrated share"), required=False, help_text=_('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.')) new_share_type = forms.ChoiceField( label=_("New share type to be set in migrating share"), required=False, help_text=_('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.')) def __init__(self, request, *args, **kwargs): super(MigrationStart, self).__init__(request, *args, **kwargs) share_networks = manila.share_network_list(request) share_types = manila.share_type_list(request) dests = manila.pool_list(request) dest_choices = [('', '')] + [(d.name, d.name) for d in dests] st_choices = [('', '')] + [(st.id, st.name) for st in share_types] sn_choices = ( [('', '')] + [(sn.id, sn.name or sn.id) for sn in share_networks]) self.fields['host'].choices = dest_choices self.fields['new_share_type'].choices = st_choices self.fields['new_share_network'].choices = sn_choices def handle(self, request, data): share_name = _get_id_if_name_empty(data) try: manila.migration_start( request, self.initial['share_id'], force_host_assisted_migration=( data['force_host_assisted_migration']), writable=data['writable'], preserve_metadata=data['preserve_metadata'], preserve_snapshots=data['preserve_snapshots'], nondisruptive=data['nondisruptive'], dest_host=data['host'], new_share_network_id=data['new_share_network'], new_share_type_id=data['new_share_type']) messages.success( request, _('Successfully sent the request to migrate share: %s.') % share_name) return True except Exception: redirect = reverse("horizon:admin:shares:index") exceptions.handle( request, _("Unable to migrate share %s.") % share_name, redirect=redirect) return False class MigrationForms(forms.SelfHandlingForm): name = forms.CharField( label=_("Share Name"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'})) share_id = forms.CharField( label=_("ID"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'})) class MigrationComplete(MigrationForms): def handle(self, request, data): share_name = _get_id_if_name_empty(data) try: manila.migration_complete(request, self.initial['share_id']) messages.success( request, _('Successfully sent the request to complete migration of ' ' share: %s.') % share_name) return True except Exception: exceptions.handle(request, _("Unable to complete migration " "of share %s.") % share_name) return False class MigrationGetProgress(MigrationForms): def handle(self, request, data): share_name = _get_id_if_name_empty(data) try: result = manila.migration_get_progress(request, self.initial['share_id']) progress = result[1] messages.success( request, _('Migration of share %(name)s is at %(progress)s percent.') % {'name': share_name, 'progress': progress['total_progress']}) return True except Exception: exceptions.handle(request, _("Unable to obtain progress of " "migration of share %s at this " "moment.") % share_name) return False class MigrationCancel(MigrationForms): def handle(self, request, data): share_name = _get_id_if_name_empty(data) try: manila.migration_cancel(request, self.initial['share_id']) messages.success( request, _('Successfully sent the request to cancel migration of ' ' share: %s.') % share_name) return True except Exception: exceptions.handle(request, _("Unable to cancel migration of share" " %s at this moment.") % share_name) return False class ManageShare(forms.SelfHandlingForm): name = forms.CharField( max_length=255, label=_("Share Name"), required=False, help_text=_("Share name to be assigned")) description = forms.CharField( max_length=255, label=_("Description"), required=False, widget=forms.Textarea( attrs={'class': 'modal-body-fixed-width', 'rows': 4})) host = forms.CharField( max_length=255, label=_("Host of share"), required=True, help_text=_( "Host where share is located, example: some.host@driver[#pool]")) export_location = forms.CharField( max_length=255, label=_("Export location"), required=True, help_text=_("Export location of share. Example for NFS: " "1.2.3.4:/path/to/share")) protocol = forms.ChoiceField(label=_("Share Protocol"), required=True) share_type = forms.ChoiceField(label=_("Share Type"), required=True) driver_options = forms.CharField( max_length=255, required=False, label=_("Driver options ('volume_id' for Generic driver, etc...)"), help_text=_("key=value pairs per line can be set"), widget=forms.Textarea( attrs={'class': 'modal-body-fixed-width', 'rows': 2})) is_public = forms.BooleanField( label=_("Public"), required=False, initial=False, help_text=("Defines whether this share is available for all or not.")) def __init__(self, request, *args, **kwargs): super(ManageShare, self).__init__(request, *args, **kwargs) share_types = manila.share_type_list(request) # NOTE(vponomaryov): choose only those share_types that have spec # 'driver_handles_share_servers' set to 'False' value or alias of it. dhss_key = 'driver_handles_share_servers' st_choices = [('', ''), ] for st in share_types: dhss = st.to_dict()['extra_specs'].get(dhss_key) if dhss and dhss.lower() in strutils.FALSE_STRINGS: st_choices.append((st.name, st.name)) self.fields['share_type'].choices = st_choices # NOTE(vkmc): choose only those share protocols that are enabled # FIXME(vkmc): this should be better implemented by having a # capabilities endpoint on the control plane. manila_features = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {}) self.enabled_share_protocols = manila_features.get( 'enabled_share_protocols', ['NFS', 'CIFS', 'GlusterFS', 'HDFS', 'CephFS', 'MapRFS']) self.fields['protocol'].choices = ([(' ', ' ')] + [(enabled_proto, enabled_proto) for enabled_proto in self.enabled_share_protocols]) def handle(self, request, data): try: driver_options = data.get('driver_options') or {} driver_options_error_msg = _( "Got improper value for field 'driver_options'. " "Expected only pairs of key=value.") if driver_options and isinstance(driver_options, six.string_types): try: set_dict, unset_list = utils.parse_str_meta(driver_options) if unset_list: raise ValidationError(message=driver_options_error_msg) driver_options = set_dict except ValidationError as e: self.api_error(e.messages[0]) return False elif not isinstance(driver_options, dict): self.api_error(driver_options_error_msg) return False manila.share_manage( request, service_host=data['host'], protocol=data['protocol'], export_path=data['export_location'], driver_options=driver_options, share_type=data['share_type'], name=data['name'], description=data['description'], is_public=data['is_public']) share_name = data.get('name', data.get('id')) messages.success( request, _('Successfully sent the request to manage share: %s') % share_name) return True except Exception: exceptions.handle(request, _("Unable to manage share")) return False class UnmanageShare(forms.SelfHandlingForm): name = forms.CharField( label=_("Share Name"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'})) host = forms.CharField( label=_("Host"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'})) share_id = forms.CharField( label=_("ID"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'})) def handle(self, request, data): try: manila.share_unmanage(request, self.initial['share_id']) messages.success( request, _('Successfully sent the request to unmanage share: %s') % data['name']) return True except Exception: exceptions.handle(request, _("Unable to unmanage share.")) return False manila-ui-2.13.0/manila_ui/dashboards/admin/shares/panel.py000066400000000000000000000015611323215354300235530ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.admin import dashboard class Shares(horizon.Panel): name = _("Shares") slug = "shares" permissions = ( 'openstack.services.share', ) dashboard.Admin.register(Shares) manila-ui-2.13.0/manila_ui/dashboards/admin/shares/replicas/000077500000000000000000000000001323215354300237015ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/replicas/__init__.py000066400000000000000000000000001323215354300260000ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/replicas/forms.py000066400000000000000000000075211323215354300254060ustar00rootroot00000000000000# Copyright (c) 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. from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from manila_ui.api import manila class ResyncReplicaForm(forms.SelfHandlingForm): def handle(self, request, data): replica_id = self.initial['replica_id'] try: replica = manila.share_replica_get(self.request, replica_id) manila.share_replica_resync(request, replica) message = _("Resync'ing replica '%s'") % replica_id messages.success(request, message) return True except Exception: redirect = reverse("horizon:admin:shares:index") exceptions.handle( request, _("Unable to resync replica '%s'.") % replica_id, redirect=redirect) class ResetReplicaStatusForm(forms.SelfHandlingForm): replica_status = forms.ChoiceField( label=_("Replica State"), required=True, choices=( ('available', 'available'), ('creating', 'creating'), ('deleting', 'deleting'), ('error', 'error'), ) ) def handle(self, request, data): replica_id = self.initial['replica_id'] try: replica = manila.share_replica_get(self.request, replica_id) manila.share_replica_reset_status( request, replica, data["replica_status"]) message = _("Reseting replica ('%(id)s') status from '%(from)s' " "to '%(to)s'.") % { "id": replica_id, "from": replica.replica_state, "to": data["replica_status"]} messages.success(request, message) return True except Exception: redirect = reverse("horizon:admin:shares:index") exceptions.handle( request, _("Unable to reset status of replica '%s'.") % replica_id, redirect=redirect) class ResetReplicaStateForm(forms.SelfHandlingForm): replica_state = forms.ChoiceField( label=_("Replica State"), required=True, choices=( ('active', 'active'), ('in_sync', 'in_sync'), ('out_of_sync', 'out_of_sync'), ('error', 'error'), ) ) def handle(self, request, data): replica_id = self.initial['replica_id'] try: replica = manila.share_replica_get(self.request, replica_id) manila.share_replica_reset_state( request, replica, data["replica_state"]) message = _("Reseting replica ('%(id)s') state from '%(from)s' " "to '%(to)s'.") % { "id": replica_id, "from": replica.replica_state, "to": data["replica_state"]} messages.success(request, message) return True except Exception: redirect = reverse("horizon:admin:shares:index") exceptions.handle( request, _("Unable to reset state of replica '%s'.") % replica_id, redirect=redirect) manila-ui-2.13.0/manila_ui/dashboards/admin/shares/replicas/tables.py000066400000000000000000000120551323215354300255300ustar00rootroot00000000000000# Copyright (c) 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. from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import messages from horizon import tables from manila_ui.api import manila from manila_ui.dashboards.project.shares.replicas import ( tables as replica_tables) DELETABLE_STATUSES = ("error", "available") class UpdateReplicaRow(tables.Row): ajax = True def get_data(self, request, replica_id): replica = manila.share_replica_get(request, replica_id) return replica class ResyncReplica(tables.LinkAction): name = "resync_replica" verbose_name = _("Resync replica") url = "horizon:admin:shares:resync_replica" classes = ("ajax-modal", "btn-create") policy_rules = (("share_replica", "share_replica:resync"),) def allowed(self, request, replica=None): return True def get_policy_target(self, request, datum=None): return {"project_id": getattr(datum, "project_id", None)} def get_link_url(self, replica): return reverse(self.url, args=(replica.id,)) class ResetReplicaState(tables.LinkAction): name = "reset_replica_state" verbose_name = _("Reset replica state") url = "horizon:admin:shares:reset_replica_state" classes = ("ajax-modal", "btn-create") policy_rules = (("share_replica", "share_replica:reset_replica_state"),) def allowed(self, request, replica=None): return True def get_policy_target(self, request, datum=None): return {"project_id": getattr(datum, "project_id", None)} def get_link_url(self, replica): return reverse(self.url, args=(replica.id,)) class ResetReplicaStatus(tables.LinkAction): name = "reset_replica_status" verbose_name = _("Reset replica status") url = "horizon:admin:shares:reset_replica_status" classes = ("ajax-modal", "btn-create") policy_rules = (("share_replica", "share_replica:reset_status"),) def allowed(self, request, replica=None): return True def get_policy_target(self, request, datum=None): return {"project_id": getattr(datum, "project_id", None)} def get_link_url(self, replica): return reverse(self.url, args=(replica.id,)) class DeleteReplica(tables.DeleteAction): policy_rules = (("share_replica", "share_replica:delete"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Replica", u"Delete Replicas", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Replica", u"Deleted Replicas", count ) def get_policy_target(self, request, datum=None): return {"project_id": getattr(datum, "project_id", None)} def delete(self, request, obj_id): try: manila.share_replica_delete(request, obj_id) except Exception: msg = _('Unable to delete replica "%s".') % obj_id messages.error(request, msg) def allowed(self, request, replica=None): if replica: share = manila.share_get(request, replica.share_id) replicas = manila.share_replica_list(request, replica.share_id) if share.replication_type is None: return False elif (share.replication_type is 'writable' and replica.status in DELETABLE_STATUSES and len(replicas) > 1) or ( share.replication_type in ('dr', 'readable') and replica.status in DELETABLE_STATUSES and replica.replica_state != 'active'): return True return False def single(self, data_table, request, object_id): try: manila.share_replica_delete(request, object_id) messages.success( request, _('Share replica %s has been deleted.') % object_id) except Exception: msg = _('Unable to delete replica "%s".') % object_id messages.error(request, msg) _DETAIL_URL = "horizon:admin:shares:replica_detail" class ReplicasTable(replica_tables.ReplicasTable): class Meta(object): name = "replicas" verbose_name = _("Replicas") status_columns = ("status",) row_class = UpdateReplicaRow row_actions = ( ResyncReplica, ResetReplicaState, ResetReplicaStatus, DeleteReplica) manila-ui-2.13.0/manila_ui/dashboards/admin/shares/replicas/tabs.py000066400000000000000000000020621323215354300252040ustar00rootroot00000000000000# Copyright (c) 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. from django.utils.translation import ugettext_lazy as _ from horizon import tabs class ReplicaOverviewTab(tabs.Tab): name = _("Overview") slug = "overview" template_name = "admin/shares/replicas/_detail_overview.html" def get_context_data(self, request): return {"replica": self.tab_group.kwargs['replica']} class ReplicaDetailTabs(tabs.TabGroup): slug = "replica_details" tabs = (ReplicaOverviewTab,) manila-ui-2.13.0/manila_ui/dashboards/admin/shares/replicas/views.py000066400000000000000000000136471323215354300254230ustar00rootroot00000000000000# Copyright (c) 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. from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from manila_ui.api import manila from manila_ui.dashboards.admin.shares.replicas import ( tables as replicas_tables) from manila_ui.dashboards.admin.shares.replicas import forms as replicas_forms from manila_ui.dashboards.admin.shares.replicas import tabs as replicas_tabs from manila_ui.dashboards.project.shares.replicas import ( views as project_replica_views) class ManageReplicasView(project_replica_views.ManageReplicasView): table_class = replicas_tables.ReplicasTable template_name = 'admin/shares/replicas/manage_replicas.html' _redirect_url = 'horizon:admin:shares:index' class DetailReplicaView(project_replica_views.DetailReplicaView): tab_group_class = replicas_tabs.ReplicaDetailTabs template_name = 'admin/shares/replicas/detail.html' _redirect_url = 'horizon:admin:shares:index' class ResyncReplicaView(forms.ModalFormView): form_class = replicas_forms.ResyncReplicaForm form_id = "resync_replica" template_name = 'admin/shares/replicas/resync_replica.html' modal_header = _("Resync Replica") modal_id = "resync_replica_modal" submit_label = _("Resync") submit_url = "horizon:admin:shares:resync_replica" success_url = 'horizon:admin:shares:manage_replicas' page_title = _("Resync Replica") def get_success_url(self): return reverse(self.success_url, args=[self.get_object().share_id]) def get_object(self): if not hasattr(self, "_object"): replica_id = self.kwargs["replica_id"] try: self._object = manila.share_replica_get( self.request, replica_id) except Exception: msg = _("Unable to retrieve replica '%s'.") % replica_id url = reverse('horizon:admin:shares:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) context['replica_id'] = self.kwargs['replica_id'] args = (context['replica_id'],) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): return {'replica_id': self.kwargs["replica_id"]} class ResetReplicaStatusView(forms.ModalFormView): form_class = replicas_forms.ResetReplicaStatusForm form_id = "reset_replica_status" template_name = 'admin/shares/replicas/reset_replica_status.html' modal_header = _("Reset Replica Status") modal_id = "reset_replica_status_modal" submit_label = _("Reset status") submit_url = "horizon:admin:shares:reset_replica_status" success_url = 'horizon:admin:shares:manage_replicas' page_title = _("Reset Replica Status") def get_success_url(self): return reverse(self.success_url, args=[self.get_object().share_id]) def get_object(self): if not hasattr(self, "_object"): replica_id = self.kwargs["replica_id"] try: self._object = manila.share_replica_get( self.request, replica_id) except Exception: msg = _("Unable to retrieve replica '%s'.") % replica_id url = reverse('horizon:admin:shares:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) context['replica_id'] = self.kwargs['replica_id'] args = (context['replica_id'],) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): return {'replica_id': self.kwargs["replica_id"]} class ResetReplicaStateView(forms.ModalFormView): form_class = replicas_forms.ResetReplicaStateForm form_id = "reset_replica_state" template_name = 'admin/shares/replicas/reset_replica_state.html' modal_header = _("Reset Replica State") modal_id = "reset_replica_state_modal" submit_label = _("Reset state") submit_url = "horizon:admin:shares:reset_replica_state" success_url = 'horizon:admin:shares:manage_replicas' page_title = _("Reset Replica State") def get_success_url(self): return reverse(self.success_url, args=[self.get_object().share_id]) def get_object(self): if not hasattr(self, "_object"): replica_id = self.kwargs["replica_id"] try: self._object = manila.share_replica_get( self.request, replica_id) except Exception: msg = _("Unable to retrieve replica '%s'.") % replica_id url = reverse('horizon:admin:shares:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) context['replica_id'] = self.kwargs['replica_id'] args = (context['replica_id'],) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): return {'replica_id': self.kwargs["replica_id"]} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/tables.py000066400000000000000000000126741323215354300237350ustar00rootroot00000000000000# 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 django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import tables from manila_ui.dashboards.project.shares import tables as shares_tables from manila_ui import features class MigrationStartAction(tables.LinkAction): name = "migration_start" verbose_name = _("Migrate Share") url = "horizon:admin:shares:migration_start" classes = ("ajax-modal",) policy_rules = (("share", "migration_start"),) ajax = True def allowed(self, request, share=None): if share: return (share.status.upper() == "AVAILABLE" and not getattr(share, 'has_snapshot', False) and features.is_migration_enabled()) return False class MigrationCompleteAction(tables.LinkAction): name = "migration_complete" verbose_name = _("Complete migration") url = "horizon:admin:shares:migration_complete" classes = ("ajax-modal",) policy_rules = (("share", "migration_complete"),) ajax = True def allowed(self, request, share=None): if (share and share.status.upper() == "MIGRATING" and features.is_migration_enabled()): return True return False class MigrationCancelAction(tables.LinkAction): name = "migration_cancel" verbose_name = _("Cancel migration") url = "horizon:admin:shares:migration_cancel" classes = ("ajax-modal",) policy_rules = (("share", "migration_cancel"),) ajax = True def allowed(self, request, share=None): if (share and share.status.upper() == "MIGRATING" and features.is_migration_enabled()): return True return False class MigrationGetProgressAction(tables.LinkAction): name = "migration_get_progress" verbose_name = _("Get migration progress") url = "horizon:admin:shares:migration_get_progress" classes = ("ajax-modal",) policy_rules = (("share", "migration_get_progress"),) ajax = True def allowed(self, request, share=None): if (share and share.status.upper() == "MIGRATING" and features.is_migration_enabled()): return True return False class ManageShareAction(tables.LinkAction): name = "manage" verbose_name = _("Manage Share") url = "horizon:admin:shares:manage" classes = ("ajax-modal",) icon = "plus" policy_rules = (("share", "share_extension:share_manage"),) ajax = True class UnmanageShareAction(tables.LinkAction): name = "unmanage" verbose_name = _("Unmanage Share") url = "horizon:admin:shares:unmanage" classes = ("ajax-modal",) icon = "pencil" policy_rules = (("share", "share_extension:share_unmanage"),) def allowed(self, request, share=None): if (not share or share.share_server_id or share.status.upper() not in shares_tables.DELETABLE_STATES): return False elif hasattr(share, 'has_snapshot'): return not share.has_snapshot return False class ManageReplicas(tables.LinkAction): name = "manage_replicas" verbose_name = _("Manage Replicas") url = "horizon:admin:shares:manage_replicas" classes = ("btn-edit",) policy_rules = (("share", "share:replica_get_all"),) def allowed(self, request, share): share_replication_enabled = share.replication_type is not None return features.is_replication_enabled() and share_replication_enabled class SharesTable(shares_tables.SharesTable): name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:admin:shares:detail") host = tables.Column("host", verbose_name=_("Host")) project = tables.Column("project_name", verbose_name=_("Project")) def get_share_server_link(share): if getattr(share, 'share_server_id', None): return reverse("horizon:admin:share_servers:share_server_detail", args=(share.share_server_id,)) else: return None share_server = tables.Column( "share_server_id", verbose_name=_("Share Server"), link=get_share_server_link) class Meta(object): name = "shares" verbose_name = _("Shares") status_columns = ["status"] row_class = shares_tables.UpdateRow table_actions = ( tables.NameFilterAction, ManageShareAction, shares_tables.DeleteShare, ) row_actions = ( ManageReplicas, MigrationStartAction, MigrationCompleteAction, MigrationGetProgressAction, MigrationCancelAction, UnmanageShareAction, shares_tables.DeleteShare, ) columns = [ 'tenant', 'host', 'name', 'size', 'status', 'visibility', 'share_type', 'protocol', 'share_server', ] if features.is_share_groups_enabled(): columns.append('share_group_id') manila-ui-2.13.0/manila_ui/dashboards/admin/shares/tabs.py000066400000000000000000000020261323215354300234020ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareOverviewTab(tabs.Tab): name = _("Share Overview") slug = "share_overview_tab" template_name = "admin/shares/_detail.html" def get_context_data(self, request): return {"share": self.tab_group.kwargs["share"]} class ShareDetailTabs(tabs.TabGroup): slug = "share_details" tabs = ( ShareOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/000077500000000000000000000000001323215354300240755ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/000077500000000000000000000000001323215354300253625ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/_detail.html000066400000000000000000000070371323215354300276600ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Overview" %}


{% trans "Name" %}
{{ share.name }}
{% trans "ID" %}
{{ share.id }}
{% if share.description %}
{% trans "Description" %}
{{ share.description }}
{% endif %}
{% trans "Status" %}
{{ share.status|capfirst }}
{% trans "Export locations" %}
{% for el in share.export_locations %}

Path:
Preferred: {{ el.preferred }}
{% if el.is_admin_only == True or el.is_admin_only == False %}
Is admin only: {{ el.is_admin_only }}
{% endif %} {% if el.share_instance_id %}
Share Replica ID: {{ el.share_instance_id }}
{% endif %}

{% endfor %} {% if share.snapshot_id %}
{% trans "Snapshot ID" %}
{% url 'horizon:admin:share_snapshots:snapshot_detail' share.snapshot_id as snapshot_url%}
{{ share.snapshot_id }}
{% endif %}
{% trans "Visibility" %}
{% if share.is_public == True %}
{{ 'public' }}
{% else %}
{{ 'private' }}
{% trans "Availability zone" %}
{{ share.availability_zone }}
{% endif %}
{% trans "Size" %}
{{ share.size }} {% trans "GiB" %}
{% trans "Protocol" %}
{{ share.share_proto }}
{% if share.share_type %}
{% trans "Share type" %}

Name: {{ share.share_type_name }}
ID: {{ share.share_type }}

{% endif %} {% if share.share_network_id %}
{% trans "Share Network" %}
{% url 'horizon:admin:share_networks:share_network_detail' share.share_network_id as sn_url%}
{{ share.share_network_id }}
{% endif %} {% if share.share_group_id %}
{% trans "Share Group" %}
{% url 'horizon:admin:share_groups:detail' share.share_group_id as sg_url%}
{{ share.share_group_id }}
{% endif %}
{% trans "Mount snapshot support" %}
{{ share.mount_snapshot_support }}
{% trans "Created" %}
{{ share.created_at|parse_date }}
{% trans "Host" %}
{{ share.host }}
{% trans "Task state" %}
{{ share.task_state }}

{% trans "Access Rules" %}


{% for rule in share.rules %}
{{ rule.access_type }}

Access to: {{ rule.access_to }}
Access Level: {{ rule.access_level }}
Status: {{ rule.state }}
Access Key: {{ rule.access_key }}

{% endfor %}

{% trans "Metadata" %}


{% for key, value in share.metadata.items %}
{{ key }}
{{ value }}
{% endfor %}
manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/_manage_share.html000066400000000000000000000006031323215354300310200ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description:" %}

{% blocktrans %} "Manage" an existing share from a Manila host. This will make the share visible within OpenStack.

This is equivalent to the 'manila manage' command. {% endblocktrans %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/_migration_cancel.html000066400000000000000000000005171323215354300317100ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description:" %}

{% blocktrans %} Cancel migration of a migrating share.

This is equivalent to the 'manila migration-cancel' command. {% endblocktrans %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/_migration_complete.html000066400000000000000000000006331323215354300322720ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description:" %}

{% blocktrans %} Complete migration of a migrating share to another Manila host. This operation is expected to be disruptive.

This is equivalent to the 'manila migration-complete' command. {% endblocktrans %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/_migration_get_progress.html000066400000000000000000000005371323215354300331700ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description:" %}

{% blocktrans %} Obtains migration progress of a migrating share.

This is equivalent to the 'manila migration-get-progress' command. {% endblocktrans %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/_migration_start.html000066400000000000000000000006321323215354300316160ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description:" %}

{% blocktrans %} Migrate an existing share to another Manila host. This will move all your share data from one host to another.

This is equivalent to the 'manila migration-start' command. {% endblocktrans %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/_unmanage_share.html000066400000000000000000000006371323215354300313720ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description:" %}

{% blocktrans %} When a share is "unmanaged", the share will no longer be visible within OpenStack. Note that the share will not be deleted.

This is equivalent to the 'manila unmanage' command. {% endblocktrans %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/detail.html000066400000000000000000000003331323215354300275110ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/index.html000066400000000000000000000003271323215354300273610ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Shares" %}{% endblock %} {% block main %}
{{ shares_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/manage_share.html000066400000000000000000000002711323215354300306620ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Manage Share" %}{% endblock %} {% block main %} {% include 'admin/shares/_manage_share.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/migration_cancel.html000066400000000000000000000003011323215354300315400ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Cancel Migration" %}{% endblock %} {% block main %} {% include 'admin/shares/_migration_cancel.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/migration_complete.html000066400000000000000000000003051323215354300321270ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Complete Migration" %}{% endblock %} {% block main %} {% include 'admin/shares/_migration_complete.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/migration_get_progress.html000066400000000000000000000003151323215354300330230ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Get Migration Progress" %}{% endblock %} {% block main %} {% include 'admin/shares/_migration_get_progress.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/migration_start.html000066400000000000000000000002751323215354300314620ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Migrate Share" %}{% endblock %} {% block main %} {% include 'admin/shares/_migration_start.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas/000077500000000000000000000000001323215354300271645ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas/_detail_overview.html000066400000000000000000000027101323215354300334010ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Replica Overview" %}


{% trans "ID" %}
{{ replica.id }}
{% trans "Share" %}
{% url 'horizon:admin:shares:detail' replica.share_id as share_url%}
{{ replica.share_id }}
{% trans "Status" %}
{{ replica.status|capfirst }}
{% trans "Replica state" %}
{{ replica.replica_state|capfirst }}
{% trans "Export locations" %}
{% for el in replica.export_locations %}

Path:
Preferred: {{ el.preferred }}
{% if el.is_admin_only == True or el.is_admin_only == False %}
Is admin only: {{ el.is_admin_only }}
{% endif %}

{% endfor %}
{% trans "Availability zone" %}
{{ replica.availability_zone }}
{% trans "Created" %}
{{ replica.created_at|parse_date }}
{% trans "Updated" %}
{{ replica.updated_at|parse_date }}
{% trans "Host" %}
{{ replica.host }}
_reset_replica_state.html000066400000000000000000000003031323215354300341470ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Reset share replica's state with ID" %} "{{ replica_id }}"

{% endblock %} _reset_replica_status.html000066400000000000000000000003041323215354300343530ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Reset share replica's status with ID" %} "{{ replica_id }}"

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas/_resync_replica.html000066400000000000000000000002671323215354300332200ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body %}

{% trans "Resync share replica with ID" %} "{{ replica_id }}"?

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas/detail.html000066400000000000000000000003351323215354300313150ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Replica Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas/manage_replicas.html000066400000000000000000000002341323215354300331630ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Replicas" %}{% endblock %} {% block main %} {{ table.render }} {% endblock %} reset_replica_state.html000066400000000000000000000003201323215354300340070ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Reset Replica State" %}{% endblock %} {% block main %} {% include 'admin/shares/replicas/_reset_replica_state.html' %} {% endblock %} reset_replica_status.html000066400000000000000000000003221323215354300342140ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Reset Replica Status" %}{% endblock %} {% block main %} {% include 'admin/shares/replicas/_reset_replica_status.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/replicas/resync_replica.html000066400000000000000000000003061323215354300330530ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Resync Replica" %}{% endblock %} {% block main %} {% include 'admin/shares/replicas/_resync_replica.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/templates/shares/unmanage_share.html000066400000000000000000000002751323215354300312310ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Unmanage Share" %}{% endblock %} {% block main %} {% include 'admin/shares/_unmanage_share.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/admin/shares/urls.py000066400000000000000000000054331323215354300234430ustar00rootroot00000000000000# 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 django.conf import urls from manila_ui.dashboards.admin.shares.replicas import views as replica_views from manila_ui.dashboards.admin.shares import views from manila_ui import features urlpatterns = [ urls.url( r'^$', views.SharesView.as_view(), name='index'), urls.url( r'^(?P[^/]+)/$', views.DetailView.as_view(), name='detail'), urls.url( r'^manage$', views.ManageShareView.as_view(), name='manage'), urls.url( r'^unmanage/(?P[^/]+)$', views.UnmanageShareView.as_view(), name='unmanage'), ] if features.is_replication_enabled(): urlpatterns.extend([ urls.url( r'^(?P[^/]+)/replicas/$', replica_views.ManageReplicasView.as_view(), name='manage_replicas'), urls.url( r'^replica/(?P[^/]+)$', replica_views.DetailReplicaView.as_view(), name='replica_detail'), urls.url( r'^replica/(?P[^/]+)/resync_replica$', replica_views.ResyncReplicaView.as_view(), name='resync_replica'), urls.url( r'^replica/(?P[^/]+)/reset_replica_status$', replica_views.ResetReplicaStatusView.as_view(), name='reset_replica_status'), urls.url( r'^replica/(?P[^/]+)/reset_replica_state$', replica_views.ResetReplicaStateView.as_view(), name='reset_replica_state'), ]) if features.is_migration_enabled(): urlpatterns.extend([ urls.url( r'^migration_start/(?P[^/]+)$', views.MigrationStartView.as_view(), name='migration_start'), urls.url( r'^migration_complete/(?P[^/]+)$', views.MigrationCompleteView.as_view(), name='migration_complete'), urls.url( r'^migration_cancel/(?P[^/]+)$', views.MigrationCancelView.as_view(), name='migration_cancel'), urls.url( r'^migration_get_progress/(?P[^/]+)$', views.MigrationGetProgressView.as_view(), name='migration_get_progress'), ]) manila-ui-2.13.0/manila_ui/dashboards/admin/shares/views.py000066400000000000000000000237311323215354300236140ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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. """ Admin views for managing shares. """ from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon.utils import memoized from manila_ui.api import manila from manila_ui.dashboards.admin.shares import forms as project_forms from manila_ui.dashboards.admin.shares import tables as s_tables from manila_ui.dashboards.admin.shares import tabs as s_tabs from manila_ui.dashboards.admin import utils from manila_ui.dashboards.project.shares import views as share_views class SharesView(tables.MultiTableView, share_views.ShareTableMixIn): table_classes = ( s_tables.SharesTable, ) template_name = "admin/shares/index.html" page_title = _("Shares") @memoized.memoized_method def get_shares_data(self): shares = [] try: shares = manila.share_list( self.request, search_opts={'all_tenants': True}) snapshots = manila.share_snapshot_list( self.request, detailed=True, search_opts={'all_tenants': True}) share_ids_with_snapshots = [] for snapshot in snapshots: share_ids_with_snapshots.append(snapshot.to_dict()['share_id']) for share in shares: if share.to_dict()['id'] in share_ids_with_snapshots: setattr(share, 'has_snapshot', True) else: setattr(share, 'has_snapshot', False) except Exception: exceptions.handle( self.request, _('Unable to retrieve share list.')) # Gather our projects to correlate against IDs utils.set_project_name_to_objects(self.request, shares) return shares class DetailView(share_views.DetailView): tab_group_class = s_tabs.ShareDetailTabs template_name = "admin/shares/detail.html" def get_context_data(self, **kwargs): context = super(DetailView, self).get_context_data(**kwargs) context["page_title"] = _("Share Details: %(share_name)s") % { 'share_name': context["share_display_name"]} return context class ManageShareView(forms.ModalFormView): form_class = project_forms.ManageShare form_id = "manage_share" template_name = 'admin/shares/manage_share.html' modal_header = _("Manage Share") modal_id = "manage_share_modal" submit_label = _("Manage") success_url = reverse_lazy('horizon:admin:shares:index') submit_url = reverse_lazy('horizon:admin:shares:manage') page_title = _("Manage Share") def get_context_data(self, **kwargs): context = super(ManageShareView, self).get_context_data(**kwargs) return context class MigrationStartView(forms.ModalFormView): form_class = project_forms.MigrationStart template_name = 'admin/shares/migration_start.html' modal_header = _("Migrate Share") form_id = "migration_start_share" modal_id = "migration_start_share_modal" submit_label = _("Start migration") success_url = reverse_lazy('horizon:admin:shares:index') submit_url = 'horizon:admin:shares:migration_start' cancel_url = reverse_lazy('horizon:admin:shares:index') page_title = _("Migrate a Share") def get_context_data(self, **kwargs): context = super(MigrationStartView, self).get_context_data(**kwargs) args = (self.kwargs['share_id'],) context['submit_url'] = reverse(self.submit_url, args=args) return context @memoized.memoized_method def get_data(self): try: share_id = self.kwargs['share_id'] share = manila.share_get(self.request, share_id) except Exception: exceptions.handle( self.request, _('Unable to retrieve share details.'), redirect=self.success_url) return share def get_initial(self): share = self.get_data() return { 'share_id': self.kwargs["share_id"], 'name': share.name, } class MigrationCompleteView(forms.ModalFormView): form_class = project_forms.MigrationComplete template_name = 'admin/shares/migration_complete.html' modal_header = _("Confirm Migration Completion of Share") form_id = "migration_complete_share" modal_id = "migration_complete_share_modal" submit_label = _("Complete Migration") success_url = reverse_lazy('horizon:admin:shares:index') submit_url = 'horizon:admin:shares:migration_complete' cancel_url = reverse_lazy('horizon:admin:shares:index') page_title = _("Complete migration of a Share") def get_context_data(self, **kwargs): context = super(MigrationCompleteView, self).get_context_data(**kwargs) args = (self.kwargs['share_id'],) context['submit_url'] = reverse(self.submit_url, args=args) return context @memoized.memoized_method def get_data(self): try: share_id = self.kwargs['share_id'] share = manila.share_get(self.request, share_id) except Exception: exceptions.handle( self.request, _('Unable to retrieve share details.'), redirect=self.success_url) return share def get_initial(self): share = self.get_data() return { 'share_id': self.kwargs["share_id"], 'name': share.name, } class MigrationCancelView(forms.ModalFormView): form_class = project_forms.MigrationCancel template_name = 'admin/shares/migration_cancel.html' modal_header = _("Confirm Migration Cancelling of Share") form_id = "migration_cancel_share" modal_id = "migration_cancel_share_modal" submit_label = _("Cancel Migration") success_url = reverse_lazy('horizon:admin:shares:index') submit_url = 'horizon:admin:shares:migration_cancel' cancel_url = reverse_lazy('horizon:admin:shares:index') page_title = _("Cancel migration of a Share") def get_context_data(self, **kwargs): context = super(MigrationCancelView, self).get_context_data(**kwargs) args = (self.kwargs['share_id'],) context['submit_url'] = reverse(self.submit_url, args=args) return context @memoized.memoized_method def get_data(self): try: share_id = self.kwargs['share_id'] share = manila.share_get(self.request, share_id) except Exception: exceptions.handle( self.request, _('Unable to retrieve share details.'), redirect=self.success_url) return share def get_initial(self): share = self.get_data() return { 'share_id': self.kwargs["share_id"], 'name': share.name, } class MigrationGetProgressView(forms.ModalFormView): form_class = project_forms.MigrationGetProgress template_name = 'admin/shares/migration_get_progress.html' modal_header = _("Confirm Obtaining migration progress of Share") form_id = "migration_get_progress_share" modal_id = "migration_get_progress_share_modal" submit_label = _("Obtain Progress") success_url = reverse_lazy('horizon:admin:shares:index') submit_url = 'horizon:admin:shares:migration_get_progress' cancel_url = reverse_lazy('horizon:admin:shares:index') page_title = _("Obtain migration progress of a Share") def get_context_data(self, **kwargs): context = super(MigrationGetProgressView, self).get_context_data(**kwargs) args = (self.kwargs['share_id'],) context['submit_url'] = reverse(self.submit_url, args=args) return context @memoized.memoized_method def get_data(self): try: share_id = self.kwargs['share_id'] share = manila.share_get(self.request, share_id) except Exception: exceptions.handle( self.request, _('Unable to retrieve share details.'), redirect=self.success_url) return share def get_initial(self): share = self.get_data() return { 'share_id': self.kwargs["share_id"], 'name': share.name, } class UnmanageShareView(forms.ModalFormView): form_class = project_forms.UnmanageShare form_id = "unmanage_share" template_name = 'admin/shares/unmanage_share.html' modal_header = _("Confirm Unmanage Share") modal_id = "unmanage_share_modal" submit_label = _("Unmanage") success_url = reverse_lazy('horizon:admin:shares:index') submit_url = 'horizon:admin:shares:unmanage' page_title = _("Unmanage Share") def get_context_data(self, **kwargs): context = super(UnmanageShareView, self).get_context_data(**kwargs) args = (self.kwargs['share_id'],) context['submit_url'] = reverse(self.submit_url, args=args) return context @memoized.memoized_method def get_data(self): try: share_id = self.kwargs['share_id'] share = manila.share_get(self.request, share_id) except Exception: exceptions.handle( self.request, _('Unable to retrieve volume details.'), redirect=self.success_url) return share def get_initial(self): share = self.get_data() return { 'share_id': self.kwargs["share_id"], 'name': share.name, 'host': getattr(share, "host"), } manila-ui-2.13.0/manila_ui/dashboards/admin/utils.py000066400000000000000000000030721323215354300223260ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 oslo_utils import timeutils from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from openstack_dashboard.api import keystone PROJECTS = {} TIME = None def set_project_name_to_objects(request, objects): global PROJECTS, TIME try: # NOTE(vponomaryov): we will use saved values making lots of requests # in short period of time. 'memoized' is not suitable here now = timeutils.now() if TIME is None: TIME = now if not PROJECTS or now > TIME + 20: projects, has_more = keystone.tenant_list(request) PROJECTS = {t.id: t for t in projects} TIME = now except Exception: msg = _('Unable to retrieve list of projects.') exceptions.handle(request, msg) for obj in objects: project_id = getattr(obj, "project_id", None) project = PROJECTS.get(project_id, None) obj.project_name = getattr(project, "name", None) manila-ui-2.13.0/manila_ui/dashboards/project/000077500000000000000000000000001323215354300211705ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/__init__.py000066400000000000000000000013661323215354300233070ustar00rootroot00000000000000#!/usr/bin/env python # 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. # Specify a custom application configuration. The comments in that class give # more background about why this is needed. default_app_config = 'manila_ui.dashboards.project.config.Config' manila-ui-2.13.0/manila_ui/dashboards/project/config.py000066400000000000000000000023471323215354300230150ustar00rootroot00000000000000#!/usr/bin/env python # 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. # # Starting with Django 1.7, when a django app is loaded, it is assigned a # default label containing the portion of the application name after the last # period, and this name has to be globally unique. When horizon project # dashboard, openstack_dashboard.dashboards.project, is loaded, it is assigned # the label 'project'. But when the manila dashboard # manila_ui.dashboards.project is loaded, it label will conflict with # horizon's. Therefore this AppConfig class exists merely to specify a unique # configuration label and avoid this conflict. # from django import apps class Config(apps.AppConfig): name = 'manila_ui.dashboards.project' label = 'manila_project' manila-ui-2.13.0/manila_ui/dashboards/project/security_services/000077500000000000000000000000001323215354300247425ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/__init__.py000066400000000000000000000000001323215354300270410ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/forms.py000066400000000000000000000076221323215354300264510ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, 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 django.core.urlresolvers import reverse from django.forms import ValidationError # noqa from django.template.defaultfilters import filesizeformat # noqa from django.utils.translation import ugettext_lazy as _ from django.views.decorators.debug import sensitive_variables # noqa from horizon import exceptions from horizon import forms from horizon import messages from horizon.utils.memoized import memoized # noqa from manila_ui.api import manila class Create(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Name")) dns_ip = forms.CharField(max_length="15", label=_("DNS IP")) server = forms.CharField(max_length="255", label=_("Server")) domain = forms.CharField(max_length="255", label=_("Domain")) user = forms.CharField(max_length="255", label=_("User"), required=False) password = forms.CharField( label=_("Password"), widget=forms.PasswordInput(render_value=False), required=False) confirm_password = forms.CharField( label=_("Confirm Password"), widget=forms.PasswordInput(render_value=False)) type = forms.ChoiceField(choices=(("", ""), ("active_directory", "Active Directory"), ("ldap", "LDAP"), ("kerberos", "Kerberos")), label=_("Type")) description = forms.CharField(widget=forms.Textarea, label=_("Description"), required=False) def clean(self): '''Check to make sure password fields match.''' data = super(forms.Form, self).clean() if 'password' in data: if data['password'] != data.get('confirm_password', None): raise ValidationError(_('Passwords do not match.')) return data @sensitive_variables('data') def handle(self, request, data): try: data.pop('confirm_password') security_service = manila.security_service_create( request, **data) messages.success(request, _('Successfully created security ' 'service: %s') % data['name']) return security_service except Exception: exceptions.handle(request, _('Unable to create security service.')) return False class Update(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Share Name")) description = forms.CharField( widget=forms.Textarea, label=_("Description"), required=False) def handle(self, request, data): sec_service_id = self.initial['sec_service_id'] try: manila.security_service_update(request, sec_service_id, name=data['name'], description=data['description']) message = _('Successfully updated security service ' '"%s"') % data['name'] messages.success(request, message) return True except Exception: redirect = reverse("horizon:project:security_services:index") exceptions.handle(request, _('Unable to update security service.'), redirect=redirect) manila-ui-2.13.0/manila_ui/dashboards/project/security_services/panel.py000066400000000000000000000016721323215354300264210ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.project import dashboard class SecurityServices(horizon.Panel): name = _("Security Services") slug = 'security_services' permissions = ( 'openstack.services.share', ) dashboard.Project.register(SecurityServices) manila-ui-2.13.0/manila_ui/dashboards/project/security_services/tables.py000066400000000000000000000054321323215354300265720ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, 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 django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import tables from manila_ui.api import manila class Create(tables.LinkAction): name = "create_security_service" verbose_name = _("Create Security Service") url = "horizon:project:security_services:security_service_create" classes = ("ajax-modal", "btn-create") icon = "plus" policy_rules = (("share", "security_service:create"),) class Delete(tables.DeleteAction): policy_rules = (("share", "security_service:delete"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Security Service", u"Delete Security Services", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Security Service", u"Deleted Security Services", count ) def delete(self, request, obj_id): manila.security_service_delete(request, obj_id) class Edit(tables.LinkAction): name = "edit" verbose_name = _("Edit Security Service") url = "horizon:project:security_services:security_service_update" classes = ("ajax-modal", "btn-create") policy_rules = (("share", "security_service:update"),) class SecurityServicesTable(tables.DataTable): name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:project:security_services:security_service_detail") dns_ip = tables.Column("dns_ip", verbose_name=_("DNS IP")) server = tables.Column("server", verbose_name=_("Server")) domain = tables.Column("domain", verbose_name=_("Domain")) user = tables.Column("user", verbose_name=_("User")) def get_object_display(self, security_service): return security_service.name or str(security_service.id) def get_object_id(self, security_service): return str(security_service.id) class Meta(object): name = "security_services" verbose_name = _("Security Services") table_actions = ( tables.NameFilterAction, Create, Delete) row_actions = ( Edit, Delete) manila-ui-2.13.0/manila_ui/dashboards/project/security_services/tabs.py000066400000000000000000000020141323215354300262420ustar00rootroot00000000000000# # 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class OverviewTab(tabs.Tab): name = _("Overview") slug = "overview" template_name = ("project/security_services/_detail.html") def get_context_data(self, request): return {"sec_service": self.tab_group.kwargs['sec_service']} class SecurityServiceDetailTabs(tabs.TabGroup): slug = "security_service_details" tabs = ( OverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/000077500000000000000000000000001323215354300267405ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services/000077500000000000000000000000001323215354300325125ustar00rootroot00000000000000_add.html000066400000000000000000000033441323215354300342140ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block form_id %}{% endblock %} {% block form_action %}{% url 'horizon:project:security_service:add_security_service' share_network.id %}{% endblock %} {% block modal_id %}add_security_service_modal{% endblock %} {% block modal-header %}{% trans "Add Security Service" %}{% endblock %} {% block modal-body %}
{% include "horizon/common/_form_fields.html" %}

{% trans "Description" %}:

{% blocktrans %} The security service can be used by backend drivers to configure clients, for more secure using of share. {% endblocktrans %}

{% include "horizon/common/_form_fields.html" %}
{{ step.get_help_text }}
{% endblock %} {% block modal-footer %} {% trans "Cancel" %} {% endblock %} _create.html000066400000000000000000000004671323215354300347320ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% blocktrans %} The security service can be used by backend drivers to configure clients, for more secure using of share. {% endblocktrans %}

{% endblock %} _detail.html000066400000000000000000000020171323215354300347220ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services{% load i18n sizeformat parse_date %}

{% trans "Security Service Overview" %}


{% trans "Type" %}
{{ sec_service.type }}
{% trans "Name" %}
{{ sec_service.name }}
{% trans "ID" %}
{{ sec_service.id }}
{% if sec_service.description %}
{% trans "Description" %}
{{ sec_service.description }}
{% endif %}
{% trans "Created at" %}
{{ sec_service.created_at|parse_date }}

{% trans "Security Service Details" %}


{% trans "DNS IP" %}
{{ sec_service.dns_ip }}
{% trans "Server" %}
{{ sec_service.server }}
{% trans "Domain" %}
{{ sec_service.domain }}
{% trans "User" %}
{{ sec_service.user }}
_update.html000066400000000000000000000003621323215354300347430ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "From here you can modify name and description of a security service." %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services/add.html000066400000000000000000000003101323215354300341220ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Security Service" %}{% endblock %} {% block main %} {% include 'project/security_services/_add.html' %} {% endblock %} create.html000066400000000000000000000003131323215354300345610ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Security Service" %}{% endblock %} {% block main %} {% include 'project/security_services/_create.html' %} {% endblock %} detail.html000066400000000000000000000003461323215354300345660ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Security Service Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} index.html000066400000000000000000000003551323215354300344330ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Security Services" %}{% endblock %} {% block main %}
{{ security_services_table.render }}
{% endblock %} update.html000066400000000000000000000003111323215354300345760ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/security_services/templates/security_services{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Edit Security Service" %}{% endblock %} {% block main %} {% include 'project/security_services/_update.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/security_services/urls.py000066400000000000000000000022751323215354300263070ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.conf import urls from manila_ui.dashboards.project.security_services import views urlpatterns = [ urls.url( r'^$', views.SecurityServicesView.as_view(), name='index'), urls.url( r'^create_security_service$', views.CreateView.as_view(), name='security_service_create'), urls.url( r'^(?P[^/]+)/update/$', views.UpdateView.as_view(), name='security_service_update'), urls.url( r'^(?P[^/]+)$', views.Detail.as_view(), name='security_service_detail'), ] manila-ui-2.13.0/manila_ui/dashboards/project/security_services/views.py000066400000000000000000000146241323215354300264600ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon import tabs from horizon.utils import memoized from manila_ui.api import manila from manila_ui.dashboards.project.security_services import forms as ss_forms from manila_ui.dashboards.project.security_services import tables as ss_tables from manila_ui.dashboards.project.security_services import tabs as ss_tabs from manila_ui.dashboards.project.share_networks import forms as sn_forms from manila_ui.dashboards import utils class SecurityServicesView(tables.MultiTableView): table_classes = ( ss_tables.SecurityServicesTable, ) template_name = "project/security_services/index.html" page_title = _("Security Services") @memoized.memoized_method def get_security_services_data(self): try: security_services = manila.security_service_list(self.request) except Exception: security_services = [] exceptions.handle( self.request, _("Unable to retrieve security services")) return security_services class UpdateView(forms.ModalFormView): template_name = "project/security_services/update.html" form_class = ss_forms.Update form_id = "update_security_service" modal_header = _("Edit Security Service") modal_id = "update_security_service_modal" submit_label = _("Edit") submit_url = "horizon:project:security_services:security_service_update" success_url = reverse_lazy("horizon:project:security_services:index") page_title = _('Edit Security Service') def get_object(self): if not hasattr(self, "_object"): sec_service_id = self.kwargs['sec_service_id'] try: self._object = manila.security_service_get( self.request, sec_service_id) except Exception: msg = _('Unable to retrieve security_service.') url = reverse('horizon:project:security_services:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(UpdateView, self).get_context_data(**kwargs) return context def get_initial(self): self.submit_url = reverse(self.submit_url, kwargs=self.kwargs) sec_service = self.get_object() return {'sec_service_id': self.kwargs["sec_service_id"], 'name': sec_service.name, 'description': sec_service.description} class CreateView(forms.ModalFormView): form_class = ss_forms.Create form_id = "create_security_service" template_name = 'project/security_services/create.html' modal_header = _("Create Security Service") modal_id = "create_security_service_modal" submit_label = _("Create") submit_url = reverse_lazy( "horizon:project:security_services:security_service_create") success_url = reverse_lazy("horizon:project:security_services:index") page_title = _('Create Security Service') class AddSecurityServiceView(forms.ModalFormView): form_class = sn_forms.AddSecurityServiceForm template_name = 'project/security_services/add.html' success_url = 'horizon:project:security_services:index' page_title = _('Add Security Service') def get_object(self): if not hasattr(self, "_object"): share_id = self.kwargs['share_network_id'] try: self._object = manila.share_network_get(self.request, share_id) except Exception: msg = _('Unable to retrieve share network.') url = reverse('horizon:project:security_services:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(AddSecurityServiceView, self).get_context_data(**kwargs) context['share_network'] = self.get_object() return context def get_initial(self): share_net = self.get_object() return {'share_net_id': self.kwargs["share_network_id"], 'name': share_net.name, 'description': share_net.description} class Detail(tabs.TabView): tab_group_class = ss_tabs.SecurityServiceDetailTabs template_name = 'project/security_services/detail.html' redirect_url = reverse_lazy('horizon:project:security_services:index') def get_context_data(self, **kwargs): context = super(Detail, self).get_context_data(**kwargs) sec_service = self.get_data() context["sec_service"] = sec_service sec_service_display_name = sec_service.name or sec_service.id context["sec_service_display_name"] = sec_service_display_name context["page_title"] = _("Security Service Details: " "%(service_display_name)s") % \ {'service_display_name': sec_service_display_name} return context @memoized.memoized_method def get_data(self): try: sec_service_id = self.kwargs['sec_service_id'] sec_service = manila.security_service_get( self.request, sec_service_id) sec_service.type = utils.get_nice_security_service_type( sec_service) except Exception: message = _("Unable to retrieve security service " "'%s' details.") % sec_service_id exceptions.handle( self.request, message, redirect=self.redirect_url) return sec_service def get_tabs(self, request, *args, **kwargs): sec_service = self.get_data() return self.tab_group_class(request, sec_service=sec_service, **kwargs) manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/000077500000000000000000000000001323215354300256105ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/__init__.py000066400000000000000000000000001323215354300277070ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/forms.py000066400000000000000000000056201323215354300273130ustar00rootroot00000000000000# Copyright 2017 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 django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from manila_ui.api import manila class CreateShareGroupSnapshotForm(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Name"), required=True) description = forms.CharField( widget=forms.Textarea, label=_("Description"), required=False) def __init__(self, request, *args, **kwargs): super(self.__class__, self).__init__(request, *args, **kwargs) # populate share_group_id sg_id = kwargs.get('initial', {}).get('share_group_id', []) self.fields['share_group_id'] = forms.CharField( widget=forms.HiddenInput(), initial=sg_id) def handle(self, request, data): try: snapshot = manila.share_group_snapshot_create( request, data['share_group_id'], data['name'], data['description']) message = _('Creating share group snapshot "%s".') % data['name'] messages.success(request, message) return snapshot except Exception: redirect = reverse("horizon:project:share_group_snapshots:index") exceptions.handle( request, _('Unable to create share group snapshot.'), redirect=redirect) return False class UpdateShareGroupSnapshotForm(forms.SelfHandlingForm): name = forms.CharField( max_length="255", label=_("Name")) description = forms.CharField( widget=forms.Textarea, label=_("Description"), required=False) def handle(self, request, data): sgs_id = self.initial['share_group_snapshot_id'] try: manila.share_group_snapshot_update( request, sgs_id, data['name'], data['description']) message = _('Updating share group snapshot "%s"') % data['name'] messages.success(request, message) return True except Exception: redirect = reverse("horizon:project:share_group_snapshots:index") exceptions.handle( request, _('Unable to update share group snapshot.'), redirect=redirect) return False manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/panel.py000066400000000000000000000017371323215354300272710ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.project import dashboard class ShareGroupSnapshots(horizon.Panel): name = _("Share Group Snapshots") slug = 'share_group_snapshots' permissions = ( 'openstack.services.share', ) dashboard.Project.register(ShareGroupSnapshots) manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/tables.py000066400000000000000000000132031323215354300274330ustar00rootroot00000000000000# Copyright 2017 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 django.core.urlresolvers import reverse from django.template.defaultfilters import title # noqa from django.utils.http import urlencode # noqa from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import tables from horizon.utils import filters from manila_ui.api import manila class UpdateShareGroupSnapshot(tables.LinkAction): name = "update_share_group_snapshot" verbose_name = _("Update") url = "horizon:project:share_group_snapshots:update" classes = ("ajax-modal", "btn-camera") def allowed(self, request, share_group_snapshot=None): return share_group_snapshot.status in ("available", "error") class CreateShareGroupSnapshot(tables.LinkAction): name = "create_share_group_snapshot" verbose_name = _("Create Share Group Snapshot") url = "horizon:project:share_group_snapshots:create" classes = ("ajax-modal", "btn-camera") def allowed(self, request, share_group=None): self.verbose_name = _("Create Share Group Snapshot") classes = [c for c in self.classes if c != "disabled"] self.classes = classes return share_group.status == "available" class CreateShareGroupFromSnapshot(tables.LinkAction): name = "create_share_group_from_snapshot" verbose_name = _("Create Share Group") url = "horizon:project:share_groups:create" classes = ("ajax-modal", "btn-camera") def get_link_url(self, datum): base_url = reverse(self.url) params = urlencode({ "snapshot_id": self.table.get_object_id(datum)}) return "?".join([base_url, params]) def allowed(self, request, share_group=None): return share_group.status == "available" class ShareGroupSnapshotShareGroupNameColumn(tables.Column): def get_link_url(self, snapshot): return reverse(self.link, args=(snapshot.share_group_id,)) class DeleteShareGroupSnapshot(tables.DeleteAction): @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Group Snapshot", u"Delete Share Group Snapshots", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Group Snapshot", u"Deleted Share Group Snapshots", count ) def delete(self, request, obj_id): obj = self.table.get_object_by_id(obj_id) name = self.table.get_object_display(obj) try: manila.share_group_snapshot_delete(request, obj_id) except Exception: msg = _('Unable to delete share group snapshot "%s". ' 'One or more share groups depend on it.') exceptions.check_message(["snapshots", "dependent"], msg % name) raise def allowed(self, request, snapshot=None): if snapshot: return snapshot.status.lower() in ('available', 'error') return True class UpdateShareGroupSnapshotRow(tables.Row): ajax = True def get_data(self, request, share_group_snapshot_id): snapshot = manila.share_group_snapshot_get( request, share_group_snapshot_id) if not snapshot.name: snapshot.name = share_group_snapshot_id return snapshot class ShareGroupSnapshotsTable(tables.DataTable): STATUS_CHOICES = ( ("available", True), ("creating", None), ("error", False), ) STATUS_DISPLAY_CHOICES = ( ("available", pgettext_lazy("Current status of snapshot", u"Available")), ("creating", pgettext_lazy("Current status of snapshot", u"Creating")), ("error", pgettext_lazy("Current status of snapshot", u"Error")), ) name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:project:share_group_snapshots:detail") description = tables.Column( "description", verbose_name=_("Description"), truncate=40) created_at = tables.Column( "created_at", verbose_name=_("Created at"), filters=( filters.parse_isotime, )) status = tables.Column( "status", filters=(title,), verbose_name=_("Status"), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES) source = ShareGroupSnapshotShareGroupNameColumn( "share_group", verbose_name=_("Source"), link="horizon:project:share_groups:detail") def get_object_display(self, obj): return obj.name class Meta(object): name = "share_group_snapshots" verbose_name = _("Share Group Snapshots") status_columns = ["status"] row_class = UpdateShareGroupSnapshotRow table_actions = ( tables.NameFilterAction, DeleteShareGroupSnapshot, ) row_actions = ( CreateShareGroupFromSnapshot, UpdateShareGroupSnapshot, DeleteShareGroupSnapshot, ) manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/tabs.py000066400000000000000000000022751323215354300271210ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareGroupSnapshotOverviewTab(tabs.Tab): name = _("Share Group Snapshot Overview") slug = "share_group_snapshot_overview_tab" template_name = "project/share_group_snapshots/_detail.html" def get_context_data(self, request): return {"share_group_snapshot": self.tab_group.kwargs[ "share_group_snapshot"]} class ShareGroupSnapshotDetailTabs(tabs.TabGroup): slug = "share_group_snapshot_details" tabs = ( ShareGroupSnapshotOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/templates/000077500000000000000000000000001323215354300276065ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/templates/share_group_snapshots/000077500000000000000000000000001323215354300342265ustar00rootroot00000000000000_create.html000066400000000000000000000004001323215354300364310ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/templates/share_group_snapshots{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}
Please, choose a name for the new share group snapshot, that will be created from '{{ share_group_name }}' share group.
{% endblock %} _detail.html000066400000000000000000000016031323215354300364360ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/templates/share_group_snapshots{% load i18n sizeformat parse_date %}

{% trans "Share Group Snapshot Overview" %}


{% trans "Name" %}
{{ share_group_snapshot.name }}
{% trans "ID" %}
{{ share_group_snapshot.id }}
{% url 'horizon:project:share_groups:detail' share_group_snapshot.share_group_id as sg_url %}
{% trans "Source Share Group" %}
{{ share_group_snapshot.sg_name_or_id }}
{% if share_group_snapshot.description %}
{% trans "Description" %}
{{ share_group_snapshot.description }}
{% endif %}
{% trans "Status" %}
{{ share_group_snapshot.status|capfirst }}
{% trans "Created" %}
{{ share_group_snapshot.created_at|parse_date }}
_update.html000066400000000000000000000003621323215354300364570ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/templates/share_group_snapshots{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "From here you can modify name and description of a share group snapshot." %}

{% endblock %} create.html000066400000000000000000000003231323215354300362760ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/templates/share_group_snapshots{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Share Group Snapshot" %}{% endblock %} {% block main %} {% include 'project/share_group_snapshots/_create.html' %} {% endblock %} detail.html000066400000000000000000000003521323215354300362770ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/templates/share_group_snapshots{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Group Snapshot Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} index.html000066400000000000000000000003651323215354300361500ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/templates/share_group_snapshots{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Group Snapshots" %}{% endblock %} {% block main %}
{{ share_group_snapshots_table.render }}
{% endblock %} update.html000066400000000000000000000003231323215354300363150ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/templates/share_group_snapshots{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Update Share Group Snapshot" %}{% endblock %} {% block main %} {% include 'project/share_group_snapshots/_update.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/urls.py000066400000000000000000000025751323215354300271600ustar00rootroot00000000000000# Copyright 2017 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 django.conf import urls from manila_ui.dashboards.project.share_group_snapshots import views from manila_ui import features if features.is_share_groups_enabled(): urlpatterns = [ urls.url( r'^$', views.ShareGroupSnapshotsView.as_view(), name='index'), urls.url( r'^(?P[^/]+)/snapshot_create/$', views.CreateShareGroupSnapshotView.as_view(), name='create'), urls.url( r'^(?P[^/]+)/$', views.ShareGroupSnapshotDetailView.as_view(), name='detail'), urls.url( r'^(?P[^/]+)/update/$', views.UpdateShareGroupSnapshotView.as_view(), name='update'), ] manila-ui-2.13.0/manila_ui/dashboards/project/share_group_snapshots/views.py000066400000000000000000000152141323215354300273220ustar00rootroot00000000000000# Copyright 2017 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. """ Project views for managing share group snapshots. """ from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon import tabs from horizon.utils import memoized from manila_ui.api import manila import manila_ui.dashboards.project.share_group_snapshots.forms as sgs_forms import manila_ui.dashboards.project.share_group_snapshots.tables as sgs_tables import manila_ui.dashboards.project.share_group_snapshots.tabs as sgs_tabs class ShareGroupSnapshotsView(tables.MultiTableView): table_classes = ( sgs_tables.ShareGroupSnapshotsTable, ) template_name = "project/share_group_snapshots/index.html" page_title = _("Share Group Snapshots") @memoized.memoized_method def get_share_group_snapshots_data(self): share_group_snapshots = [] try: share_group_snapshots = manila.share_group_snapshot_list( self.request, search_opts={'all_tenants': True}) share_groups = manila.share_group_list(self.request) sg_names = dict([(sg.id, sg.name or sg.id) for sg in share_groups]) for snapshot in share_group_snapshots: snapshot.share_group = sg_names.get(snapshot.share_group_id) except Exception: msg = _("Unable to retrieve share group snapshot list.") exceptions.handle(self.request, msg) return share_group_snapshots class ShareGroupSnapshotDetailView(tabs.TabView): tab_group_class = sgs_tabs.ShareGroupSnapshotDetailTabs template_name = "project/share_group_snapshots/detail.html" redirect_url = reverse_lazy("horizon:project:share_group_snapshots:index") def get_context_data(self, **kwargs): context = super(ShareGroupSnapshotDetailView, self).get_context_data( **kwargs) snapshot = self.get_data() snapshot_display_name = snapshot.name or snapshot.id context["snapshot"] = snapshot context["snapshot_display_name"] = snapshot_display_name context["page_title"] = _( "Share Group Snapshot Details: %(sgs_display_name)s") % ( {'sgs_display_name': snapshot_display_name}) return context @memoized.memoized_method def get_data(self): try: share_group_snapshot = manila.share_group_snapshot_get( self.request, self.kwargs['share_group_snapshot_id']) sg = manila.share_group_get( self.request, share_group_snapshot.share_group_id) share_group_snapshot.sg_name_or_id = sg.name or sg.id except Exception: exceptions.handle( self.request, _('Unable to retrieve share group snapshot details.'), redirect=self.redirect_url) return share_group_snapshot def get_tabs(self, request, *args, **kwargs): return self.tab_group_class( request, share_group_snapshot=self.get_data(), **kwargs) class CreateShareGroupSnapshotView(forms.ModalFormView): form_class = sgs_forms.CreateShareGroupSnapshotForm form_id = "create_share_group_snapshot" template_name = 'project/share_group_snapshots/create.html' modal_header = _("Create Share Group Snapshot") modal_id = "create_share_group_snapshot_modal" submit_label = _("Create Share Group Snapshot") submit_url = "horizon:project:share_group_snapshots:create" success_url = reverse_lazy('horizon:project:share_group_snapshots:index') page_title = _('Create Share Group Snapshot') def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) sg_id = self.kwargs['share_group_id'] try: sg = manila.share_group_get(self.request, sg_id) context['share_group_name'] = sg.name or sg_id except Exception: exceptions.handle( self.request, _("Unable to get the specified share group '%s' for " "snapshot creation.") % sg_id) context['share_group_name'] = sg_id context['share_group_id'] = sg_id # TODO(vponomaryov): add support of quotas when it is implemented # for share group snapshots on server side. return context def get_initial(self): self.submit_url = reverse(self.submit_url, kwargs=self.kwargs) return {'share_group_id': self.kwargs["share_group_id"]} class UpdateShareGroupSnapshotView(forms.ModalFormView): form_class = sgs_forms.UpdateShareGroupSnapshotForm form_id = "update_share_group_snapshot" template_name = 'project/share_group_snapshots/update.html' modal_header = _("Update Share Group Snapshot") modal_id = "update_share_group_snapshot_modal" submit_label = _("Update") submit_url = "horizon:project:share_group_snapshots:update" success_url = reverse_lazy('horizon:project:share_group_snapshots:index') page_title = _('Update Share Group') @memoized.memoized_method def get_object(self): if not hasattr(self, "_object"): try: self._object = manila.share_group_snapshot_get( self.request, self.kwargs['share_group_snapshot_id']) except Exception: msg = _('Unable to retrieve share group snapshot.') url = reverse('horizon:project:share_group_snapshots:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) args = (self.get_object().id,) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): snapshot = self.get_object() return { 'share_group_snapshot_id': self.kwargs["share_group_snapshot_id"], 'name': snapshot.name, 'description': snapshot.description, } manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/000077500000000000000000000000001323215354300236715ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/__init__.py000066400000000000000000000000001323215354300257700ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/forms.py000066400000000000000000000260131323215354300253730ustar00rootroot00000000000000# Copyright 2017 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 django.core.urlresolvers import reverse from django.forms import ValidationError # noqa from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from horizon.utils import memoized import six from manila_ui.api import manila class CreateShareGroupForm(forms.SelfHandlingForm): name = forms.CharField(label=_("Name"), max_length="255", required=True) description = forms.CharField( label=_("Description"), max_length="255", widget=forms.Textarea(attrs={"rows": 3}), required=False) def __init__(self, request, *args, **kwargs): super(CreateShareGroupForm, self).__init__(request, *args, **kwargs) self.st_field_name_prefix = "share-type-choices-" self.fields["source_type"] = forms.ChoiceField( label=_("Source Type"), widget=forms.Select(attrs={ "class": "switchable", "data-slug": "source", }), required=False) self.fields["snapshot"] = forms.ChoiceField( label=_("Use share group snapshot as a source"), widget=forms.SelectWidget(attrs={ "class": "switched", "data-switch-on": "source", "data-source-snapshot": _("Share Group Snapshot"), }), required=True) if ("snapshot_id" in request.GET or kwargs.get("data", {}).get("snapshot")): try: snapshot = self.get_share_group_snapshot( request, request.GET.get( "snapshot_id", kwargs.get("data", {}).get("snapshot"))) self.fields["name"].initial = snapshot.name self.fields["snapshot"].choices = ( (snapshot.id, snapshot.name or snapshot.id), ) try: # Set the share group type from the original share group orig_sg = manila.share_group_get( request, snapshot.share_group_id) self.fields["sgt"].initial = orig_sg.share_group_type_id except Exception: pass del self.fields["source_type"] except Exception: exceptions.handle( request, _("Unable to load the specified share group snapshot.")) else: source_type_choices = [] try: snapshot_list = manila.share_group_snapshot_list(request) snapshots = [s for s in snapshot_list if s.status == "available"] if snapshots: source_type_choices.append(("snapshot", _("Snapshot"))) self.fields["snapshot"].choices = ( [("", _("Choose a snapshot"))] + [(s.id, s.name or s.id) for s in snapshots] ) else: del self.fields["snapshot"] except Exception: exceptions.handle( request, _("Unable to retrieve share group snapshots.")) if source_type_choices: choices = ([('none', _("No source, empty share group"))] + source_type_choices) self.fields["source_type"].choices = choices else: del self.fields["source_type"] self.fields["az"] = forms.ChoiceField( label=_("Availability Zone"), widget=forms.SelectWidget(attrs={ "class": "switched", "data-switch-on": "source", "data-source-none": _("Availability Zone"), }), required=False) availability_zones = manila.availability_zone_list(request) self.fields["az"].choices = ( [("", "")] + [(az.name, az.name) for az in availability_zones]) share_group_types = manila.share_group_type_list(request) self.fields["sgt"] = forms.ChoiceField( label=_("Share Group Type"), widget=forms.fields.SelectWidget(attrs={ "class": "switched switchable", "data-switch-on": "source", "data-source-none": _("Share Group Type"), "data-slug": "sgt", }), required=True) self.fields["sgt"].choices = ( [("", "")] + [(sgt.id, sgt.name) for sgt in share_group_types]) # NOTE(vponomaryov): create separate set of available share types # for each of share group types. share_types = manila.share_type_list(request) for sgt in share_group_types: st_choices = ( [(st.id, st.name) for st in share_types if st.id in sgt.share_types]) amount_of_choices = len(st_choices) st_field_name = self.st_field_name_prefix + sgt.id if amount_of_choices < 2: st_field = forms.ChoiceField( label=_("Share Types"), choices=st_choices, widget=forms.fields.SelectWidget(attrs={ "class": "switched", "data-switch-on": "sgt", "data-sgt-%s" % sgt.id: _( "Share Types (one available)"), }), required=True) else: height = min(30 * amount_of_choices, 155) st_field = forms.MultipleChoiceField( label=_("Share Types"), choices=st_choices, widget=forms.fields.widgets.SelectMultiple(attrs={ "style": "max-height: %spx;" % height, "class": "switched", "data-switch-on": "sgt", "data-sgt-%s" % sgt.id: _( "Share Types (multiple available)"), }), required=False) st_field.initial = st_choices[0] self.fields[st_field_name] = st_field self.fields["share_network"] = forms.ChoiceField( label=_("Share Network"), widget=forms.fields.SelectWidget(attrs={ "class": "switched", "data-switch-on": "source", "data-source-none": _("Share Network"), }), required=False) share_networks = manila.share_network_list(request) self.fields["share_network"].choices = ( [("", "")] + [(sn.id, sn.name or sn.id) for sn in share_networks]) def clean(self): cleaned_data = super(CreateShareGroupForm, self).clean() errors = [k for k in self.errors.viewkeys()] for k in errors: sgt_name = k.split(self.st_field_name_prefix)[-1] chosen_sgt = cleaned_data.get("sgt") if (k.startswith(self.st_field_name_prefix) and sgt_name != chosen_sgt): cleaned_data[k] = "Not set" self.errors.pop(k, None) source_type = cleaned_data.get("source_type") if source_type != "snapshot": self.errors.pop("snapshot", None) share_group_type = cleaned_data.get("sgt") if share_group_type: cleaned_data["share_types"] = cleaned_data.get( self.st_field_name_prefix + share_group_type) if isinstance(cleaned_data["share_types"], six.string_types): cleaned_data["share_types"] = [cleaned_data["share_types"]] else: self.errors.pop("sgt", None) return cleaned_data def handle(self, request, data): try: source_type = data.get('source_type') if (data.get("snapshot") and source_type in (None, 'snapshot')): snapshot = self.get_share_group_snapshot( request, data["snapshot"]) snapshot_id = snapshot.id source_sg = manila.share_group_get( request, snapshot.share_group_id) data['sgt'] = source_sg.share_group_type_id else: snapshot_id = None share_group = manila.share_group_create( request, name=data['name'], description=data['description'], share_group_type=data['sgt'], share_types=None if snapshot_id else data.get('share_types'), share_network=( None if snapshot_id else data.get('share_network')), source_share_group_snapshot=snapshot_id, availability_zone=None if snapshot_id else data['az']) message = _('Creating share group "%s"') % data['name'] messages.success(request, message) return share_group except ValidationError as e: self.api_error(e.messages[0]) return False except Exception: exceptions.handle(request, ignore=True) self.api_error(_("Unable to create share group.")) return False @memoized.memoized def get_share_group_snapshot(self, request, sg_snapshot_id): return manila.share_group_snapshot_get(request, sg_snapshot_id) class UpdateShareGroupForm(forms.SelfHandlingForm): name = forms.CharField( max_length="255", label=_("Share Group Name")) description = forms.CharField( widget=forms.Textarea, label=_("Description"), required=False) def handle(self, request, data): sg_id = self.initial['share_group_id'] try: manila.share_group_update( request, sg_id, data['name'], data['description']) message = _('Updating share group "%s"') % data['name'] messages.success(request, message) return True except Exception: redirect = reverse("horizon:project:share_groups:index") exceptions.handle( request, _('Unable to update share group.'), redirect=redirect) return False manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/panel.py000066400000000000000000000016751323215354300253530ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.project import dashboard class ShareGroups(horizon.Panel): name = _("Share Groups") slug = 'share_groups' permissions = ( 'openstack.services.share', ) dashboard.Project.register(ShareGroups) manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/tables.py000066400000000000000000000116561323215354300255260ustar00rootroot00000000000000# Copyright 2017 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 django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import tables import six from manila_ui.api import manila import manila_ui.dashboards.project.share_group_snapshots.tables as sgs_tables class UpdateShareGroup(tables.LinkAction): name = "update" verbose_name = _("Update") url = "horizon:project:share_groups:update" classes = ("ajax-modal", "btn-create") def allowed(self, request, share_group=None): return share_group.status in ("available", "error") class DeleteShareGroup(tables.DeleteAction): @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Group", u"Delete Share Groups", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Group", u"Deleted Share Groups", count ) def delete(self, request, obj_id): manila.share_group_delete(request, obj_id) def allowed(self, request, share_group=None): if share_group: # Row button return (share_group.status.lower() in ('available', 'error')) # Table button. Always return 'True' return True class CreateShareGroup(tables.LinkAction): name = "create" verbose_name = _("Create Share Group") url = "horizon:project:share_groups:create" classes = ("ajax-modal", "btn-create") icon = "plus" policy_rules = (("share", "share_group:create"),) def allowed(self, request, share=None): # TODO(vponomaryov): implement quota restriction when quota support # is implemented for share groups. return True class UpdateShareGroupRow(tables.Row): ajax = True def get_data(self, request, sg_id): sg = manila.share_group_get(request, sg_id) return sg class ShareGroupsTable(tables.DataTable): def get_share_network_link(share_group): if getattr(share_group, 'share_network_id', None): return reverse( "horizon:project:share_networks:share_network_detail", args=(share_group.share_network_id,)) else: return None def get_source_share_group_snapshot_link(share_group): if getattr(share_group, 'source_share_group_snapshot_id', None): return reverse( "horizon:project:share_group_snapshots:detail", args=(share_group.source_share_group_snapshot_id,)) else: return None STATUS_CHOICES = ( ("available", True), ("creating", None), ("deleting", None), ("error", False), ("error_deleting", False), ) STATUS_DISPLAY_CHOICES = ( ("available", u"Available"), ("creating", u"Creating"), ("deleting", u"Deleting"), ("error", u"Error"), ("error_deleting", u"Error deleting"), ) name = tables.Column( "name", verbose_name=_("Name"), link="horizon:project:share_groups:detail") status = tables.Column( "status", verbose_name=_("Status"), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES, ) availability_zone = tables.Column( "availability_zone", verbose_name=_("Availability Zone")) share_network_id = tables.Column( "share_network_id", verbose_name=_("Share Network"), link=get_share_network_link) source_share_group_snapshot_id = tables.Column( "source_share_group_snapshot_id", verbose_name=_("Source Share Group Snapshot"), link=get_source_share_group_snapshot_link) def get_object_display(self, share_group): return six.text_type(share_group.id) def get_object_id(self, share_group): return six.text_type(share_group.id) class Meta(object): name = "share_groups" verbose_name = _("Share Groups") status_columns = ("status", ) row_class = UpdateShareGroupRow table_actions = ( CreateShareGroup, tables.NameFilterAction, DeleteShareGroup, ) row_actions = ( sgs_tables.CreateShareGroupSnapshot, UpdateShareGroup, DeleteShareGroup, ) manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/tabs.py000066400000000000000000000021421323215354300251730ustar00rootroot00000000000000# Copyright 2017 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareGroupOverviewTab(tabs.Tab): name = _("Share Group Overview") slug = "share_group_overview_tab" template_name = "project/share_groups/_detail.html" def get_context_data(self, request): return {"share_group": self.tab_group.kwargs["share_group"]} class ShareGroupDetailTabs(tabs.TabGroup): slug = "share_group_details" tabs = ( ShareGroupOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/templates/000077500000000000000000000000001323215354300256675ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/templates/share_groups/000077500000000000000000000000001323215354300303705ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/templates/share_groups/_create.html000066400000000000000000000003331323215354300326570ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "Select parameters of share group you want to create. " %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/templates/share_groups/_detail.html000066400000000000000000000041771323215354300326700ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Group Overview" %}


{% trans "ID" %}
{{ share_group.id }}
{% trans "Name" %}
{{ share_group.name }}
{% trans "Description" %}
{{ share_group.description }}
{% trans "Status" %}
{{ share_group.status|capfirst }}
{% trans "Created" %}
{{ share_group.created_at|parse_date }}
{% if share_group.source_share_group_snapshot_id %}
{% trans "Source SG Snapshot" %}
{% url 'horizon:project:share_group_snapshots:detail' share_group.source_share_group_snapshot_id as ssgs_url%}
{{ share_group.source_share_group_snapshot_id }}
{% endif %}
{% trans "Share Group Type" %}
{{ share_group.share_group_type_id}}
{% if share_group.availability_zone %}
{% trans "Availability Zone" %}
{{ share_group.availability_zone }}
{% endif %} {% if share_group.share_network_id %}
{% trans "Share Network" %}
{% url 'horizon:project:share_networks:share_network_detail' share_group.share_network_id as sn_url%}
{{ share_group.share_network_id }}
{% endif %} {% if share_group.share_types %}
{% trans "Share Types" %}
{% for st in share_group.share_types %}

Share Type Name: {{ st.name }}
Share Type Visibility: {% if st.is_public %}Public{% else %}Private{% endif %}
Network handling enabled: {{ st.dhss }}

{% endfor %} {% endif %} {% if share_group.members %}
{% trans "Shares" %}
{% for m in share_group.members %} {% url 'horizon:project:shares:detail' m.id as share_url%}
{% endfor %} {% endif %}
manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/templates/share_groups/_update.html000066400000000000000000000003711323215354300327000ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "From here you can modify name, description and visibility of a share group." %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/templates/share_groups/create.html000066400000000000000000000003011323215354300325130ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Share Group" %}{% endblock %} {% block main %} {% include 'project/share_groups/_create.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/templates/share_groups/detail.html000066400000000000000000000003411323215354300325160ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Group Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/templates/share_groups/index.html000066400000000000000000000003431323215354300323650ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Groups" %}{% endblock %} {% block main %}
{{ share_groups_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/templates/share_groups/update.html000066400000000000000000000003011323215354300325320ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Update Share Group" %}{% endblock %} {% block main %} {% include 'project/share_groups/_update.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/urls.py000066400000000000000000000024361323215354300252350ustar00rootroot00000000000000# Copyright 2017 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 django.conf import urls from manila_ui.dashboards.project.share_groups import views from manila_ui import features if features.is_share_groups_enabled(): urlpatterns = [ urls.url( r'^$', views.ShareGroupsView.as_view(), name='index'), urls.url( r'^create/$', views.ShareGroupCreateView.as_view(), name='create'), urls.url( r'^(?P[^/]+)/$', views.ShareGroupDetailView.as_view(), name='detail'), urls.url( r'^(?P[^/]+)/update/$', views.ShareGroupUpdateView.as_view(), name='update'), ] manila-ui-2.13.0/manila_ui/dashboards/project/share_groups/views.py000066400000000000000000000130471323215354300254050ustar00rootroot00000000000000# Copyright 2017 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. """ Project views for managing share groups. """ from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon import tabs from horizon.utils import memoized from manila_ui.api import manila from manila_ui.dashboards.project.share_groups import forms as sg_forms from manila_ui.dashboards.project.share_groups import tables as sg_tables from manila_ui.dashboards.project.share_groups import tabs as sg_tabs class ShareGroupsView(tables.MultiTableView): table_classes = ( sg_tables.ShareGroupsTable, ) template_name = "project/share_groups/index.html" page_title = _("Share Groups") @memoized.memoized_method def get_share_groups_data(self): try: share_groups = manila.share_group_list( self.request, detailed=True) except Exception: share_groups = [] exceptions.handle( self.request, _("Unable to retrieve share groups.")) return share_groups class ShareGroupDetailView(tabs.TabView): tab_group_class = sg_tabs.ShareGroupDetailTabs template_name = 'project/share_groups/detail.html' def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) share_group = self.get_data() context["share_group"] = share_group context["page_title"] = ( _("Share Group Details: %s") % share_group.id) return context @memoized.memoized_method def get_data(self): try: share_group_id = self.kwargs['share_group_id'] share_group = manila.share_group_get(self.request, share_group_id) members = manila.share_list( self.request, search_opts={"share_group_id": share_group_id}) share_group.members = members share_types = manila.share_type_list(self.request) share_group.share_types = [ {"id": st.id, "name": st.name, "is_public": getattr(st, 'share_type_access:is_public'), "dhss": st.extra_specs.get('driver_handles_share_servers')} for st in share_types if st.id in share_group.share_types ] return share_group except Exception: redirect = reverse('horizon:project:share_groups:index') exceptions.handle( self.request, _('Unable to retrieve share group details.'), redirect=redirect) def get_tabs(self, request, *args, **kwargs): share_group = self.get_data() return self.tab_group_class(request, share_group=share_group, **kwargs) class ShareGroupCreateView(forms.ModalFormView): form_class = sg_forms.CreateShareGroupForm form_id = "create_share_group" template_name = 'project/share_groups/create.html' modal_header = _("Create Share Group") modal_id = "create_share_group_modal" submit_label = _("Create") submit_url = reverse_lazy("horizon:project:share_groups:create") success_url = reverse_lazy("horizon:project:share_groups:index") page_title = _('Create a Share') def get_context_data(self, **kwargs): context = super(ShareGroupCreateView, self).get_context_data(**kwargs) try: # TODO(vponomaryov): add quota logic here when quotas are # implemented for share groups. pass except Exception: exceptions.handle(self.request) return context class ShareGroupUpdateView(forms.ModalFormView): form_class = sg_forms.UpdateShareGroupForm form_id = "update_share_group" template_name = 'project/share_groups/update.html' modal_header = _("Update") modal_id = "update_share_group_modal" submit_label = _("Update") submit_url = "horizon:project:share_groups:update" success_url = reverse_lazy("horizon:project:share_groups:index") page_title = _("Update Share Group") def get_object(self): if not hasattr(self, "_object"): sg_id = self.kwargs['share_group_id'] try: self._object = manila.share_group_get(self.request, sg_id) except Exception: msg = _('Unable to retrieve share group.') url = reverse('horizon:project:share_groups:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(ShareGroupUpdateView, self).get_context_data(**kwargs) return context def get_initial(self): self.submit_url = reverse(self.submit_url, kwargs=self.kwargs) sg = self.get_object() return { 'share_group_id': self.kwargs["share_group_id"], 'name': sg.name, 'description': sg.description, } manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/000077500000000000000000000000001323215354300242265ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/__init__.py000066400000000000000000000000001323215354300263250ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/forms.py000066400000000000000000000137431323215354300257360ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, 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 django.core.urlresolvers import reverse from django.forms import ValidationError # noqa from django.template.defaultfilters import filesizeformat # noqa from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from horizon.utils.memoized import memoized # noqa from openstack_dashboard.api import base from openstack_dashboard.api import neutron from manila_ui.api import manila from manila_ui.api import network class Create(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Name")) description = forms.CharField( widget=forms.Textarea, label=_("Description"), required=False) def __init__(self, request, *args, **kwargs): super(Create, self).__init__(request, *args, **kwargs) self.neutron_enabled = base.is_service_enabled(request, 'network') net_choices = network.network_list(request) if self.neutron_enabled: self.fields['neutron_net_id'] = forms.ChoiceField( choices=[(' ', ' ')] + [(choice.id, choice.name_or_id) for choice in net_choices], label=_("Neutron Net"), widget=forms.Select( attrs={'class': 'switchable', 'data-slug': 'net'})) for net in net_choices: # For each network create switched choice field with # the its subnet choices subnet_field_name = 'subnet-choices-%s' % net.id subnet_field = forms.ChoiceField( choices=(), label=_("Neutron Subnet"), widget=forms.Select(attrs={ 'class': 'switched', 'data-switch-on': 'net', 'data-net-%s' % net.id: _("Neutron Subnet") })) self.fields[subnet_field_name] = subnet_field subnet_choices = neutron.subnet_list( request, network_id=net.id) self.fields[subnet_field_name].choices = [ (' ', ' ')] + [(choice.id, choice.name_or_id) for choice in subnet_choices] else: self.fields['nova_net_id'] = forms.ChoiceField( choices=[(' ', ' ')] + [(choice.id, choice.name_or_id) for choice in net_choices], label=_("Nova Net"), widget=forms.Select( attrs={'class': 'switched', 'data-slug': 'net'})) def handle(self, request, data): try: send_data = {'name': data['name']} if data['description']: send_data['description'] = data['description'] share_net_id = data.get('neutron_net_id', data.get('nova_net_id')) share_net_id = share_net_id.strip() if self.neutron_enabled and share_net_id: send_data['neutron_net_id'] = share_net_id subnet_key = 'subnet-choices-%s' % share_net_id if subnet_key in data: send_data['neutron_subnet_id'] = data[subnet_key] elif not self.neutron_enabled and share_net_id: send_data['nova_net_id'] = data['nova_net_id'] share_network = manila.share_network_create(request, **send_data) messages.success(request, _('Successfully created share' ' network: %s') % send_data['name']) return share_network except Exception: exceptions.handle(request, _('Unable to create share network.')) return False class Update(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Share Name")) description = forms.CharField(widget=forms.Textarea, label=_("Description"), required=False) def handle(self, request, data, *args, **kwargs): share_net_id = self.initial['share_network_id'] try: manila.share_network_update(request, share_net_id, name=data['name'], description=data['description']) message = _('Updating share network "%s"') % data['name'] messages.info(request, message) return True except Exception: redirect = reverse("horizon:project:shares:index") exceptions.handle(request, _('Unable to update share network.'), redirect=redirect) class AddSecurityServiceForm(forms.SelfHandlingForm): sec_service = forms.MultipleChoiceField( label=_("Networks"), required=True, widget=forms.CheckboxSelectMultiple(), error_messages={ 'required': _( "At least one security service" " must be specified.")}) def __init__(self, request, *args, **kwargs): super(AddSecurityServiceForm, self).__init__( request, *args, **kwargs) sec_services_choices = manila.security_service_list(request) self.fields['sec_service'].choices = [(' ', ' ')] + \ [(choice.id, choice.name or choice.id) for choice in sec_services_choices] def handle(self, request, data): pass manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/panel.py000066400000000000000000000016561323215354300257070ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.project import dashboard class ShareNetworks(horizon.Panel): name = _("Share Networks") slug = 'share_networks' permissions = ( 'openstack.services.share', ) dashboard.Project.register(ShareNetworks) manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/tables.py000066400000000000000000000116311323215354300260540ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.core.urlresolvers import NoReverseMatch # noqa from django.template.defaultfilters import title # noqa from django.utils.translation import pgettext_lazy from django.utils.translation import string_concat # noqa from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import tables from openstack_dashboard.api import base from openstack_dashboard.api import neutron from manila_ui.api import manila from manila_ui.api import network DELETABLE_STATES = ("INACTIVE", "ERROR") EDITABLE_STATES = ("INACTIVE", ) class Create(tables.LinkAction): name = "create_share_network" verbose_name = _("Create Share Network") url = "horizon:project:share_networks:share_network_create" classes = ("ajax-modal", "btn-create") icon = "plus" policy_rules = (("share", "share_network:create"),) class Delete(tables.DeleteAction): policy_rules = (("share", "share_network:delete"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Network", u"Delete Share Networks", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Network", u"Deleted Share Networks", count ) def delete(self, request, obj_id): manila.share_network_delete(request, obj_id) def allowed(self, request, obj=None): if obj: # NOTE: leave it True until statuses become used # return obj.status in DELETABLE_STATES return True return True class EditShareNetwork(tables.LinkAction): name = "edit" verbose_name = _("Edit Share Network") url = "horizon:project:share_networks:share_network_update" classes = ("ajax-modal", "btn-create") policy_rules = (("share", "share_network:update"),) def allowed(self, request, obj_id): # sn = manila.share_network_get(request, obj_id) # return sn.status in EDITABLE_STATES # NOTE: leave it always True, until statuses become used return True class UpdateRow(tables.Row): ajax = True def get_data(self, request, share_net_id): share_net = manila.share_network_get(request, share_net_id) neutron_enabled = base.is_service_enabled(request, 'network') if neutron_enabled: share_net.neutron_net = neutron.network_get( request, share_net.neutron_net_id).name_or_id share_net.neutron_subnet = neutron.subnet_get( request, share_net.neutron_subnet_id).name_or_id else: share_net.nova_net = network.network_get( request, share_net.nova_net_id).name_or_id return share_net class ShareNetworksTable(tables.DataTable): STATUS_CHOICES = ( ("ACTIVE", True), ("INACTIVE", True), ("ERROR", False), ) STATUS_DISPLAY_CHOICES = ( ("ACTIVE", pgettext_lazy("Current status of share network", u"Active")), ("INACTIVE", pgettext_lazy("Current status of share network", u"Inactive")), ("ERROR", pgettext_lazy("Current status of share network", u"Error")), ) name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:project:share_networks:share_network_detail") neutron_net = tables.Column("neutron_net", verbose_name=_("Neutron Net")) neutron_subnet = tables.Column( "neutron_subnet", verbose_name=_("Neutron Subnet")) ip_version = tables.Column("ip_version", verbose_name=_("IP Version")) network_type = tables.Column( "network_type", verbose_name=_("Network Type")) segmentation_id = tables.Column( "segmentation_id", verbose_name=_("Segmentation Id")) def get_object_display(self, share_network): return share_network.name or str(share_network.id) def get_object_id(self, share_network): return str(share_network.id) class Meta(object): name = "share_networks" verbose_name = _("Share Networks") table_actions = ( tables.NameFilterAction, Create, Delete, ) row_class = UpdateRow row_actions = ( EditShareNetwork, Delete, ) manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/tabs.py000066400000000000000000000020051323215354300255260ustar00rootroot00000000000000# # 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class OverviewTab(tabs.Tab): name = _("Overview") slug = "overview" template_name = "project/share_networks/_detail.html" def get_context_data(self, request): return {"share_network": self.tab_group.kwargs['share_network']} class ShareNetworkDetailTabs(tabs.TabGroup): slug = "share_network_details" tabs = ( OverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/templates/000077500000000000000000000000001323215354300262245ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/templates/share_networks/000077500000000000000000000000001323215354300312625ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/templates/share_networks/_create.html000066400000000000000000000004741323215354300335570ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% blocktrans %} Share networks contain network data, that will be used for creation of service VM, where will be hosted shares. {% endblocktrans %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/templates/share_networks/_detail.html000066400000000000000000000027511323215354300335560ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Network Overview" %}


{% trans "Name" %}
{{ share_network.name }}
{% trans "ID" %}
{{ share_network.id }}
{% if share_network.description %}
{% trans "Description" %}
{{ share_network.description }}
{% endif %}

{% trans "Net Details" %}


{% trans "Network" %}
{% if share_network.neutron_net %}
{{ share_network.neutron_net }}
{% trans "Subnet" %}
{{ share_network.neutron_subnet}}
{% endif %} {% if share_network.nova_net %}
{{ share_network.nova_net }}
{% endif %}

{% trans "Security Services" %}


{% for sec_service in share_network.sec_services %} {% url 'horizon:project:security_services:security_service_detail' sec_service.id as sec_service_url%}
{% trans "Id" %}
{{ sec_service.id }}
{% trans "Name" %}
{{ sec_service.name }}
{% trans "Type" %}
{{ sec_service.type }}

{% endfor %}
manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/templates/share_networks/_update.html000066400000000000000000000016411323215354300335730ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block form_id %}{% endblock %} {% block form_action %}{% url 'horizon:project:share_networks:share_network_update' share_network.id %}{% endblock %} {% block modal_id %}update_share_network_modal{% endblock %} {% block modal-header %}{% trans "Edit Share network" %}{% endblock %} {% block modal-body %}
{% include "horizon/common/_form_fields.html" %}

{% trans "Description" %}:

{% trans "From here you can modify name and description of a share network." %}

{% endblock %} {% block modal-footer %} {% trans "Cancel" %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/templates/share_networks/create.html000066400000000000000000000003051323215354300334110ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Share Network" %}{% endblock %} {% block main %} {% include 'project/share_networks/_create.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/templates/share_networks/detail.html000066400000000000000000000003431323215354300334120ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Network Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/templates/share_networks/index.html000066400000000000000000000003471323215354300332630ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Networks" %}{% endblock %} {% block main %}
{{ share_networks_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/templates/share_networks/update.html000066400000000000000000000002771323215354300334400ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Update share network" %}{% endblock %} {% block main %} {% include 'horizon/common/_workflow.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/urls.py000066400000000000000000000022501323215354300255640ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.conf import urls from manila_ui.dashboards.project.share_networks import views urlpatterns = [ urls.url( r'^$', views.ShareNetworksView.as_view(), name='index'), urls.url( r'^create_share_network$', views.Create.as_view(), name='share_network_create'), urls.url( r'^(?P[^/]+)/update$', views.Update.as_view(), name='share_network_update'), urls.url( r'^(?P[^/]+)$', views.Detail.as_view(), name='share_network_detail'), ] manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/views.py000066400000000000000000000146461323215354300257500ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon import tabs from horizon.utils import memoized from horizon import workflows from openstack_dashboard.api import base from openstack_dashboard.api import neutron from manila_ui.api import manila from manila_ui.api import network from manila_ui.dashboards.project.share_networks import forms as sn_forms from manila_ui.dashboards.project.share_networks import tables as sn_tables from manila_ui.dashboards.project.share_networks import tabs as sn_tabs import manila_ui.dashboards.project.share_networks.workflows as sn_workflows from manila_ui.dashboards import utils class ShareNetworksView(tables.MultiTableView): table_classes = ( sn_tables.ShareNetworksTable, ) template_name = "admin/share_networks/index.html" page_title = _("Share Networks") @memoized.memoized_method def get_share_networks_data(self): try: share_networks = manila.share_network_list( self.request, detailed=True) if base.is_service_enabled(self.request, 'network'): neutron_net_names = dict((net.id, net.name) for net in neutron.network_list(self.request)) neutron_subnet_names = dict((net.id, net.name) for net in neutron.subnet_list(self.request)) for sn in share_networks: sn.neutron_net = neutron_net_names.get( sn.neutron_net_id) or sn.neutron_net_id or "-" sn.neutron_subnet = neutron_subnet_names.get( sn.neutron_subnet_id) or sn.neutron_subnet_id or "-" except Exception: share_networks = [] exceptions.handle( self.request, _("Unable to retrieve share networks")) return share_networks class Update(workflows.WorkflowView): workflow_class = sn_workflows.UpdateShareNetworkWorkflow template_name = "project/share_networks/update.html" success_url = 'horizon:project:share_networks:index' page_title = _('Update Share Network') def get_initial(self): return {'id': self.kwargs["share_network_id"]} def get_context_data(self, **kwargs): context = super(Update, self).get_context_data(**kwargs) context['id'] = self.kwargs['share_network_id'] return context class Create(forms.ModalFormView): form_class = sn_forms.Create form_id = "create_share_network" template_name = 'project/share_networks/create.html' modal_header = _("Create Share Network") modal_id = "create_share_network_modal" submit_label = _("Create") submit_url = reverse_lazy( "horizon:project:share_networks:share_network_create") success_url = reverse_lazy("horizon:project:share_networks:index") page_title = _('Create Share Network') class Detail(tabs.TabView): tab_group_class = sn_tabs.ShareNetworkDetailTabs template_name = 'project/share_networks/detail.html' redirect_url = reverse_lazy('horizon:project:share_networks:index') def get_context_data(self, **kwargs): context = super(Detail, self).get_context_data(**kwargs) share_network = self.get_data() share_network_display_name = share_network.name or share_network.id context["share_network"] = share_network context["share_network_display_name"] = share_network_display_name context["page_title"] = _("Share Network Details: " "%(network_display_name)s") % \ {'network_display_name': share_network_display_name} return context @memoized.memoized_method def get_data(self): try: share_net_id = self.kwargs['share_network_id'] share_net = manila.share_network_get(self.request, share_net_id) if base.is_service_enabled(self.request, 'network'): try: share_net.neutron_net = neutron.network_get( self.request, share_net.neutron_net_id).name_or_id except ( neutron.neutron_client.exceptions.NeutronClientException): share_net.neutron_net = _("Unknown") try: share_net.neutron_subnet = neutron.subnet_get( self.request, share_net.neutron_subnet_id).name_or_id except ( neutron.neutron_client.exceptions.NeutronClientException): share_net.neutron_subnet = _("Unknown") else: try: share_net.nova_net = network.network_get( self.request, share_net.nova_net_id).name_or_id except Exception: share_net.nova_net = _("Unknown") share_net.sec_services = ( manila.share_network_security_service_list( self.request, share_net_id)) for ss in share_net.sec_services: ss.type = utils.get_nice_security_service_type(ss) server_search_opts = {'share_network_id': share_net_id} share_servs = manila.share_server_list( self.request, search_opts=server_search_opts) share_net.share_servers = share_servs except Exception: exceptions.handle(self.request, _('Unable to retrieve share network details.'), redirect=self.redirect_url) return share_net def get_tabs(self, request, *args, **kwargs): share_network = self.get_data() return self.tab_group_class(request, share_network=share_network, **kwargs) manila-ui-2.13.0/manila_ui/dashboards/project/share_networks/workflows.py000066400000000000000000000136351323215354300266450ustar00rootroot00000000000000# 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 django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import workflows from manila_ui.api import manila class UpdateShareNetworkInfoAction(workflows.Action): name = forms.CharField(label=_("Name"), max_length=255) description = forms.CharField(label=_("Description"), max_length=255, required=False) def __init__(self, request, *args, **kwargs): super(UpdateShareNetworkInfoAction, self).__init__( request, *args, **kwargs) share_network = manila.share_network_get(request, self.initial['id']) self.fields['name'].initial = share_network.name self.fields['description'].initial = share_network.description class Meta(object): name = _("Share Network Info") help_text = _("From here you can update share network info. ") slug = "update-share_network_info" def clean(self): cleaned_data = super(UpdateShareNetworkInfoAction, self).clean() return cleaned_data class UpdateShareNetworkInfoStep(workflows.Step): action_class = UpdateShareNetworkInfoAction contributes = ("description", "name") class AddSecurityServiceAction(workflows.MembershipAction): def __init__(self, request, *args, **kwargs): super(AddSecurityServiceAction, self).__init__(request, *args, **kwargs) err_msg = _('Unable to get the security services hosts') default_role_field_name = self.get_default_role_field_name() self.fields[default_role_field_name] = forms.CharField(required=False) self.fields[default_role_field_name].initial = 'member' field_name = self.get_member_field_name('member') self.fields[field_name] = forms.MultipleChoiceField(required=False) share_network_id = self.initial['id'] security_services = manila.share_network_security_service_list( request, share_network_id) sec_services_initial = [sec_service.id for sec_service in security_services] sec_services = [] try: sec_services = manila.security_service_list(request) except Exception: exceptions.handle(request, err_msg) sec_services_choices = [(sec_service.id, sec_service.name or sec_service.id) for sec_service in sec_services] self.fields[field_name].choices = sec_services_choices self.fields[field_name].initial = sec_services_initial class Meta(object): name = _("Security services within share network") slug = "add_security_service" class AddSecurityServiceStep(workflows.UpdateMembersStep): action_class = AddSecurityServiceAction help_text = _("Add security services to share network.") available_list_title = _("Available security services") members_list_title = _("Selected security services") no_available_text = _("No security services found.") no_members_text = _("No security services selected.") show_roles = False depends_on = ("id",) contributes = ("security_services",) def contribute(self, data, context): if data: member_field_name = self.get_member_field_name('member') context['security_service'] = data.get(member_field_name, []) return context class UpdateShareNetworkWorkflow(workflows.Workflow): slug = "update_share_network" name = _("Update Share Network") finalize_button_name = _("Update Share Network") success_message = _('Updated share network "%s".') failure_message = _('Unable to update share network "%s".') success_url = 'horizon:project:share_networks:index' default_steps = (UpdateShareNetworkInfoStep, AddSecurityServiceStep) def format_status_message(self, message): return message % self.context['name'] def handle(self, request, context): try: manila.share_network_update(request, context['id'], description=context['description'], name=context['name']) sec_services = manila.security_service_list(request, search_opts={ 'share_network_id': context['id']}) sec_services_old = set([sec_service.id for sec_service in sec_services]) sec_services_new = set(context['security_service']) for sec_service in sec_services_new - sec_services_old: manila.share_network_security_service_add(request, context['id'], sec_service) for sec_service in sec_services_old - sec_services_new: manila.share_network_security_service_remove(request, context['id'], sec_service) return True except Exception: exceptions.handle(request, _('Unable to update share network.')) return False manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/000077500000000000000000000000001323215354300243745ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/__init__.py000066400000000000000000000000001323215354300264730ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/forms.py000066400000000000000000000075611323215354300261050ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, 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. """ Views for managing share snapshots. """ from django.core.urlresolvers import reverse from django.forms import ValidationError # noqa from django.template.defaultfilters import filesizeformat # noqa from django.utils.http import urlencode # noqa from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from manila_ui.api import manila class CreateShareSnapshotForm(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Share Snapshot Name")) description = forms.CharField( widget=forms.Textarea, label=_("Description"), required=False) def __init__(self, request, *args, **kwargs): super(self.__class__, self).__init__(request, *args, **kwargs) # populate share_id share_id = kwargs.get('initial', {}).get('share_id', []) self.fields['share_id'] = forms.CharField( widget=forms.HiddenInput(), initial=share_id) def handle(self, request, data): try: snapshot = manila.share_snapshot_create( request, data['share_id'], data['name'], data['description']) message = _('Creating share snapshot "%s".') % data['name'] messages.success(request, message) return snapshot except Exception: redirect = reverse("horizon:project:share_snapshots:index") exceptions.handle(request, _('Unable to create share snapshot.'), redirect=redirect) class UpdateShareSnapshotForm(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Share Snapshot Name")) description = forms.CharField( widget=forms.Textarea, label=_("Description"), required=False) def handle(self, request, data): snapshot_id = self.initial['snapshot_id'] try: manila.share_snapshot_update( request, snapshot_id, data['name'], data['description']) message = _('Updating share snapshot "%s"') % data['name'] messages.success(request, message) return True except Exception: exceptions.handle(request, _('Unable to update share snapshot.')) class AddShareSnapshotRule(forms.SelfHandlingForm): access_type = forms.ChoiceField( label=_("Access Type"), required=True, choices=(('ip', 'ip'), ('user', 'user'), ('cephx', 'cephx'), ('cert', 'cert'))) access_to = forms.CharField( label=_("Access To"), max_length="255", required=True) def handle(self, request, data): snapshot_id = self.initial['snapshot_id'] try: manila.share_snapshot_allow( request, snapshot_id, access_to=data['access_to'], access_type=data['access_type']) message = _('Creating snapshot rule for "%s"') % data['access_to'] messages.success(request, message) return True except Exception: redirect = reverse( "horizon:project:share_snapshots:share_snapshot_manage_rules", args=[self.initial['snapshot_id']]) exceptions.handle( request, _('Unable to add snapshot rule.'), redirect=redirect) manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/panel.py000066400000000000000000000016621323215354300260520ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.project import dashboard class ShareSnapshots(horizon.Panel): name = _("Share Snapshots") slug = 'share_snapshots' permissions = ( 'openstack.services.share', ) dashboard.Project.register(ShareSnapshots) manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/tables.py000066400000000000000000000234721323215354300262300ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.core.urlresolvers import NoReverseMatch # noqa from django.core.urlresolvers import reverse from django.template.defaultfilters import title # noqa from django.utils.http import urlencode # noqa from django.utils.translation import pgettext_lazy from django.utils.translation import string_concat # noqa from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import tables from openstack_dashboard.usage import quotas from manila_ui.api import manila DELETABLE_STATES = ("available", "error") class UpdateShareSnapshotRow(tables.Row): ajax = True def get_data(self, request, snapshot_id): snapshot = manila.share_snapshot_get(request, snapshot_id) if not snapshot.name: snapshot.name = snapshot_id return snapshot def get_size(snapshot): return _("%sGiB") % snapshot.size class CreateShareSnapshot(tables.LinkAction): name = "create_share_snapshot" verbose_name = _("Create Share Snapshot") url = "horizon:project:share_snapshots:share_snapshot_create" classes = ("ajax-modal", "btn-camera") policy_rules = (("share", "share:create_snapshot"),) def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "project_id", None) return {"project_id": project_id} def allowed(self, request, share=None): usages = quotas.tenant_quota_usages(request) if usages['snapshots']['available'] <= 0: if "disabled" not in self.classes: self.classes = [c for c in self.classes] + ['disabled'] self.verbose_name = string_concat( self.verbose_name, ' ', _("(Quota exceeded)")) else: self.verbose_name = _("Create Share Snapshot") classes = [c for c in self.classes if c != "disabled"] self.classes = classes # NOTE(vponomaryov): Disable form with creation of a snapshot for # shares that has attr 'snapshot_support' equal to False. if hasattr(share, 'snapshot_support'): snapshot_support = share.snapshot_support else: # NOTE(vponomaryov): Allow creation of a snapshot for shares that # do not have such attr for backward compatibility. snapshot_support = True return share.status in ("available", "in-use") and snapshot_support class DeleteShareSnapshot(tables.DeleteAction): policy_rules = (("share", "share:delete_snapshot"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Snapshot", u"Delete Share Snapshots", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Snapshot", u"Deleted Share Snapshots", count ) def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "project_id", None) return {"project_id": project_id} def delete(self, request, obj_id): obj = self.table.get_object_by_id(obj_id) name = self.table.get_object_display(obj) try: manila.share_snapshot_delete(request, obj_id) except Exception: msg = _('Unable to delete snapshot "%s". One or more shares ' 'depend on it.') exceptions.check_message(["snapshots", "dependent"], msg % name) raise def allowed(self, request, snapshot=None): if snapshot: return snapshot.status in DELETABLE_STATES return True class CreateShareFromShareSnapshot(tables.LinkAction): name = "create_share_from_share_snapshot" verbose_name = _("Create Share") url = "horizon:project:shares:create" classes = ("ajax-modal", "btn-camera") policy_rules = (("share", "share:create"),) def get_link_url(self, datum): base_url = reverse(self.url) params = urlencode({"snapshot_id": self.table.get_object_id(datum)}) return "?".join([base_url, params]) def allowed(self, request, share=None): return share.status == "available" class EditShareSnapshot(tables.LinkAction): name = "edit_share_snapshot" verbose_name = _("Edit Share Snapshot") url = "horizon:project:share_snapshots:share_snapshot_edit" classes = ("ajax-modal", "btn-camera") class ShareSnapshotShareNameColumn(tables.Column): def get_link_url(self, snapshot): return reverse(self.link, args=(snapshot.share_id,)) class ManageShareSnapshotRules(tables.LinkAction): name = "share_snapshot_manage_rules" verbose_name = _("Manage Share Snapshot Rules") url = "horizon:project:share_snapshots:share_snapshot_manage_rules" classes = ("btn-edit",) policy_rules = (("share", "share:access_get_all"),) def allowed(self, request, snapshot=None): share = manila.share_get(request, snapshot.share_id) return share.mount_snapshot_support class AddShareSnapshotRule(tables.LinkAction): name = "share_snapshot_rule_add" verbose_name = _("Add Share Snapshot Rule") url = 'horizon:project:share_snapshots:share_snapshot_rule_add' classes = ("ajax-modal", "btn-create") icon = "plus" policy_rules = (("share", "share:allow_access"),) def allowed(self, request, snapshot=None): snapshot = manila.share_snapshot_get( request, self.table.kwargs['snapshot_id']) return snapshot.status in ("available", "in-use") def get_link_url(self): return reverse(self.url, args=[self.table.kwargs['snapshot_id']]) class DeleteShareSnapshotRule(tables.DeleteAction): policy_rules = (("share", "share:deny_access"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share Snapshot Rule", u"Delete Share Snapshot Rules", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share Snapshot Rule", u"Deleted Share Snapshot Rules", count ) def delete(self, request, obj_id): try: manila.share_snapshot_deny( request, self.table.kwargs['snapshot_id'], obj_id) except Exception: msg = _('Unable to delete snapshot rule "%s".') % obj_id exceptions.handle(request, msg) class UpdateShareSnapshotRuleRow(tables.Row): ajax = True def get_data(self, request, rule_id): rules = manila.share_snapshot_rules_list( request, self.table.kwargs['snapshot_id']) if rules: for rule in rules: if rule.id == rule_id: return rule raise exceptions.NotFound class ShareSnapshotRulesTable(tables.DataTable): access_type = tables.Column("access_type", verbose_name=_("Access Type")) access_to = tables.Column("access_to", verbose_name=_("Access to")) status = tables.Column("state", verbose_name=_("Status")) def get_object_display(self, obj): return obj.id class Meta(object): name = "rules" verbose_name = _("Share Snapshot Rules") status_columns = ["status"] row_class = UpdateShareSnapshotRuleRow table_actions = ( AddShareSnapshotRule, DeleteShareSnapshotRule, ) row_actions = ( DeleteShareSnapshotRule, ) class ShareSnapshotsTable(tables.DataTable): STATUS_CHOICES = ( ("in-use", True), ("available", True), ("creating", None), ("error", False), ) STATUS_DISPLAY_CHOICES = ( ("in-use", pgettext_lazy("Current status of snapshot", u"In-use")), ("available", pgettext_lazy("Current status of snapshot", u"Available")), ("creating", pgettext_lazy("Current status of snapshot", u"Creating")), ("error", pgettext_lazy("Current status of snapshot", u"Error")), ) name = tables.Column( "name", verbose_name=_("Name"), link="horizon:project:share_snapshots:share_snapshot_detail") description = tables.Column( "description", verbose_name=_("Description"), truncate=40) size = tables.Column( get_size, verbose_name=_("Size"), attrs={'data-type': 'size'}) status = tables.Column( "status", filters=(title,), verbose_name=_("Status"), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES) source = ShareSnapshotShareNameColumn( "share", verbose_name=_("Source"), link="horizon:project:shares:detail") def get_object_display(self, obj): return obj.name class Meta(object): name = "share_snapshots" verbose_name = _("Share Snapshots") status_columns = ["status"] row_class = UpdateShareSnapshotRow table_actions = ( tables.NameFilterAction, DeleteShareSnapshot, ) row_actions = ( EditShareSnapshot, CreateShareFromShareSnapshot, ManageShareSnapshotRules, DeleteShareSnapshot, ) manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/tabs.py000066400000000000000000000020721323215354300257000ustar00rootroot00000000000000# # 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ShareSnapshotOverviewTab(tabs.Tab): name = _("Share Snapshot Overview") slug = "share_snapshot_overview_tab" template_name = "project/share_snapshots/_detail.html" def get_context_data(self, request): return {"snapshot": self.tab_group.kwargs['snapshot']} class ShareSnapshotDetailTabs(tabs.TabGroup): slug = "share_snapshot_details" tabs = ( ShareSnapshotOverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/000077500000000000000000000000001323215354300263725ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots/000077500000000000000000000000001323215354300315765ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots/_create.html000066400000000000000000000003631323215354300340700ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}
{% include "project/share_snapshots/_limits.html" with usages=usages snapshot_quota=True %}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots/_detail.html000066400000000000000000000040351323215354300340670ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Snapshot Overview" %}


{% trans "Name" %}
{{ snapshot.name }}
{% trans "ID" %}
{{ snapshot.id }}
{% url 'horizon:project:shares:detail' snapshot.share_id as share_url %}
{% trans "Source" %}
{{ snapshot.share_name_or_id }}
{% if snapshot.description %}
{% trans "Description" %}
{{ snapshot.description }}
{% endif %}
{% trans "Status" %}
{{ snapshot.status|capfirst }}
{% if snapshot.export_locations %}
{% trans "Export locations" %}
{% for el in snapshot.export_locations %}

Path:
{% if el.is_admin_only != None %}
Is admin only: {{ el.is_admin_only }}
{% endif %} {% if el.share_snapshot_instance_id %}
Snapshot Replica ID: {{ el.share_snapshot_instance_id }}
{% endif %}

{% endfor %} {% endif %}
{% if snapshot.rules != None %}

{% trans "Access Rules" %}


{% for rule in snapshot.rules %}
{{ rule.access_type }}

Access to: {{ rule.access_to }}
Status: {{ rule.state }}

{% endfor %}
{% endif %}

{% trans "Specs" %}


{% trans "Size" %}
{{ snapshot.size }} {% trans "GiB" %}
{% trans "Created" %}
{{ snapshot.created_at|parse_date }}
manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots/_limits.html000066400000000000000000000023761323215354300341340ustar00rootroot00000000000000{% load i18n horizon humanize %}

{% trans "Description" %}:

{% trans "Share Snapshots are used for storing share changes and creating shares. " %}

{% trans "Share Limits" %}

{% trans "Total Gibibytes" %} ({{ usages.totalShareGigabytesUsed|intcomma }} {% trans "GiB" %})

{{ usages.maxTotalShareGigabytes|quota:_("GiB")|intcomma }}

{% trans "Number of Share Snapshots" %} ({{ usages.totalShareSnapshotsUsed|intcomma }})

{{ usages.maxTotalShareSnapshots|quota|intcomma }}

_rule_add.html000066400000000000000000000006261323215354300343270ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% blocktrans %} Add policy rule to snapshot, 'ip' rule represents ip address, 'user' rule represents username or usergroup, 'cephx' rule represents ceph auth ID, and 'cert' rule represents certificate. {% endblocktrans %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots/_update.html000066400000000000000000000003461323215354300341100ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "From here you can modify name and description of a snapshot." %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots/create.html000066400000000000000000000003071323215354300337270ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Share Snapshot" %}{% endblock %} {% block main %} {% include 'project/share_snapshots/_create.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots/detail.html000066400000000000000000000003441323215354300337270ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Snapshot Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots/index.html000066400000000000000000000003511323215354300335720ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Snapshots" %}{% endblock %} {% block main %}
{{ share_snapshots_table.render }}
{% endblock %} manage_rules.html000066400000000000000000000002421323215354300350450ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Snapshot Rules" %}{% endblock %} {% block main %} {{ table.render }} {% endblock %} rule_add.html000066400000000000000000000002741323215354300341670ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Add Rule" %}{% endblock %} {% block main %} {% include 'project/share_snapshots/_rule_add.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/templates/share_snapshots/update.html000066400000000000000000000003051323215354300337440ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Edit Share Snapshot" %}{% endblock %} {% block main %} {% include 'project/share_snapshots/_update.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/urls.py000066400000000000000000000031131323215354300257310ustar00rootroot00000000000000# Copyright 2017 Mirantis, Inc. # # 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 django.conf import urls from manila_ui.dashboards.project.share_snapshots import views urlpatterns = [ urls.url( r'^$', views.ShareSnapshotsView.as_view(), name='index'), urls.url( r'^(?P[^/]+)/share_snapshot_create/$', views.CreateShareSnapshotView.as_view(), name='share_snapshot_create'), urls.url( r'^(?P[^/]+)/share_snapshot_edit/$', views.UpdateShareSnapshotView.as_view(), name='share_snapshot_edit'), urls.url( r'^(?P[^/]+)$', views.ShareSnapshotDetailView.as_view(), name='share_snapshot_detail'), urls.url( r'^(?P[^/]+)/share_snapshot_rules/$', views.ManageShareSnapshotRulesView.as_view(), name='share_snapshot_manage_rules'), urls.url( r'^(?P[^/]+)/share_snapshot_rule_add/$', views.AddShareSnapshotRuleView.as_view(), name='share_snapshot_rule_add'), ] manila-ui-2.13.0/manila_ui/dashboards/project/share_snapshots/views.py000066400000000000000000000224741323215354300261140ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon import tabs from horizon.utils import memoized from openstack_dashboard.usage import quotas from manila_ui.api import manila from manila_ui.dashboards.project.share_snapshots import forms as ss_forms from manila_ui.dashboards.project.share_snapshots import tables as ss_tables from manila_ui.dashboards.project.share_snapshots import tabs as ss_tabs from manila_ui.dashboards import utils as ui_utils class ShareSnapshotsView(tables.MultiTableView): table_classes = ( ss_tables.ShareSnapshotsTable, ) template_name = "project/share_snapshots/index.html" page_title = _("Share Snapshots") @memoized.memoized_method def get_share_snapshots_data(self): try: snapshots = manila.share_snapshot_list(self.request) shares = manila.share_list(self.request) share_names = dict([(share.id, share.name or share.id) for share in shares]) for snapshot in snapshots: snapshot.share = share_names.get(snapshot.share_id) except Exception: msg = _("Unable to retrieve share snapshots list.") exceptions.handle(self.request, msg) return [] # Gather our tenants to correlate against IDs return snapshots class ShareSnapshotDetailView(tabs.TabView): tab_group_class = ss_tabs.ShareSnapshotDetailTabs template_name = 'project/share_snapshots/detail.html' redirect_url = reverse_lazy('horizon:project:share_snapshots:index') def get_context_data(self, **kwargs): context = super(ShareSnapshotDetailView, self).get_context_data( **kwargs) snapshot = self.get_data() snapshot_display_name = snapshot.name or snapshot.id context["snapshot"] = snapshot context["snapshot_display_name"] = snapshot_display_name context["page_title"] = _("Snapshot Details: " "%(snapshot_display_name)s") % ( {'snapshot_display_name': snapshot_display_name}) return context @memoized.memoized_method def get_data(self): try: snapshot_id = self.kwargs['snapshot_id'] snapshot = manila.share_snapshot_get(self.request, snapshot_id) share = manila.share_get(self.request, snapshot.share_id) if share.mount_snapshot_support: snapshot.rules = manila.share_snapshot_rules_list( self.request, snapshot_id) snapshot.export_locations = ( manila.share_snap_export_location_list( self.request, snapshot)) export_locations = [ exp['path'] for exp in snapshot.export_locations ] snapshot.el_size = ui_utils.calculate_longest_str_size( export_locations) snapshot.share_name_or_id = share.name or share.id except Exception: exceptions.handle( self.request, _('Unable to retrieve snapshot details.'), redirect=self.redirect_url) return snapshot def get_tabs(self, request, *args, **kwargs): snapshot = self.get_data() return self.tab_group_class(request, snapshot=snapshot, **kwargs) class CreateShareSnapshotView(forms.ModalFormView): form_class = ss_forms.CreateShareSnapshotForm form_id = "create_share_snapshot" template_name = 'project/share_snapshots/create.html' modal_header = _("Create Share Snapshot") modal_id = "create_share_snapshot_modal" submit_label = _("Create Share Snapshot") submit_url = "horizon:project:share_snapshots:share_snapshot_create" success_url = reverse_lazy('horizon:project:share_snapshots:index') page_title = _('Create Share Snapshot') def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) context['share_id'] = self.kwargs['share_id'] try: context['usages'] = quotas.tenant_limit_usages(self.request) except Exception: exceptions.handle(self.request, _('Unable to retrieve quotas.')) return context def get_initial(self): self.submit_url = reverse(self.submit_url, kwargs=self.kwargs) return {'share_id': self.kwargs["share_id"]} class UpdateShareSnapshotView(forms.ModalFormView): form_class = ss_forms.UpdateShareSnapshotForm form_id = "update_share_snapshot" template_name = 'project/share_snapshots/update.html' modal_header = _("Update Share Snapshot") modal_id = "update_share_snapshot_modal" submit_label = _("Update") submit_url = "horizon:project:share_snapshots:share_snapshot_edit" success_url = reverse_lazy('horizon:project:share_snapshots:index') page_title = _('Edit Share Snapshot') @memoized.memoized_method def get_object(self): if not hasattr(self, "_object"): snap_id = self.kwargs['snapshot_id'] try: self._object = manila.share_snapshot_get(self.request, snap_id) except Exception: msg = _('Unable to retrieve share snapshot.') url = reverse('horizon:project:share_snapshots:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) args = (self.get_object().id,) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): snapshot = self.get_object() return {'snapshot_id': self.kwargs["snapshot_id"], 'name': snapshot.name, 'description': snapshot.description} class AddShareSnapshotRuleView(forms.ModalFormView): form_class = ss_forms.AddShareSnapshotRule form_id = "rule_add_snap" template_name = 'project/share_snapshots/rule_add.html' modal_header = _("Add Rule") modal_id = "rule_add_share_snapshot_modal" submit_label = _("Add") submit_url = "horizon:project:share_snapshots:share_snapshot_rule_add" success_url = reverse_lazy("horizon:project:share_snapshots:index") page_title = _('Add Rule') def get_object(self): if not hasattr(self, "_object"): snapshot_id = self.kwargs['snapshot_id'] try: self._object = manila.share_snapshot_get( self.request, snapshot_id) except Exception: msg = _('Unable to retrieve snapshot.') url = reverse('horizon:project:share_snapshots:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) args = (self.get_object().id,) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): snapshot = self.get_object() return {'snapshot_id': self.kwargs["snapshot_id"], 'name': snapshot.name, 'description': snapshot.description} def get_success_url(self): return reverse( "horizon:project:share_snapshots:share_snapshot_manage_rules", args=[self.kwargs['snapshot_id']]) class ManageShareSnapshotRulesView(tables.DataTableView): table_class = ss_tables.ShareSnapshotRulesTable template_name = 'project/share_snapshots/manage_rules.html' def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) snapshot = manila.share_snapshot_get( self.request, self.kwargs['snapshot_id']) context['snapshot_display_name'] = snapshot.name or snapshot.id context["snapshot"] = self.get_data() context["page_title"] = _("Snapshot Rules: " "%(snapshot_display_name)s") % { 'snapshot_display_name': context['snapshot_display_name']} return context @memoized.memoized_method def get_data(self): try: snapshot_id = self.kwargs['snapshot_id'] rules = manila.share_snapshot_rules_list( self.request, snapshot_id) except Exception: redirect = reverse('horizon:project:share_snapshots:index') exceptions.handle( self.request, _('Unable to retrieve share snapshot rules.'), redirect=redirect) return rules manila-ui-2.13.0/manila_ui/dashboards/project/shares/000077500000000000000000000000001323215354300224555ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/shares/__init__.py000066400000000000000000000332751323215354300246000ustar00rootroot00000000000000# 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 functools import sys from django.utils.translation import ugettext_lazy as _ import horizon from manila_ui.api import manila from openstack_dashboard.api import base from openstack_dashboard.dashboards.admin.defaults import tables as quota_tbl from openstack_dashboard.dashboards.admin.defaults import views \ as default_views from openstack_dashboard.dashboards.admin.defaults import workflows \ as default_workflows from openstack_dashboard.dashboards.identity.projects import views \ as project_views from openstack_dashboard.dashboards.identity.projects import workflows \ as project_workflows from openstack_dashboard.dashboards.project.overview import views \ as overview_views from openstack_dashboard.usage import base as usage_base from openstack_dashboard.usage import quotas def wrap(orig_func): """decorator to wrap an existing function Modified post from http://downgra.de/2009/05/16/python-monkey-patching/ to work with functions e.g. @wrap(quotas.tenant_limit_usages) def tenant_limit_usages(orig, self): limits = orig(request) limits['disksUsed'] = 100 return limits the first parameter of the new function is the the original, overwritten function ('orig'). """ def outer(new_func): @functools.wraps(orig_func) def wrapper(*args, **kwargs): return new_func(orig_func, *args, **kwargs) # Replace the original function in the module with the wrapper orig_module = sys.modules[orig_func.__module__] setattr(orig_module, orig_func.__name__, wrapper) return wrapper return outer # All public methods in openstack_dashboard.usage.quotas are hardcoded to # only look at a fixed set of services (nova, cinder, etc.). In order to # incorporate manila quotas and usage, all public functions must be # monkey-patched to add that information in. MANILA_QUOTA_FIELDS = { "shares", "share_gigabytes", "share_snapshots", "share_snapshot_gigabytes", "share_networks", } MANILA_QUOTA_NAMES = { 'shares': _('Shares'), 'share_gigabytes': _('Share gigabytes'), 'share_snapshots': _('Share snapshots'), 'share_snapshot_gigabytes': _('Share snapshot gigabytes'), 'share_networks': _('Shares Networks'), } quotas.QUOTA_FIELDS = quotas.QUOTA_FIELDS | MANILA_QUOTA_FIELDS def _get_manila_disabled_quotas(request): disabled_quotas = [] if not base.is_service_enabled(request, 'share'): disabled_quotas.extend(MANILA_QUOTA_FIELDS) return disabled_quotas def _get_manila_quota_data(request, method_name, disabled_quotas=None, tenant_id=None): if not tenant_id: tenant_id = request.user.tenant_id if disabled_quotas is None: disabled_quotas = _get_manila_disabled_quotas(request) if 'shares' not in disabled_quotas: manila_quotas = getattr(manila, method_name)(request, tenant_id) for quota in manila_quotas: if quota.name == 'gigabytes': quota.name = 'share_gigabytes' elif quota.name == 'snapshots': quota.name = 'share_snapshots' elif quota.name == 'snapshot_gigabytes': quota.name = 'share_snapshot_gigabytes' return manila_quotas else: return None @wrap(quotas.get_default_quota_data) def get_default_quota_data(f, request, disabled_quotas=None, tenant_id=None): qs = f(request, disabled_quotas, tenant_id) manila_quota = _get_manila_quota_data(request, "default_quota_get", disabled_quotas=disabled_quotas, tenant_id=tenant_id) if manila_quota: qs.add(manila_quota) return qs @wrap(quotas.get_tenant_quota_data) def get_tenant_quota_data(f, request, disabled_quotas=None, tenant_id=None): qs = f(request, disabled_quotas, tenant_id) manila_quota = _get_manila_quota_data(request, "tenant_quota_get", disabled_quotas=disabled_quotas, tenant_id=tenant_id) if manila_quota: qs.add(manila_quota) return qs @wrap(quotas.get_disabled_quotas) def get_disabled_quotas(f, request): disabled_quotas = f(request) disabled_quotas.update(_get_manila_disabled_quotas(request)) return disabled_quotas @wrap(quotas.tenant_quota_usages) def tenant_quota_usages(f, request, tenant_id=None, targets=None): usages = f(request, tenant_id, targets) if 'shares' not in _get_manila_disabled_quotas(request): shares = manila.share_list(request) snapshots = manila.share_snapshot_list(request) sn_l = manila.share_network_list(request) gig_s = sum([int(v.size) for v in shares]) gig_ss = sum([int(v.size) for v in snapshots]) usages.tally('shares', len(shares)) usages.tally('share_gigabytes', gig_s) usages.tally('share_snapshots', len(snapshots)) usages.tally('share_snapshot_gigabytes', gig_ss) usages.tally('share_networks', len(sn_l)) return usages @wrap(quotas.tenant_limit_usages) def tenant_limit_usages(f, request): limits = f(request) if base.is_service_enabled(request, 'share'): try: limits.update(manila.tenant_absolute_limits(request)) shares = manila.share_list(request) snapshots = manila.share_snapshot_list(request) share_networks = manila.share_network_list(request) total_s_size = sum([getattr(share, 'size', 0) for share in shares]) total_ss_size = sum([getattr(ss, 'size', 0) for ss in snapshots]) limits['totalSharesUsed'] = len(shares) limits['totalShareGigabytesUsed'] = total_s_size limits['totalSnapshotsUsed'] = len(snapshots) limits['totalSnapshotGigabytesUsed'] = total_ss_size limits['totalShareNetworksUsed'] = len(share_networks) except Exception: msg = _("Unable to retrieve share limit information.") horizon.exceptions.handle(request, msg) return limits @wrap(quota_tbl.get_quota_name) def get_quota_name(f, quota): if quota.name in MANILA_QUOTA_NAMES: return MANILA_QUOTA_NAMES.get(quota.name) else: return f(quota) # # Add manila fields to Admin/Defaults/Update Defaults # class ManilaUpdateDefaultQuotaAction( default_workflows.UpdateDefaultQuotasAction): shares = horizon.forms.IntegerField(min_value=-1, label=_("Shares")) share_gigabytes = horizon.forms.IntegerField( min_value=-1, label=_("Share gigabytes")) share_snapshots = horizon.forms.IntegerField( min_value=-1, label=_("Share snapshots")) share_snapshot_gigabytes = horizon.forms.IntegerField( min_value=-1, label=_("Share snapshot gigabytes")) share_networks = horizon.forms.IntegerField( min_value=-1, label=_("Share Networks")) class Meta(object): name = _("Default Quotas") slug = 'update_default_quotas' help_text = _("From here you can update the default quotas " "(max limits).") class ManilaUpdateDefaultQuotasStep(default_workflows.UpdateDefaultQuotasStep): action_class = ManilaUpdateDefaultQuotaAction contributes = quotas.QUOTA_FIELDS class ManilaUpdateDefaultQuotas(default_workflows.UpdateDefaultQuotas): default_steps = (ManilaUpdateDefaultQuotasStep,) def handle(self, request, data): try: super(ManilaUpdateDefaultQuotas, self).handle(request, data) if base.is_service_enabled(request, 'share'): manila_data = dict([(key, data[key]) for key in MANILA_QUOTA_FIELDS]) manila.default_quota_update(request, **manila_data) except Exception: horizon.exceptions.handle(request, _('Unable to update default quotas.')) return True default_views.UpdateDefaultQuotasView.workflow_class = ( ManilaUpdateDefaultQuotas) # # Add manila fields to Identity/Projects/Modify Quotas # class ManilaUpdateProjectQuotaAction( project_workflows.UpdateProjectQuotaAction): shares = horizon.forms.IntegerField(min_value=-1, label=_("Shares")) share_gigabytes = horizon.forms.IntegerField( min_value=-1, label=_("Share gigabytes")) share_snapshots = horizon.forms.IntegerField( min_value=-1, label=_("Share snapshots")) share_snapshot_gigabytes = horizon.forms.IntegerField( min_value=-1, label=_("Share snapshot gigabytes")) share_networks = horizon.forms.IntegerField( min_value=-1, label=_("Share Networks")) class Meta(object): name = _("Quota") slug = 'update_quotas' help_text = _("Set maximum quotas for the project.") project_workflows.UpdateProjectQuota.action_class = ( ManilaUpdateProjectQuotaAction) project_workflows.UpdateProjectQuota.contributes = quotas.QUOTA_FIELDS class ManilaUpdateProject(project_workflows.UpdateProject): def handle(self, request, data): try: super(ManilaUpdateProject, self).handle(request, data) if base.is_service_enabled(request, 'share'): manila_data = dict([(key, data[key]) for key in MANILA_QUOTA_FIELDS]) manila.tenant_quota_update(request, data['project_id'], **manila_data) except Exception: horizon.exceptions.handle(request, _('Modified project information and ' 'members, but unable to modify ' 'project quotas.')) return True project_views.UpdateProjectView.workflow_class = ManilaUpdateProject # # Add manila fields to Identity/Projects/Create Project # class ManilaCreateProjectQuotaAction( project_workflows.CreateProjectQuotaAction): shares = horizon.forms.IntegerField(min_value=-1, label=_("Shares")) share_gigabytes = horizon.forms.IntegerField( min_value=-1, label=_("Share gigabytes")) share_snapshots = horizon.forms.IntegerField( min_value=-1, label=_("Share snapshots")) share_snapshot_gigabytes = horizon.forms.IntegerField( min_value=-1, label=_("Share snapshot gigabytes")) share_networks = horizon.forms.IntegerField( min_value=-1, label=_("Share Networks")) class Meta(object): name = _("Quota") slug = 'create_quotas' help_text = _("Set maximum quotas for the project.") project_workflows.CreateProjectQuota.action_class = ( ManilaCreateProjectQuotaAction) project_workflows.CreateProjectQuota.contributes = quotas.QUOTA_FIELDS class ManilaCreateProject(project_workflows.CreateProject): def handle(self, request, data): try: super(ManilaCreateProject, self).handle(request, data) if base.is_service_enabled(request, 'share'): manila_data = dict([(key, data[key]) for key in MANILA_QUOTA_FIELDS]) manila.tenant_quota_update(request, self.object.id, **manila_data) except Exception: horizon.exceptions.handle(request, _('Unable to set project quotas.')) return True project_views.CreateProjectView.workflow_class = ManilaCreateProject # # Add extra pie charts to Project/Compute Overview # class ManilaUsage(usage_base.ProjectUsage): def get_manila_limits(self): """Get share limits if manila is enabled.""" if not base.is_service_enabled(self.request, 'share'): return try: self.limits.update(manila.tenant_absolute_limits(self.request)) except Exception: msg = _("Unable to retrieve share limit information.") horizon.exceptions.handle(self.request, msg) return def get_limits(self): super(self.__class__, self).get_limits() self.get_manila_limits() def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) types = ( ("totalSharesUsed", "maxTotalShares", _("Shares")), ("totalShareGigabytesUsed", "maxTotalShareGigabytes", _("Share Storage")), ("totalShareSnapshotsUsed", "maxTotalShareSnapshots", _("Share Snapshots")), ("totalSnapshotGigabytesUsed", "maxTotalSnapshotGigabytes", _("Share Snapshots Storage")), ("totalShareNetworksUsed", "maxTotalShareNetworks", _("Share Networks")), ) for t in types: if t[0] in self.usage.limits and t[1] in self.usage.limits: context['charts'].append({ 'type': t[0], 'name': t[2], 'used': self.usage.limits[t[0]], 'max': self.usage.limits[t[1]], 'text': False, }) return context overview_views.ProjectOverview.get_context_data = get_context_data overview_views.ProjectOverview.usage_class = ManilaUsage manila-ui-2.13.0/manila_ui/dashboards/project/shares/forms.py000066400000000000000000000461231323215354300241630ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, 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 django.conf import settings from django.core.urlresolvers import reverse from django.forms import ValidationError # noqa from django.template.defaultfilters import filesizeformat # noqa from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from horizon.utils.memoized import memoized # noqa from openstack_dashboard.usage import quotas import six from manila_ui.api import manila from manila_ui.dashboards import utils from manila_ui import features from manilaclient.common.apiclient import exceptions as m_exceptions class CreateForm(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Share Name")) description = forms.CharField( label=_("Description"), required=False, widget=forms.Textarea(attrs={'rows': 3})) share_proto = forms.ChoiceField(label=_("Share Protocol"), required=True) size = forms.IntegerField(min_value=1, label=_("Size (GiB)")) share_type = forms.ChoiceField( label=_("Share Type"), required=True, widget=forms.Select( attrs={'class': 'switchable', 'data-slug': 'sharetype'})) availability_zone = forms.ChoiceField( label=_("Availability Zone"), required=False) def __init__(self, request, *args, **kwargs): super(CreateForm, self).__init__(request, *args, **kwargs) # NOTE(vkmc): choose only those share protocols that are enabled # FIXME(vkmc): this should be better implemented by having a # capabilities endpoint on the control plane. manila_features = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {}) self.enabled_share_protocols = manila_features.get( 'enabled_share_protocols', ['NFS', 'CIFS', 'GlusterFS', 'HDFS', 'CephFS', 'MapRFS']) self.enable_public_shares = manila_features.get( 'enable_public_shares', True) share_networks = manila.share_network_list(request) share_types = manila.share_type_list(request) self.fields['share_type'].choices = ( [("", "")] + [(st.name, st.name) for st in share_types]) availability_zones = manila.availability_zone_list(request) self.fields['availability_zone'].choices = ( [("", "")] + [(az.name, az.name) for az in availability_zones]) if features.is_share_groups_enabled(): share_groups = manila.share_group_list(request) self.fields['sg'] = forms.ChoiceField( label=_("Share Group"), choices=[("", "")] + [(sg.id, sg.name or sg.id) for sg in share_groups], required=False) self.sn_field_name_prefix = 'share-network-choices-' for st in share_types: extra_specs = st.get_keys() dhss = extra_specs.get('driver_handles_share_servers') # NOTE(vponomaryov): Set and tie share-network field only for # share types with enabled handling of share servers. if (isinstance(dhss, six.string_types) and dhss.lower() in ['true', '1']): sn_choices = ( [('', '')] + [(sn.id, sn.name or sn.id) for sn in share_networks]) sn_field_name = self.sn_field_name_prefix + st.name sn_field = forms.ChoiceField( label=_("Share Network"), required=True, choices=sn_choices, widget=forms.Select(attrs={ 'class': 'switched', 'data-switch-on': 'sharetype', 'data-sharetype-%s' % st.name: _("Share Network"), })) self.fields[sn_field_name] = sn_field self.fields['share_source_type'] = forms.ChoiceField( label=_("Share Source"), required=False, widget=forms.Select( attrs={'class': 'switchable', 'data-slug': 'source'})) self.fields['snapshot'] = forms.ChoiceField( label=_("Use snapshot as a source"), widget=forms.fields.SelectWidget( attrs={'class': 'switched', 'data-switch-on': 'source', 'data-source-snapshot': _('Snapshot')}, data_attrs=('size', 'name'), transform=lambda x: "%s (%sGiB)" % (x.name, x.size)), required=False) self.fields['metadata'] = forms.CharField( label=_("Metadata"), required=False, widget=forms.Textarea(attrs={'rows': 4})) if self.enable_public_shares: self.fields['is_public'] = forms.BooleanField( label=_("Make visible for all"), required=False, help_text=( "If set then all tenants will be able to see this share.")) self.fields['share_proto'].choices = [(sp, sp) for sp in self.enabled_share_protocols] if ("snapshot_id" in request.GET or kwargs.get("data", {}).get("snapshot")): try: snapshot = self.get_snapshot( request, request.GET.get("snapshot_id", kwargs.get("data", {}).get("snapshot"))) self.fields['name'].initial = snapshot.name self.fields['size'].initial = snapshot.size self.fields['snapshot'].choices = ((snapshot.id, snapshot),) try: # Set the share type from the original share orig_share = manila.share_get(request, snapshot.share_id) # NOTE(vponomaryov): we should use share type name, not ID, # because we use names in our choices above. self.fields['share_type'].initial = ( orig_share.share_type_name) except Exception: pass self.fields['size'].help_text = _( 'Share size must be equal to or greater than the snapshot ' 'size (%sGiB)') % snapshot.size del self.fields['share_source_type'] except Exception: exceptions.handle(request, _('Unable to load the specified snapshot.')) else: source_type_choices = [] try: snapshot_list = manila.share_snapshot_list(request) snapshots = [s for s in snapshot_list if s.status == 'available'] if snapshots: source_type_choices.append(("snapshot", _("Snapshot"))) choices = [('', _("Choose a snapshot"))] + \ [(s.id, s) for s in snapshots] self.fields['snapshot'].choices = choices else: del self.fields['snapshot'] except Exception: exceptions.handle(request, _("Unable to retrieve " "share snapshots.")) if source_type_choices: choices = ([('no_source_type', _("No source, empty share"))] + source_type_choices) self.fields['share_source_type'].choices = choices else: del self.fields['share_source_type'] def clean(self): cleaned_data = super(CreateForm, self).clean() errors = [k for k in self.errors.viewkeys()] # NOTE(vponomaryov): skip errors for share-network fields that are not # related to chosen share type. for k in errors: st_name = k.split(self.sn_field_name_prefix)[-1] chosen_st = cleaned_data.get('share_type') if (k.startswith(self.sn_field_name_prefix) and st_name != chosen_st): cleaned_data[k] = 'Not set' self.errors.pop(k, None) share_type = cleaned_data.get('share_type') if share_type: cleaned_data['share_network'] = cleaned_data.get( self.sn_field_name_prefix + share_type) return cleaned_data def handle(self, request, data): try: snapshot_id = None source_type = data.get('share_source_type', None) share_network = data.get('share_network', None) if (data.get("snapshot", None) and source_type in [None, 'snapshot']): # Create from Snapshot snapshot = self.get_snapshot(request, data["snapshot"]) snapshot_id = snapshot.id if (data['size'] < snapshot.size): error_message = _('The share size cannot be less than the ' 'snapshot size (%sGiB)') % snapshot.size raise ValidationError(error_message) else: data['size'] = int(data['size']) metadata = {} try: set_dict, unset_list = utils.parse_str_meta(data['metadata']) if unset_list: msg = _("Expected only pairs of key=value.") raise ValidationError(message=msg) metadata = set_dict except ValidationError as e: self.api_error(e.messages[0]) return False is_public = self.enable_public_shares and data['is_public'] share = manila.share_create( request, size=data['size'], name=data['name'], description=data['description'], proto=data['share_proto'], share_network=share_network, snapshot_id=snapshot_id, share_type=data['share_type'], is_public=is_public, metadata=metadata, availability_zone=data['availability_zone'], share_group_id=data.get('sg') or None, ) message = _('Creating share "%s"') % data['name'] messages.success(request, message) return share except ValidationError as e: self.api_error(e.messages[0]) except m_exceptions.BadRequest as e: self.api_error(_("Unable to create share. %s") % e.message) except Exception: exceptions.handle(request, ignore=True) self.api_error(_("Unable to create share.")) return False @memoized def get_snapshot(self, request, id): return manila.share_snapshot_get(request, id) class UpdateForm(forms.SelfHandlingForm): name = forms.CharField(max_length="255", label=_("Share Name")) description = forms.CharField(widget=forms.Textarea, label=_("Description"), required=False) is_public = forms.ChoiceField( choices=((None, 'Do not change share visibility'), (False, "Make it 'Private'"), (True, "Make it 'Public'")), label=_("Visibility"), required=False, widget=forms.Select( attrs={'class': 'switched', 'data-slug': 'sharetype'})) def __init__(self, request, *args, **kwargs): super(UpdateForm, self).__init__(request, *args, **kwargs) manila_features = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {}) self.enable_public_shares = manila_features.get( 'enable_public_shares', True) if not self.enable_public_shares: self.fields.pop('is_public') def handle(self, request, data): share_id = self.initial['share_id'] is_public = data['is_public'] if self.enable_public_shares else False try: share = manila.share_get(self.request, share_id) manila.share_update( request, share, data['name'], data['description'], is_public=is_public) message = _('Updating share "%s"') % data['name'] messages.success(request, message) return True except Exception: redirect = reverse("horizon:project:shares:index") exceptions.handle(request, _('Unable to update share.'), redirect=redirect) class UpdateMetadataForm(forms.SelfHandlingForm): metadata = forms.CharField(widget=forms.Textarea, label=_("Metadata"), required=False) def __init__(self, *args, **kwargs): super(UpdateMetadataForm, self).__init__(*args, **kwargs) meta_str = "" for k, v in self.initial["metadata"].iteritems(): meta_str += "%s=%s\r\n" % (k, v) self.initial["metadata"] = meta_str def handle(self, request, data): share_id = self.initial['share_id'] try: share = manila.share_get(self.request, share_id) set_dict, unset_list = utils.parse_str_meta(data['metadata']) if set_dict: manila.share_set_metadata(request, share, set_dict) if unset_list: manila.share_delete_metadata(request, share, unset_list) message = _('Updating share metadata "%s"') % share.name messages.success(request, message) return True except ValidationError as e: self.api_error(e.messages[0]) return False except Exception: redirect = reverse("horizon:project:shares:index") exceptions.handle(request, _('Unable to update share metadata.'), redirect=redirect) class AddRule(forms.SelfHandlingForm): access_type = forms.ChoiceField( label=_("Access Type"), required=True, choices=(('ip', 'ip'), ('user', 'user'), ('cert', 'cert'), ('cephx', 'cephx'))) access_level = forms.ChoiceField( label=_("Access Level"), required=True, choices=(('rw', 'read-write'), ('ro', 'read-only'),)) access_to = forms.CharField( label=_("Access To"), max_length="255", required=True) def handle(self, request, data): share_id = self.initial['share_id'] try: manila.share_allow( request, share_id, access_to=data['access_to'], access_type=data['access_type'], access_level=data['access_level']) message = _('Creating rule for "%s"') % data['access_to'] messages.success(request, message) return True except Exception: redirect = reverse("horizon:project:shares:manage_rules", args=[self.initial['share_id']]) exceptions.handle( request, _('Unable to add rule.'), redirect=redirect) class ExtendForm(forms.SelfHandlingForm): name = forms.CharField( max_length="255", label=_("Share Name"), widget=forms.TextInput(attrs={'readonly': 'readonly'}), required=False, ) orig_size = forms.IntegerField( label=_("Current Size (GiB)"), widget=forms.TextInput(attrs={'readonly': 'readonly'}), required=False, ) new_size = forms.IntegerField( label=_("New Size (GiB)"), ) def clean(self): cleaned_data = super(ExtendForm, self).clean() new_size = cleaned_data.get('new_size') orig_size = self.initial['orig_size'] if new_size <= orig_size: message = _("New size must be greater than current size.") self._errors["new_size"] = self.error_class([message]) return cleaned_data usages = quotas.tenant_limit_usages(self.request) availableGB = (usages['maxTotalShareGigabytes'] - usages['totalShareGigabytesUsed']) if availableGB < (new_size - orig_size): message = _('Share cannot be extended to %(req)iGiB as ' 'you only have %(avail)iGiB of your quota ' 'available.') params = {'req': new_size, 'avail': availableGB + orig_size} self._errors["new_size"] = self.error_class([message % params]) return cleaned_data def handle(self, request, data): share_id = self.initial['share_id'] try: manila.share_extend(request, share_id, data['new_size']) message = _('Extend share "%s"') % data['name'] messages.success(request, message) return True except Exception: redirect = reverse("horizon:project:shares:index") exceptions.handle(request, _('Unable to extend share.'), redirect=redirect) class RevertForm(forms.SelfHandlingForm): """Form for reverting a share to a snapshot.""" snapshot = forms.ChoiceField( label=_("Snapshot"), required=True, widget=forms.Select( attrs={'class': 'switchable', 'data-slug': 'share_snapshot'})) def __init__(self, req, *args, **kwargs): super(self.__class__, self).__init__(req, *args, **kwargs) # NOTE(vponomaryov): manila client does not allow to filter snapshots # using "created_at" field, so, we need to get all snapshots of a share # and do filtering here. search_opts = {'share_id': self.initial['share_id']} snapshots = manila.share_snapshot_list(req, search_opts=search_opts) amount_of_snapshots = len(snapshots) if amount_of_snapshots < 1: self.fields['snapshot'].choices = [("", "")] else: snapshot = snapshots[0] if amount_of_snapshots > 1: for s in snapshots[1:]: if s.created_at > snapshot.created_at: snapshot = s self.fields['snapshot'].choices = [ (snapshot.id, snapshot.name or snapshot.id)] def handle(self, request, data): share_id = self.initial['share_id'] snapshot_id = data['snapshot'] try: manila.share_revert(request, share_id, snapshot_id) message = _('Share "%(s)s" has been reverted to "%(ss)s" snapshot ' 'successfully') % {'s': share_id, 'ss': snapshot_id} messages.success(request, message) return True except Exception: redirect = reverse("horizon:project:shares:index") exceptions.handle( request, _('Unable to revert share to the snapshot.'), redirect=redirect) manila-ui-2.13.0/manila_ui/dashboards/project/shares/panel.py000066400000000000000000000016161323215354300241320ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.project import dashboard class Shares(horizon.Panel): name = _("Shares") slug = 'shares' permissions = ( 'openstack.services.share', ) dashboard.Project.register(Shares) manila-ui-2.13.0/manila_ui/dashboards/project/shares/replicas/000077500000000000000000000000001323215354300242575ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/shares/replicas/__init__.py000066400000000000000000000000001323215354300263560ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/shares/replicas/forms.py000066400000000000000000000055721323215354300257700ustar00rootroot00000000000000# Copyright (c) 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 django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import messages from manila_ui.api import manila class CreateReplicaForm(forms.SelfHandlingForm): availability_zone = forms.ChoiceField( label=_("Availability Zone"), required=False) def __init__(self, request, *args, **kwargs): super(CreateReplicaForm, self).__init__(request, *args, **kwargs) # populate share_id share_id = kwargs.get('initial', {}).get('share_id', []) self.fields['share_id'] = forms.CharField(widget=forms.HiddenInput(), initial=share_id) availability_zones = manila.availability_zone_list(request) self.fields['availability_zone'].choices = ( [(az.name, az.name) for az in availability_zones]) def handle(self, request, data): try: replica = manila.share_replica_create(request, data['share_id'], data['availability_zone']) message = _('Creating replica for share "%s".') % data['share_id'] messages.success(request, message) return replica except Exception: redirect = reverse("horizon:project:shares:manage_replicas", args=[data['share_id']]) exceptions.handle(request, _('Unable to create share replica.'), redirect=redirect) class SetReplicaAsActiveForm(forms.SelfHandlingForm): def handle(self, request, data): replica_id = self.initial['replica_id'] try: replica = manila.share_replica_get(self.request, replica_id) manila.share_replica_promote(request, replica) message = _('Setting replica "%s" as active...') % replica_id messages.success(request, message) return True except Exception: redirect = reverse("horizon:project:shares:index") exceptions.handle( request, _("Unable to set replica '%s' as active.") % replica_id, redirect=redirect) manila-ui-2.13.0/manila_ui/dashboards/project/shares/replicas/tables.py000066400000000000000000000141411323215354300261040ustar00rootroot00000000000000# Copyright (c) 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 django.core.urlresolvers import reverse from django.template.defaultfilters import title from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy import six from horizon import messages from horizon import tables from horizon.utils import filters from manila_ui.api import manila DELETABLE_STATUSES = ("error", "available") class UpdateReplicaRow(tables.Row): ajax = True def get_data(self, request, replica_id): replica = manila.share_replica_get(request, replica_id) return replica class CreateReplica(tables.LinkAction): name = "replicas" verbose_name = _("Create Replica") url = "horizon:project:shares:create_replica" classes = ("ajax-modal", "btn-camera") icon = "plus" policy_rules = (("share", "share:create_replica"),) def allowed(self, request, datum=None): share = manila.share_get(request, self.table.kwargs['share_id']) return share.replication_type is not None def get_policy_target(self, request, datum=None): return {"project_id": getattr(datum, "project_id", None)} def get_link_url(self): return reverse(self.url, args=[self.table.kwargs['share_id']]) class SetReplicaAsActive(tables.LinkAction): name = "set_replica_as_active" verbose_name = _("Set as Active") url = "horizon:project:shares:set_replica_as_active" classes = ("ajax-modal", "btn-create") policy_rules = (("share_replica", "share_replica:promote"),) def allowed(self, request, replica=None): return replica.replica_state == "in_sync" def get_policy_target(self, request, datum=None): return {"project_id": getattr(datum, "project_id", None)} def get_link_url(self, replica): return reverse(self.url, args=(replica.id,)) class DeleteReplica(tables.DeleteAction): policy_rules = (("share_replica", "share_replica:delete"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Replica", u"Delete Replicas", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Replica", u"Deleted Replicas", count ) def get_policy_target(self, request, datum=None): return {"project_id": getattr(datum, "project_id", None)} def delete(self, request, obj_id): try: manila.share_replica_delete(request, obj_id) except Exception: msg = _('Unable to delete replica "%s".') % obj_id messages.error(request, msg) def allowed(self, request, replica=None): if replica: share = manila.share_get(request, replica.share_id) replicas = manila.share_replica_list(request, replica.share_id) if share.replication_type is None: return False elif (share.replication_type is 'writable' and replica.status in DELETABLE_STATUSES and len(replicas) > 1) or ( share.replication_type in ('dr', 'readable') and replica.status in DELETABLE_STATUSES and replica.replica_state != 'active'): return True return False def single(self, data_table, request, object_id): try: manila.share_replica_delete(request, object_id) messages.success( request, _('Share replica %s has been deleted.') % object_id) except Exception: msg = _('Unable to delete replica "%s".') % object_id messages.error(request, msg) _DETAIL_URL = "horizon:project:shares:replica_detail" class ReplicasTable(tables.DataTable): STATUS_CHOICES = ( ("creating", None), ("available", True), ("error", False), ("deleting", None), ) STATUS_DISPLAY_CHOICES = ( ("available", pgettext_lazy("Current status of replica", u"Available")), ("creating", pgettext_lazy("Current status of replica", u"Creating")), ("deleting", pgettext_lazy("Current status of replica", u"Deleting")), ("error", pgettext_lazy("Current status of replica", u"Error")), ) id = tables.Column( "id", verbose_name=_("ID"), link=_DETAIL_URL, ) availability_zone = tables.Column( "availability_zone", verbose_name=_("Availability zone")) status = tables.Column( "status", filters=(title,), verbose_name=_("Status"), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES, ) replica_state = tables.Column( "replica_state", verbose_name=_("Replica State")) host = tables.Column("host", verbose_name=_("Host")) created_at = tables.Column( "created_at", verbose_name=_("Created At"), filters=(filters.parse_isotime,)) updated_at = tables.Column( "updated_at", verbose_name=_("Updated At"), filters=(filters.parse_isotime,)) def get_object_display(self, obj): return obj.id def get_object_id(self, obj): return six.text_type(obj.id) class Meta(object): name = "replicas" verbose_name = _("Replicas") status_columns = ("status",) row_class = UpdateReplicaRow table_actions = ( CreateReplica, ) row_actions = ( SetReplicaAsActive, DeleteReplica) manila-ui-2.13.0/manila_ui/dashboards/project/shares/replicas/tabs.py000066400000000000000000000020641323215354300255640ustar00rootroot00000000000000# Copyright (c) 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class ReplicaOverviewTab(tabs.Tab): name = _("Overview") slug = "overview" template_name = "project/shares/replicas/_detail_overview.html" def get_context_data(self, request): return {"replica": self.tab_group.kwargs['replica']} class ReplicaDetailTabs(tabs.TabGroup): slug = "replica_details" tabs = (ReplicaOverviewTab,) manila-ui-2.13.0/manila_ui/dashboards/project/shares/replicas/views.py000066400000000000000000000151211323215354300257660ustar00rootroot00000000000000# Copyright (c) 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 django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon import tabs from horizon.utils import memoized from manila_ui.api import manila from manila_ui.dashboards.project.shares.replicas import ( forms as replicas_forms) from manila_ui.dashboards.project.shares.replicas import ( tables as replicas_tables) from manila_ui.dashboards.project.shares.replicas import tabs as replicas_tabs from manila_ui.dashboards import utils as ui_utils class ManageReplicasView(tables.DataTableView): table_class = replicas_tables.ReplicasTable template_name = 'project/shares/replicas/manage_replicas.html' _redirect_url = 'horizon:project:shares:index' def get_context_data(self, **kwargs): context = super(ManageReplicasView, self).get_context_data(**kwargs) try: share = manila.share_get(self.request, self.kwargs["share_id"]) except Exception: redirect = reverse(self._redirect_url) exceptions.handle( self.request, _('Unable to retrieve share. %s') % self.kwargs["share_id"], redirect=redirect) context["share_display_name"] = share.name or share.id context["share"] = self.get_data() context["page_title"] = _( "Share Replicas: %(share_display_name)s") % { "share_display_name": context["share_display_name"]} return context @memoized.memoized_method def get_data(self): try: share_id = self.kwargs['share_id'] return manila.share_replica_list(self.request, share_id) except Exception: redirect = reverse(self._redirect_url) exceptions.handle( self.request, _('Unable to retrieve share replicas.'), redirect=redirect) class DetailReplicaView(tabs.TabView): tab_group_class = replicas_tabs.ReplicaDetailTabs template_name = 'project/shares/replicas/detail.html' _redirect_url = 'horizon:project:shares:index' def get_context_data(self, **kwargs): context = super(DetailReplicaView, self).get_context_data(**kwargs) replica = self.get_data() replica_display_name = replica.id context["replica"] = replica context["replica_display_name"] = replica_display_name context["page_title"] = _( "Replica Details: %(replica_display_name)s") % { "replica_display_name": replica_display_name} return context @memoized.memoized_method def get_data(self): try: replica_id = self.kwargs['replica_id'] replica = manila.share_replica_get(self.request, replica_id) replica.export_locations = ( manila.share_instance_export_location_list( self.request, replica_id)) export_locations = [ exp['path'] for exp in replica.export_locations ] replica.el_size = ui_utils.calculate_longest_str_size( export_locations) except Exception: redirect = reverse(self._redirect_url) exceptions.handle( self.request, _('Unable to retrieve replica %sdetails.') % replica_id, redirect=redirect) return replica def get_tabs(self, request, *args, **kwargs): replica = self.get_data() return self.tab_group_class(request, replica=replica, **kwargs) class CreateReplicaView(forms.ModalFormView): form_class = replicas_forms.CreateReplicaForm form_id = "create_replica" template_name = 'project/shares/replicas/create_replica.html' modal_header = _("Create Replica") modal_id = "create_replica_modal" submit_label = _("Create") submit_url = "horizon:project:shares:create_replica" success_url = 'horizon:project:shares:manage_replicas' page_title = _("Create Replica") def get_context_data(self, **kwargs): context = super(CreateReplicaView, self).get_context_data(**kwargs) context['share_id'] = self.kwargs['share_id'] args = (context['share_id'],) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): return {'share_id': self.kwargs["share_id"]} def get_success_url(self): return reverse(self.success_url, args=[self.kwargs['share_id']]) class SetReplicaAsActiveView(forms.ModalFormView): form_class = replicas_forms.SetReplicaAsActiveForm form_id = "set_replica_as_active" template_name = "project/shares/replicas/set_replica_as_active.html" modal_header = _("Set Replica as Active") modal_id = "set_replica_as_active_modal" submit_label = _("Set as Active") submit_url = "horizon:project:shares:set_replica_as_active" success_url = "horizon:project:shares:manage_replicas" page_title = _("Set Replica as Active") def get_success_url(self): return reverse(self.success_url, args=[self.get_object().share_id]) def get_object(self): if not hasattr(self, "_object"): replica_id = self.kwargs["replica_id"] try: self._object = manila.share_replica_get( self.request, replica_id) except Exception: msg = _("Unable to retrieve replica '%s'.") % replica_id url = reverse("horizon:project:shares:index") exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(SetReplicaAsActiveView, self).get_context_data( **kwargs) context["replica_id"] = self.kwargs["replica_id"] args = (context["replica_id"],) context["submit_url"] = reverse(self.submit_url, args=args) return context def get_initial(self): return {"replica_id": self.kwargs["replica_id"]} manila-ui-2.13.0/manila_ui/dashboards/project/shares/tables.py000066400000000000000000000341521323215354300243060ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.core.urlresolvers import NoReverseMatch # noqa from django.core.urlresolvers import reverse from django.template.defaultfilters import title # noqa from django.utils.translation import string_concat, ugettext_lazy # noqa from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import messages from horizon import tables from openstack_dashboard.usage import quotas from manila_ui.api import manila from manila_ui.dashboards.project.share_snapshots import tables as ss_tables from manila_ui.dashboards import utils from manila_ui import features DELETABLE_STATES = ( "AVAILABLE", "ERROR", "MANAGE_ERROR", ) class DeleteShare(tables.DeleteAction): policy_rules = (("share", "share:delete"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Share", u"Delete Shares", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Share", u"Deleted Shares", count ) def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None) return {"project_id": project_id} def delete(self, request, obj_id): share = manila.share_get(request, obj_id) try: manila.share_delete( request, share.id, share_group_id=share.share_group_id) except Exception: msg = _('Unable to delete share "%s". ') % obj_id messages.error(request, msg) def allowed(self, request, share=None): if share: # Row button return (share.status.upper() in DELETABLE_STATES and not getattr(share, 'has_snapshot', False)) # Table button. Always return 'True'. return True class CreateShare(tables.LinkAction): name = "create" verbose_name = _("Create Share") url = "horizon:project:shares:create" classes = ("ajax-modal", "btn-create") icon = "plus" policy_rules = (("share", "share:create"),) def allowed(self, request, share=None): usages = quotas.tenant_quota_usages(request) if usages['shares']['available'] <= 0: if "disabled" not in self.classes: self.classes = [c for c in self.classes] + ['disabled'] self.verbose_name = string_concat(self.verbose_name, ' ', _("(Quota exceeded)")) else: self.verbose_name = _("Create Share") classes = [c for c in self.classes if c != "disabled"] self.classes = classes return True class EditShare(tables.LinkAction): name = "edit" verbose_name = _("Edit Share") url = "horizon:project:shares:update" classes = ("ajax-modal", "btn-create") policy_rules = (("share", "share:update"),) def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None) return {"project_id": project_id} def allowed(self, request, share=None): return share.status in ("available", "in-use") class EditShareMetadata(tables.LinkAction): name = "update_metadata" verbose_name = _("Edit Share Metadata") url = "horizon:project:shares:update_metadata" classes = ("ajax-modal", "btn-create") policy_rules = (("share", "share:update_share_metadata"),) def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None) return {"project_id": project_id} def allowed(self, request, share=None): return share.status in ("available", "in-use") class ExtendShare(tables.LinkAction): name = "extend_share" verbose_name = _("Extend Share") url = "horizon:project:shares:extend" classes = ("ajax-modal", "btn-create") policy_rules = (("share", "share:extend"),) def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None) return {"project_id": project_id} def allowed(self, request, share=None): return share.status.lower() in ("available",) class RevertShare(tables.LinkAction): name = "revert_share" verbose_name = _("Revert Share") url = "horizon:project:shares:revert" classes = ("ajax-modal", "btn-create") policy_rules = (("share", "share:revert"),) def get_policy_target(self, request, datum=None): project_id = None if datum: project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None) return {"project_id": project_id} def allowed(self, request, share=None): return ( share.revert_to_snapshot_support and share.status.lower() == "available" ) class UpdateRow(tables.Row): ajax = True def get_data(self, request, share_id): share = manila.share_get(request, share_id) if not share.name: share.name = share_id if share.share_network_id: share_net = manila.share_network_get(request, share.share_network_id) share.share_network = share_net.name or share_net.id else: share.share_network = None share.metadata = utils.metadata_to_str(share.metadata) return share def get_size(share): return _("%sGiB") % share.size class SharesTableBase(tables.DataTable): STATUS_CHOICES = ( ("available", True), ("AVAILABLE", True), ("creating", None), ("CREATING", None), ("deleting", None), ("DELETING", None), ("reverting", None), ("migrating", None), ("migrating_to", None), ("error", False), ("ERROR", False), ("error_deleting", False), ("ERROR_DELETING", False), ("MANAGE_ERROR", False), ("UNMANAGE_ERROR", False), ("extending_error", False), ("reverting_error", False), ) STATUS_DISPLAY_CHOICES = ( ("available", pgettext_lazy("Current status of share", u"Available")), ("AVAILABLE", pgettext_lazy("Current status of share", u"Available")), ("creating", pgettext_lazy("Current status of share", u"Creating")), ("CREATING", pgettext_lazy("Current status of share", u"Creating")), ("deleting", pgettext_lazy("Current status of share", u"Deleting")), ("DELETING", pgettext_lazy("Current status of share", u"Deleting")), ("migrating", pgettext_lazy("Current status of share", u"Migrating")), ("migrating_to", pgettext_lazy("Current status of share", u"Migrating to")), ("error", pgettext_lazy("Current status of share", u"Error")), ("ERROR", pgettext_lazy("Current status of share", u"Error")), ("error_deleting", pgettext_lazy("Current status of share", u"Deleting")), ("ERROR_DELETING", pgettext_lazy("Current status of share", u"Deleting")), ("MANAGE_ERROR", pgettext_lazy("Current status of share", u"Manage Error")), ("UNMANAGE_ERROR", pgettext_lazy("Current status of share", u"Unmanage Error")), ("extending_error", pgettext_lazy("Current status of share", u"Extending Error")), ("reverting_error", pgettext_lazy("Current status of share", u"Reverting Error")), ) name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:project:shares:detail") description = tables.Column("description", verbose_name=_("Description"), truncate=40) metadata = tables.Column("metadata", verbose_name=_("Metadata")) size = tables.Column(get_size, verbose_name=_("Size"), attrs={'data-type': 'size'}) status = tables.Column("status", filters=(title,), verbose_name=_("Status"), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES) def get_object_display(self, obj): return obj.name or obj.id def get_share_group_link(share): if features.is_share_groups_enabled() and share.share_group_id: return reverse( "horizon:project:share_groups:detail", args=(share.share_group_id,)) else: return None share_group_id = tables.Column( "share_group_id", verbose_name=_("Share Group"), empty_value="-", link=get_share_group_link, ) class ManageRules(tables.LinkAction): name = "manage_rules" verbose_name = _("Manage Rules") url = "horizon:project:shares:manage_rules" classes = ("btn-edit",) policy_rules = (("share", "share:access_get_all"),) class ManageReplicas(tables.LinkAction): name = "manage_replicas" verbose_name = _("Manage Replicas") url = "horizon:project:shares:manage_replicas" classes = ("btn-edit",) policy_rules = (("share", "share:replica_get_all"),) def allowed(self, request, share): share_replication_enabled = share.replication_type is not None return features.is_replication_enabled() and share_replication_enabled class AddRule(tables.LinkAction): name = "rule_add" verbose_name = _("Add rule") url = 'horizon:project:shares:rule_add' classes = ("ajax-modal", "btn-create") icon = "plus" policy_rules = (("share", "share:allow_access"),) def allowed(self, request, share=None): share = manila.share_get(request, self.table.kwargs['share_id']) return share.status in ("available", "in-use") def get_link_url(self): return reverse(self.url, args=[self.table.kwargs['share_id']]) class DeleteRule(tables.DeleteAction): policy_rules = (("share", "share:deny_access"),) @staticmethod def action_present(count): return ungettext_lazy( u"Delete Rule", u"Delete Rules", count ) @staticmethod def action_past(count): return ungettext_lazy( u"Deleted Rule", u"Deleted Rules", count ) def delete(self, request, obj_id): try: manila.share_deny(request, self.table.kwargs['share_id'], obj_id) except Exception: msg = _('Unable to delete rule "%s".') % obj_id exceptions.handle(request, msg) class UpdateRuleRow(tables.Row): ajax = True def get_data(self, request, rule_id): rules = manila.share_rules_list(request, self.table.kwargs['share_id']) if rules: for rule in rules: if rule.id == rule_id: return rule raise exceptions.NotFound class RulesTable(tables.DataTable): access_type = tables.Column("access_type", verbose_name=_("Access Type")) access_to = tables.Column("access_to", verbose_name=_("Access to")) access_level = tables.Column( "access_level", verbose_name=_("Access Level")) status = tables.Column("state", verbose_name=_("Status")) access_key = tables.Column("access_key", verbose_name=_("Access Key")) def get_object_display(self, obj): return obj.id class Meta(object): name = "rules" verbose_name = _("Rules") status_columns = ["status"] row_class = UpdateRuleRow table_actions = ( AddRule, DeleteRule) row_actions = ( DeleteRule,) def get_share_network(share): name = share.share_network_name return name if name != "None" else None class SharesTable(SharesTableBase): name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:project:shares:detail") visibility = tables.Column( "is_public", verbose_name=_("Visibility"), help_text=("Whether this share visible to all tenants (public) or " "only for owner (private)."), filters=(lambda d: 'public' if d is True else 'private', ), ) proto = tables.Column("share_proto", verbose_name=_("Protocol")) share_network = tables.Column("share_network", verbose_name=_("Share Network"), empty_value="-") class Meta(object): name = "shares" verbose_name = _("Shares") status_columns = ["status"] row_class = UpdateRow table_actions = ( tables.NameFilterAction, CreateShare, DeleteShare) row_actions = ( EditShare, ExtendShare, RevertShare, ss_tables.CreateShareSnapshot, ManageRules, ManageReplicas, EditShareMetadata, DeleteShare) columns = [ 'name', 'description', 'metadata', 'size', 'status', 'proto', 'visibility', 'share_network', ] if features.is_share_groups_enabled(): columns.append('share_group_id') manila-ui-2.13.0/manila_ui/dashboards/project/shares/tabs.py000066400000000000000000000017341323215354300237650ustar00rootroot00000000000000# 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 django.utils.translation import ugettext_lazy as _ from horizon import tabs class OverviewTab(tabs.Tab): name = _("Overview") slug = "overview" template_name = "project/shares/_detail.html" def get_context_data(self, request): return {"share": self.tab_group.kwargs['share']} class ShareDetailTabs(tabs.TabGroup): slug = "share_details" tabs = ( OverviewTab, ) manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/000077500000000000000000000000001323215354300244535ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/000077500000000000000000000000001323215354300257405ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_create.html000066400000000000000000000003261323215354300302310ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}
{% include "project/shares/_limits.html" with usages=usages %}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_detail.html000066400000000000000000000070531323215354300302340ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Overview" %}


{% trans "Name" %}
{{ share.name }}
{% trans "ID" %}
{{ share.id }}
{% if share.description %}
{% trans "Description" %}
{{ share.description }}
{% endif %}
{% trans "Status" %}
{{ share.status|capfirst }}
{% trans "Export locations" %}
{% for el in share.export_locations %}

Path:
Preferred: {{ el.preferred }}
{% if el.is_admin_only == True or el.is_admin_only == False %}
Is admin only: {{ el.is_admin_only }}
{% endif %} {% if el.share_instance_id %}
Share Replica ID: {{ el.share_instance_id }}
{% endif %}

{% endfor %} {% if share.snapshot_id %}
{% trans "Snapshot ID" %}
{% url 'horizon:project:share_snapshots:share_snapshot_detail' share.snapshot_id as snapshot_url%}
{{ share.snapshot_id }}
{% endif %}
{% trans "Visibility" %}
{% if share.is_public == True %}
{{ 'public' }}
{% else %}
{{ 'private' }}
{% trans "Availability zone" %}
{{ share.availability_zone }}
{% endif %}
{% trans "Size" %}
{{ share.size }} {% trans "GiB" %}
{% trans "Protocol" %}
{{ share.share_proto }}
{% if share.share_type %}
{% trans "Share type" %}

Name: {{ share.share_type_name }}
ID: {{ share.share_type }}

{% endif %} {% if share.share_network_id %}
{% trans "Share Network" %}
{% url 'horizon:project:share_networks:share_network_detail' share.share_network_id as sn_url%}
{{ share.share_network_id }}
{% endif %} {% if share.share_group_id %}
{% trans "Share Group" %}
{% url 'horizon:project:share_groups:detail' share.share_group_id as sg_url%}
{{ share.share_group_id }}
{% endif %}
{% trans "Mount snapshot support" %}
{{ share.mount_snapshot_support }}
{% trans "Created" %}
{{ share.created_at|parse_date }}
{% trans "Host" %}
{{ share.host }}
{% trans "Task state" %}
{{ share.task_state }}

{% trans "Access Rules" %}


{% for rule in share.rules %}
{{ rule.access_type }}

Access to: {{ rule.access_to }}
Access Level: {{ rule.access_level }}
Status: {{ rule.state }}
Access Key: {{ rule.access_key }}

{% endfor %}

{% trans "Metadata" %}


{% for key, value in share.metadata.items %}
{{ key }}
{{ value }}
{% endfor %}
manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_extend.html000066400000000000000000000003351323215354300302550ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}
{% include "project/shares/_extend_limits.html" with usages=usages %}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_extend_limits.html000066400000000000000000000020341323215354300316340ustar00rootroot00000000000000{% load i18n horizon humanize bootstrap %}

{% trans "Description" %}:

{% trans "Extend the size of a share. " %}

{% trans "Share Limits" %}

{% trans "Total Gibibytes" %} ({{ usages.totalShareGigabytesUsed|intcomma }} {% trans "GiB" %})
{{ usages.maxTotalShareGigabytes|intcomma|quota:_("GiB") }}
{% widthratio usages.totalShareGigabytesUsed usages.maxTotalShareGigabytes 100 as gigabytes_percent %} {% bs_progress_bar gigabytes_percent 0 %}
manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_limits.html000066400000000000000000000044571323215354300303000ustar00rootroot00000000000000{% load i18n horizon humanize bootstrap %}

{% trans "Description" %}:

{% trans "Select parameters of share you want to create. " %}

{% trans "Metadata" %}:

{% trans "One line - one action. Empty strings will be ignored." %}
{% trans "To add metadata use:" %}

key=value

{% trans "Share Limits" %}

{% trans "Total Gibibytes" %}
{% blocktrans with used=usages.totalShareGigabytesUsed|intcomma quota=usages.maxTotalShareGigabytes|intcomma|quotainf %}{{ used }} of {{ quota }} GiB Used{% endblocktrans %}
{{ minifyspace }}
{% widthratio usages.totalShareGigabytesUsed usages.maxTotalShareGigabytes 100 as gigabytes_percent %} {% bs_progress_bar gigabytes_percent 0 %}
{{ endminifyspace }}
{% block type_title %}{% trans "Number of Shares" %}{% endblock %}
{% block used_of_quota %} {% blocktrans with used=usages.totalSharesUsed|intcomma quota=usages.maxTotalShares|intcomma|quotainf %}{{ used }} of {{ quota }} Used{% endblocktrans %} {% endblock %}
{{ minifyspace }}
{% block show_progress_bar %} {% widthratio usages.totalSharesUsed usages.maxTotalShares 100 as shares_percent %} {% widthratio 100 usages.maxTotalShares 1 as single_step %} {% bs_progress_bar shares_percent single_step %} {% endblock %}
{{ endminifyspace }} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_manage_rules.html000066400000000000000000000001001323215354300314160ustar00rootroot00000000000000
{{ manage_rules_table.render }}
manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_revert.html000066400000000000000000000003501323215354300302720ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "From here you can revert the share to its latest snapshot." %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_rule_add.html000066400000000000000000000005471323215354300305520ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% blocktrans %} Add policy rule to share, 'ip' rule represents ipv4 address, 'user' rule represents username or usergroup, 'cephx' rule represents ceph auth ID. {% endblocktrans %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_update.html000066400000000000000000000003631323215354300302510ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "From here you can modify name, description and visibility of a share." %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/_update_metadata.html000066400000000000000000000007101323215354300321050ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Metadata" %}:

{% trans "One line - one action. Empty strings will be ignored." %}
{% trans "To add metadata use:" %}

key=value
{% trans "To unset metadata use:" %}
key
{% trans "All pairs that are in field for left are set for this metadata." %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/create.html000066400000000000000000000002651323215354300300740ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Share" %}{% endblock %} {% block main %} {% include 'project/shares/_create.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/detail.html000066400000000000000000000003331323215354300300670ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/extend.html000066400000000000000000000002651323215354300301200ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Extend Share" %}{% endblock %} {% block main %} {% include 'project/shares/_extend.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/index.html000066400000000000000000000003311323215354300277320ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Shares" %}{% endblock %} {% block main %}
{{ shares_table.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/manage_rules.html000066400000000000000000000002311323215354300312640ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Rules" %}{% endblock %} {% block main %} {{ table.render }} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/replicas/000077500000000000000000000000001323215354300275425ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/replicas/_create_replica.html000066400000000000000000000003311323215354300335260ustar00rootroot00000000000000{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}

{% trans "Description" %}:

{% trans "Create share replica in specific availability zone." %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/replicas/_detail_overview.html000066400000000000000000000027121323215354300337610ustar00rootroot00000000000000{% load i18n sizeformat parse_date %}

{% trans "Share Replica Overview" %}


{% trans "ID" %}
{{ replica.id }}
{% trans "Share" %}
{% url 'horizon:project:shares:detail' replica.share_id as share_url%}
{{ replica.share_id }}
{% trans "Status" %}
{{ replica.status|capfirst }}
{% trans "Replica state" %}
{{ replica.replica_state|capfirst }}
{% trans "Export locations" %}
{% for el in replica.export_locations %}

Path:
Preferred: {{ el.preferred }}
{% if el.is_admin_only == True or el.is_admin_only == False %}
Is admin only: {{ el.is_admin_only }}
{% endif %}

{% endfor %}
{% trans "Availability zone" %}
{{ replica.availability_zone }}
{% trans "Created" %}
{{ replica.created_at|parse_date }}
{% trans "Updated" %}
{{ replica.updated_at|parse_date }}
{% trans "Host" %}
{{ replica.host }}
_set_replica_as_active.html000066400000000000000000000003311323215354300350150ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/replicas{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body %}

{% trans "Set share replica with ID" %} "{{ replica_id }}" {% trans "as Active?" %}

{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/replicas/create_replica.html000066400000000000000000000003151323215354300333710ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Create Share Replica" %}{% endblock %} {% block main %} {% include 'project/shares/replicas/_create_replica.html' %} {% endblock %}manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/replicas/detail.html000066400000000000000000000003351323215354300316730ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Replica Details" %}{% endblock %} {% block main %}
{{ tab_group.render }}
{% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/replicas/manage_replicas.html000066400000000000000000000002341323215354300335410ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Share Replicas" %}{% endblock %} {% block main %} {{ table.render }} {% endblock %} set_replica_as_active.html000066400000000000000000000003261323215354300346620ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/replicas{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Set Replica as Active" %}{% endblock %} {% block main %} {% include 'project/shares/replicas/_set_replica_as_active.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/revert.html000066400000000000000000000002651323215354300301400ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Revert Share" %}{% endblock %} {% block main %} {% include 'project/shares/_revert.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/rule_add.html000066400000000000000000000002631323215354300304060ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Add Rule" %}{% endblock %} {% block main %} {% include 'project/shares/_rule_add.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/update.html000066400000000000000000000002631323215354300301110ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Edit Share" %}{% endblock %} {% block main %} {% include 'project/shares/_update.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/templates/shares/update_metadata.html000066400000000000000000000003051323215354300317460ustar00rootroot00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Edit Share Metadata" %}{% endblock %} {% block main %} {% include 'project/shares/_update_metadata.html' %} {% endblock %} manila-ui-2.13.0/manila_ui/dashboards/project/shares/urls.py000066400000000000000000000051561323215354300240230ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.conf import urls from manila_ui.dashboards.project.shares.replicas import views as replica_views from manila_ui.dashboards.project.shares import views as shares_views from manila_ui import features urlpatterns = [ urls.url( r'^$', shares_views.SharesView.as_view(), name='index'), urls.url( r'^create/$', shares_views.CreateView.as_view(), name='create'), urls.url( r'^(?P[^/]+)/rules/$', shares_views.ManageRulesView.as_view(), name='manage_rules'), urls.url( r'^(?P[^/]+)/rule_add/$', shares_views.AddRuleView.as_view(), name='rule_add'), urls.url( r'^(?P[^/]+)/$', shares_views.DetailView.as_view(), name='detail'), urls.url( r'^(?P[^/]+)/update/$', shares_views.UpdateView.as_view(), name='update'), urls.url( r'^(?P[^/]+)/update_metadata/$', shares_views.UpdateMetadataView.as_view(), name='update_metadata'), urls.url( r'^(?P[^/]+)/extend/$', shares_views.ExtendView.as_view(), name='extend'), urls.url( r'^(?P[^/]+)/revert/$', shares_views.RevertView.as_view(), name='revert'), ] if features.is_replication_enabled(): urlpatterns.extend([ urls.url( r'^(?P[^/]+)/create_replica/$', replica_views.CreateReplicaView.as_view(), name='create_replica'), urls.url( r'^(?P[^/]+)/replicas/$', replica_views.ManageReplicasView.as_view(), name='manage_replicas'), urls.url( r'^replica/(?P[^/]+)$', replica_views.DetailReplicaView.as_view(), name='replica_detail'), urls.url( r'^replica/(?P[^/]+)/set_replica_as_active$', replica_views.SetReplicaAsActiveView.as_view(), name='set_replica_as_active'), ]) manila-ui-2.13.0/manila_ui/dashboards/project/shares/views.py000066400000000000000000000321271323215354300241710ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import forms from horizon import tables from horizon import tabs from horizon.utils import memoized from manila_ui.api import manila from manila_ui.dashboards.project.shares import forms as share_form from manila_ui.dashboards.project.shares import tables as shares_tables from manila_ui.dashboards.project.shares import tabs as shares_tabs from manila_ui.dashboards import utils as ui_utils from openstack_dashboard.usage import quotas class ShareTableMixIn(object): def _get_shares(self, search_opts=None): try: return manila.share_list(self.request, search_opts=search_opts) except Exception: exceptions.handle(self.request, _('Unable to retrieve share list.')) return [] def _set_id_if_nameless(self, shares): for share in shares: # It is possible to create a share with no name if not share.name: share.name = share.id class SharesView(tables.MultiTableView, ShareTableMixIn): table_classes = ( shares_tables.SharesTable, ) template_name = "project/shares/index.html" page_title = _("Shares") @memoized.memoized_method def get_shares_data(self): share_nets_names = {} share_nets = manila.share_network_list(self.request) for share_net in share_nets: share_nets_names[share_net.id] = share_net.name try: shares = manila.share_list(self.request) for share in shares: share.share_network = ( share_nets_names.get(share.share_network_id) or share.share_network_id) share.metadata = ui_utils.metadata_to_str(share.metadata) snapshots = manila.share_snapshot_list(self.request, detailed=True) share_ids_with_snapshots = [] for snapshot in snapshots: share_ids_with_snapshots.append(snapshot.to_dict()['share_id']) for share in shares: if share.to_dict()['id'] in share_ids_with_snapshots: setattr(share, 'has_snapshot', True) else: setattr(share, 'has_snapshot', False) except Exception: exceptions.handle( self.request, _('Unable to retrieve share list.')) return [] # Gather our tenants to correlate against IDs return shares class DetailView(tabs.TabView): tab_group_class = shares_tabs.ShareDetailTabs template_name = 'project/shares/detail.html' def get_context_data(self, **kwargs): context = super(DetailView, self).get_context_data(**kwargs) share = self.get_data() share_display_name = share.name or share.id context["share"] = share context["share_display_name"] = share_display_name context["page_title"] = _("Share Details: " "%(share_display_name)s") % { 'share_display_name': share_display_name} return context @memoized.memoized_method def get_data(self): try: share_id = self.kwargs['share_id'] share = manila.share_get(self.request, share_id) share.rules = manila.share_rules_list(self.request, share_id) share.export_locations = manila.share_export_location_list( self.request, share_id) export_locations = [ exp['path'] for exp in share.export_locations] share.el_size = ui_utils.calculate_longest_str_size( export_locations) except Exception: redirect = reverse('horizon:project:shares:index') exceptions.handle(self.request, _('Unable to retrieve share details.'), redirect=redirect) return share def get_tabs(self, request, *args, **kwargs): share = self.get_data() return self.tab_group_class(request, share=share, **kwargs) class CreateView(forms.ModalFormView): form_class = share_form.CreateForm form_id = "create_share" template_name = 'project/shares/create.html' modal_header = _("Create Share") modal_id = "create_share_modal" submit_label = _("Create") submit_url = reverse_lazy("horizon:project:shares:create") success_url = reverse_lazy("horizon:project:shares:index") page_title = _('Create a Share') def get_context_data(self, **kwargs): context = super(CreateView, self).get_context_data(**kwargs) try: context['usages'] = quotas.tenant_limit_usages(self.request) except Exception: exceptions.handle(self.request) return context class UpdateView(forms.ModalFormView): form_class = share_form.UpdateForm form_id = "update_share" template_name = 'project/shares/update.html' modal_header = _("Edit Share") modal_id = "update_share_modal" submit_label = _("Edit") submit_url = "horizon:project:shares:update" success_url = reverse_lazy("horizon:project:shares:index") page_title = _('Edit Share') def get_object(self): if not hasattr(self, "_object"): vol_id = self.kwargs['share_id'] try: self._object = manila.share_get(self.request, vol_id) except Exception: msg = _('Unable to retrieve share.') url = reverse('horizon:project:shares:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(UpdateView, self).get_context_data(**kwargs) return context def get_initial(self): self.submit_url = reverse(self.submit_url, kwargs=self.kwargs) share = self.get_object() return {'share_id': self.kwargs["share_id"], 'name': share.name, 'description': share.description} class UpdateMetadataView(forms.ModalFormView): form_class = share_form.UpdateMetadataForm form_id = "update_share_metadata" template_name = 'project/shares/update_metadata.html' modal_header = _("Edit Share Metadata") modal_id = "update_share_metadata_modal" submit_label = _("Save Changes") submit_url = "horizon:project:shares:update_metadata" success_url = reverse_lazy("horizon:project:shares:index") page_title = _('Edit Share Metadata') def get_object(self): if not hasattr(self, "_object"): sh_id = self.kwargs['share_id'] try: self._object = manila.share_get(self.request, sh_id) except Exception: msg = _('Unable to retrieve share.') url = reverse('horizon:project:shares:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(UpdateMetadataView, self).get_context_data(**kwargs) args = (self.get_object().id,) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): share = self.get_object() return {'share_id': self.kwargs["share_id"], 'metadata': share.metadata} class AddRuleView(forms.ModalFormView): form_class = share_form.AddRule form_id = "rule_add" template_name = 'project/shares/rule_add.html' modal_header = _("Add Rule") modal_id = "rule_add_modal" submit_label = _("Add") submit_url = "horizon:project:shares:rule_add" success_url = reverse_lazy("horizon:project:shares:index") page_title = _('Add Rule') def get_object(self): if not hasattr(self, "_object"): vol_id = self.kwargs['share_id'] try: self._object = manila.share_get(self.request, vol_id) except Exception: msg = _('Unable to retrieve share.') url = reverse('horizon:project:shares:index') exceptions.handle(self.request, msg, redirect=url) return self._object def get_context_data(self, **kwargs): context = super(AddRuleView, self).get_context_data(**kwargs) args = (self.get_object().id,) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): share = self.get_object() return {'share_id': self.kwargs["share_id"], 'name': share.name, 'description': share.description} def get_success_url(self): return reverse("horizon:project:shares:manage_rules", args=[self.kwargs['share_id']]) class ManageRulesView(tables.DataTableView): table_class = shares_tables.RulesTable template_name = 'project/shares/manage_rules.html' def get_context_data(self, **kwargs): context = super(ManageRulesView, self).get_context_data(**kwargs) share = manila.share_get(self.request, self.kwargs['share_id']) context['share_display_name'] = share.name or share.id context["share"] = self.get_data() context["page_title"] = _("Share Rules: " "%(share_display_name)s") % { 'share_display_name': context['share_display_name']} return context @memoized.memoized_method def get_data(self): try: share_id = self.kwargs['share_id'] rules = manila.share_rules_list(self.request, share_id) except Exception: redirect = reverse('horizon:project:shares:index') exceptions.handle(self.request, _('Unable to retrieve share rules.'), redirect=redirect) return rules class ExtendView(forms.ModalFormView): form_class = share_form.ExtendForm form_id = "extend_share" template_name = 'project/shares/extend.html' modal_header = _("Extend Share") modal_id = "extend_share_modal" submit_label = _("Extend") submit_url = "horizon:project:shares:extend" success_url = reverse_lazy("horizon:project:shares:index") page_title = _('Extend Share') @memoized.memoized_method def get_object(self): try: return manila.share_get(self.request, self.kwargs['share_id']) except Exception: exceptions.handle(self.request, _('Unable to retrieve share.')) def get_context_data(self, **kwargs): context = super(ExtendView, self).get_context_data(**kwargs) args = (self.get_object().id,) context['submit_url'] = reverse(self.submit_url, args=args) try: context['usages'] = quotas.tenant_limit_usages(self.request) context['usages']['totalShareGigabytesUsed'] -= int( self.get_object().size) except Exception: exceptions.handle(self.request) return context def get_initial(self): share = self.get_object() if not share or isinstance(share, Exception): raise exceptions.NotFound() return { 'share_id': self.kwargs["share_id"], 'name': share.name or share.id, 'orig_size': share.size, 'new_size': int(share.size) + 1, } class RevertView(forms.ModalFormView): form_class = share_form.RevertForm form_id = "revert_share" template_name = 'project/shares/revert.html' modal_header = _("Revert Share to a Snapshot") modal_id = "revert_share_modal" submit_label = _("Revert share to a snapshot") submit_url = "horizon:project:shares:revert" success_url = reverse_lazy("horizon:project:shares:index") page_title = _('Revert Share to a Snapshot') @memoized.memoized_method def get_object(self): try: return manila.share_get(self.request, self.kwargs['share_id']) except Exception: exceptions.handle(self.request, _('Unable to retrieve share.')) def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) args = (self.get_object().id,) context['submit_url'] = reverse(self.submit_url, args=args) return context def get_initial(self): share = self.get_object() if not share or isinstance(share, Exception): raise exceptions.NotFound() return { 'share_id': self.kwargs["share_id"], 'name': share.name or share.id, } manila-ui-2.13.0/manila_ui/dashboards/utils.py000066400000000000000000000074131323215354300212410ustar00rootroot00000000000000# 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 django.forms import ValidationError # noqa from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ html_escape_table = { "&": "&", '"': """, "'": "'", ">": ">", "<": "<", } def html_escape(text): return ''.join(html_escape_table.get(s, s) for s in text) def parse_str_meta(meta_s): """Parse multiline string with data from form. :option meta_s: str - string with keys and values :returns: tuple of dict with key-value for set and list with keys for unset :raises: ValidationError """ strings = [el.strip() for el in meta_s.split("\n") if len(el.strip()) > 0] set_dict = {} unset_list = [] msg = "" for string in strings: if string.count("=") == 0: # Key for unsetting key = string.strip('\"\'\ ') if len(key) not in range(1, 256): msg = _("Key '%s' has improper length.") % key elif " " in key: msg = _("Key can not contain spaces. See string '%s'.") % key elif key not in unset_list: unset_list.append(key) else: # Key-value pair for setting pair = [p.strip('\"\'\ ') for p in string.split("=", 1)] if not all(len(p) in range(1, 256) for p in pair): msg = _("All keys and values must be in range from 1 to 255.") elif pair[0] in list(set_dict.keys()): msg = _("Duplicated keys '%s'.") % pair[0] elif " " in pair[0]: msg = _("Keys should not contain spaces. " "Error in '%s'.") % string else: set_dict[pair[0]] = pair[1] duplicated_keys = [uk for uk in unset_list if uk in list(set_dict.keys())] if duplicated_keys: msg = _("Duplicated keys '%s'.") % str(duplicated_keys) if msg: raise ValidationError(message=msg) return set_dict, unset_list def metadata_to_str(metadata, meta_visible_limit=4, text_length_limit=25): # Only convert dictionaries if not hasattr(metadata, 'keys'): return metadata meta = [] meta_keys = metadata.keys() meta_keys.sort() meta_keys = meta_keys[:meta_visible_limit] for k in meta_keys: k_shortenned = k if len(k) > text_length_limit: k_shortenned = k[:text_length_limit] + '...' v = metadata[k] if len(v) > text_length_limit: v = v[:text_length_limit] + '...' meta.append("%s = %s" % (html_escape(k_shortenned), html_escape(v))) meta_str = "
".join(meta) if len(metadata.keys()) > meta_visible_limit and meta_str[-3:] != "...": meta_str += '...' return mark_safe(meta_str) def get_nice_security_service_type(security_service): type_mapping = { 'ldap': 'LDAP', 'active_directory': 'Active Directory', 'kerberos': 'Kerberos', } return type_mapping.get(security_service.type, security_service.type) def calculate_longest_str_size(str_list): size = 40 for str_val in str_list: current_size = len(str_val) if current_size > size: size = current_size return size manila-ui-2.13.0/manila_ui/exceptions.py000066400000000000000000000017561323215354300201540ustar00rootroot00000000000000# Copyright 2012 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # Copyright 2012 Nebula, Inc. # # 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 exceptions as manilaclient UNAUTHORIZED = ( manilaclient.AuthorizationFailure, manilaclient.Unauthorized, ) NOT_FOUND = ( manilaclient.NotFound, ) RECOVERABLE = ( manilaclient.ClientException, ) manila-ui-2.13.0/manila_ui/features.py000066400000000000000000000036151323215354300176050ustar00rootroot00000000000000# Copyright 2017 Mirantis Inc. # # 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. """ This module stores functions that return boolean values and say which manila features are enabled and which are disabled among those that are optional for manila UI. These functions are required mostly for complex features, which consist of more than one logical part in manila UI and requires appropriate logic change in more than 1 place. For example, to disable share groups feature we need to do following: - Remove 'share_groups' panel from 'share groups' panel group in each dashboard. - Disable or do not register URLs for disabled features, so, no one will be able to request disabled features knowing direct URL. - Add/remove buttons for other (not disabled) features that are related to it somehow. """ from django.conf import settings from horizon.utils import memoized @memoized.memoized def is_share_groups_enabled(): manila_config = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {}) return manila_config.get('enable_share_groups', True) @memoized.memoized def is_replication_enabled(): manila_config = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {}) return manila_config.get('enable_replication', True) @memoized.memoized def is_migration_enabled(): manila_config = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {}) return manila_config.get('enable_migration', True) manila-ui-2.13.0/manila_ui/local/000077500000000000000000000000001323215354300165025ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/__init__.py000066400000000000000000000000001323215354300206010ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled/000077500000000000000000000000001323215354300200745ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled/_80_manila_admin_add_share_panel_group.py000066400000000000000000000015231323215354300301130ustar00rootroot00000000000000# Copyright 2017 Mirantis Inc. # # 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. # The slug of the panel group to be added to HORIZON_CONFIG. Required. PANEL_GROUP = 'share' # The display name of the PANEL_GROUP. Required. PANEL_GROUP_NAME = 'Share' # The slug of the dashboard the PANEL_GROUP associated with. Required. PANEL_GROUP_DASHBOARD = 'admin' manila-ui-2.13.0/manila_ui/local/enabled/_80_manila_project_add_share_panel_group.py000066400000000000000000000020161323215354300304670ustar00rootroot00000000000000# Copyright 2017 Mirantis Inc. # # 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 manila_ui import exceptions # The slug of the panel group to be added to HORIZON_CONFIG. Required. PANEL_GROUP = 'share' # The display name of the PANEL_GROUP. Required. PANEL_GROUP_NAME = 'Share' # The slug of the dashboard the PANEL_GROUP associated with. Required. PANEL_GROUP_DASHBOARD = 'project' ADD_EXCEPTIONS = { 'recoverable': exceptions.RECOVERABLE, 'not_found': exceptions.NOT_FOUND, 'unauthorized': exceptions.UNAUTHORIZED, } manila-ui-2.13.0/manila_ui/local/enabled/_9010_manila_admin_add_shares_panel_to_share_panel_group.py000066400000000000000000000013011323215354300334750ustar00rootroot00000000000000# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'shares' ADD_PANEL = 'manila_ui.dashboards.admin.shares.panel.Shares' _9010_manila_project_add_shares_panel_to_share_panel_group.py000066400000000000000000000013051323215354300340000ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'project' PANEL_GROUP = 'share' PANEL = 'shares' ADD_PANEL = 'manila_ui.dashboards.project.shares.panel.Shares' _9020_manila_admin_add_share_snapshots_panel_to_share_panel_group.py000066400000000000000000000013331323215354300353430ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'share_snapshots' ADD_PANEL = 'manila_ui.dashboards.admin.share_snapshots.panel.ShareSnapshots' _9020_manila_project_add_share_snapshots_panel_to_share_panel_group.py000066400000000000000000000013371323215354300357250ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'project' PANEL_GROUP = 'share' PANEL = 'share_snapshots' ADD_PANEL = 'manila_ui.dashboards.project.share_snapshots.panel.ShareSnapshots' _9030_manila_admin_add_share_types_panel_to_share_panel_group.py000066400000000000000000000013171323215354300344700ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'share_types' ADD_PANEL = 'manila_ui.dashboards.admin.share_types.panel.ShareTypes' _9040_manila_admin_add_share_networks_panel_to_share_panel_group.py000066400000000000000000000013301323215354300351740ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'share_networks' ADD_PANEL = 'manila_ui.dashboards.admin.share_networks.panel.ShareNetworks' _9040_manila_project_add_share_networks_panel_to_share_panel_group.py000066400000000000000000000013341323215354300355560ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'project' PANEL_GROUP = 'share' PANEL = 'share_networks' ADD_PANEL = 'manila_ui.dashboards.project.share_networks.panel.ShareNetworks' _9050_manila_admin_add_security_services_panel_to_share_panel_group.py000066400000000000000000000013501323215354300357130ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'security_services' ADD_PANEL = ( 'manila_ui.dashboards.admin.security_services.panel.SecurityServices') _9050_manila_project_add_security_services_panel_to_share_panel_group.py000066400000000000000000000013541323215354300362750ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'project' PANEL_GROUP = 'share' PANEL = 'security_services' ADD_PANEL = ( 'manila_ui.dashboards.project.security_services.panel.SecurityServices') _9060_manila_admin_add_share_servers_panel_to_share_panel_group.py000066400000000000000000000013251323215354300350170ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'share_servers' ADD_PANEL = 'manila_ui.dashboards.admin.share_servers.panel.ShareServers' _9070_manila_admin_add_share_instances_panel_to_share_panel_group.py000066400000000000000000000013331323215354300353150ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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. PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'share_instances' ADD_PANEL = 'manila_ui.dashboards.admin.share_instances.panel.ShareInstances' _9080_manila_admin_add_share_groups_panel_to_share_panel_group.py000066400000000000000000000015371323215354300346540ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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 manila_ui import features PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'share_groups' if features.is_share_groups_enabled(): ADD_PANEL = 'manila_ui.dashboards.admin.share_groups.panel.ShareGroups' else: REMOVE_PANEL = not features.is_share_groups_enabled() _9080_manila_project_add_share_groups_panel_to_share_panel_group.py000066400000000000000000000015431323215354300352270ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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 manila_ui import features PANEL_DASHBOARD = 'project' PANEL_GROUP = 'share' PANEL = 'share_groups' if features.is_share_groups_enabled(): ADD_PANEL = 'manila_ui.dashboards.project.share_groups.panel.ShareGroups' else: REMOVE_PANEL = not features.is_share_groups_enabled() _9085_manila_admin_add_share_group_snapshots_panel_to_share_panel_group.py000066400000000000000000000016171323215354300365770ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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 manila_ui import features PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'share_group_snapshots' if features.is_share_groups_enabled(): ADD_PANEL = ('manila_ui.dashboards.admin.share_group_snapshots.panel.' 'ShareGroupSnapshots') else: REMOVE_PANEL = not features.is_share_groups_enabled() _9085_manila_project_add_share_group_snapshots_panel_to_share_panel_group.py000066400000000000000000000016231323215354300371520ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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 manila_ui import features PANEL_DASHBOARD = 'project' PANEL_GROUP = 'share' PANEL = 'share_group_snapshots' if features.is_share_groups_enabled(): ADD_PANEL = ('manila_ui.dashboards.project.share_group_snapshots.panel.' 'ShareGroupSnapshots') else: REMOVE_PANEL = not features.is_share_groups_enabled() _9090_manila_admin_add_share_group_types_panel_to_share_panel_group.py000066400000000000000000000015701323215354300357130ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/enabled# Copyright 2017 Mirantis Inc. # # 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 manila_ui import features PANEL_DASHBOARD = 'admin' PANEL_GROUP = 'share' PANEL = 'share_group_types' if features.is_share_groups_enabled(): ADD_PANEL = ( 'manila_ui.dashboards.admin.share_group_types.panel.ShareGroupTypes') else: REMOVE_PANEL = not features.is_share_groups_enabled() manila-ui-2.13.0/manila_ui/local/enabled/__init__.py000066400000000000000000000000001323215354300221730ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/local_settings.d/000077500000000000000000000000001323215354300217365ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/local/local_settings.d/_90_manila_shares.py000066400000000000000000000021001323215354300255560ustar00rootroot00000000000000# Copyright 2016 Red Hat Inc. # # 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. # The OPENSTACK_MANILA_FEATURES settings can be used to enable or disable # the UI for the various services provided by Manila. OPENSTACK_MANILA_FEATURES = { 'enable_share_groups': True, 'enable_replication': True, 'enable_migration': True, 'enable_public_share_type_creation': True, 'enable_public_share_group_type_creation': True, 'enable_public_shares': True, 'enabled_share_protocols': ['NFS', 'CIFS', 'GlusterFS', 'HDFS', 'CephFS', 'MapRFS'], } manila-ui-2.13.0/manila_ui/locale/000077500000000000000000000000001323215354300166475ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/cs/000077500000000000000000000000001323215354300172545ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/cs/LC_MESSAGES/000077500000000000000000000000001323215354300210415ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/cs/LC_MESSAGES/django.po000066400000000000000000000503661323215354300226550ustar00rootroot00000000000000# Stanislav Ulrych , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.9.1.dev1\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-06-08 22:16+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2016-11-24 11:18+0000\n" "Last-Translator: Stanislav Ulrych \n" "Language-Team: Czech\n" "Language: cs\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n" #, python-format msgid "%sGiB" msgstr "%sGiB" msgid "(Quota exceeded)" msgstr "(kvóta překročena)" msgid "Access Level" msgstr "Úroveň přístupu" msgid "Access To" msgstr "Přístup do" msgid "Access Type" msgstr "Typ přístupu" msgid "Access to" msgstr "Přístup do" msgctxt "Current status of share network" msgid "Active" msgstr "Aktivní" msgctxt "Current status of share server" msgid "Active" msgstr "Aktivní" msgid "Add" msgstr "Přidat" msgid "Add Rule" msgstr "Přidat pravidlo" msgid "Add Security Service" msgstr "Přidat bezpečnostní službu" msgid "Add rule" msgstr "Přidat pravidlo" msgid "Add security services to share network." msgstr "Přidat bezpečnostní služby do sítě sdílení." msgid "All keys and values must be in range from 1 to 255." msgstr "Všechny klíče a hodnoty musí být v rozsau 1 až 255." msgid "Allow project access to share type." msgstr "Povolit projektu přístup k typu sdílení" msgid "At least one security service must be specified." msgstr "Musí být zadána alespoň jedna bezpečnostní služba." msgid "Availability Zone" msgstr "Zóna dostupnosti" msgid "Availability zone" msgstr "Zóna dostupnosti" msgctxt "Current status of replica" msgid "Available" msgstr "Dostupné" msgctxt "Current status of share" msgid "Available" msgstr "Dostupné" msgctxt "Current status of snapshot" msgid "Available" msgstr "Dostupné" msgid "Available projects" msgstr "Dostupné projekty" msgid "Available security services" msgstr "Dostupné bezpečnostní služby" msgid "Cancel Migration" msgstr "Zrušit migraci" msgid "Cancel migration" msgstr "Zrušit migraci" msgid "Cancel migration of a Share" msgstr "Zrušit migraci sdílení" msgid "Choose a snapshot" msgstr "Zvolte snapshot" msgid "Complete Migration" msgstr "Dokončit migraci" msgid "Complete migration" msgstr "Dokončit migraci" msgid "Complete migration of a Share" msgstr "Dokončit migraci sdílení" msgid "Confirm Migration Cancelling of Share" msgstr "Potvrdit zrušení migrace sdílení" msgid "Confirm Migration Completion of Share" msgstr "Potvrdit dokončení migraci sdílení" msgid "Confirm Password" msgstr "Potvrdit heslo" msgid "Create" msgstr "Vytvořit" msgid "Create Replica" msgstr "Vytvořit repliku" msgid "Create Security Service" msgstr "Vytvořit bezpečnostní službu" msgid "Create Share" msgstr "Vytvořit sdílení" msgid "Create Share Network" msgstr "Vytvořit síť sdílení" msgid "Create Share Snapshot" msgstr "Vytvořit snapshot sdílení." msgid "Create Share Type" msgstr "Vytvořit typ sdílení" msgid "Create a Share" msgstr "Vytvořit sdílení" msgid "Created At" msgstr "Vytvořeno" msgctxt "Current status of replica" msgid "Creating" msgstr "Vytváření" msgctxt "Current status of share" msgid "Creating" msgstr "Vytváření" msgctxt "Current status of share server" msgid "Creating" msgstr "Vytváření" msgctxt "Current status of snapshot" msgid "Creating" msgstr "Výtvářeno" #, python-format msgid "Creating replica for share \"%s\"." msgstr "Vytváření repliky pro sdílení \"%s\"." #, python-format msgid "Creating rule for \"%s\"" msgstr "Vytváření pravidla pro \"%s\"" #, python-format msgid "Creating share \"%s\"" msgstr "Vytváření sdílení \"%s\"" #, python-format msgid "Creating share snapshot \"%s\"." msgstr "Vytváření snapshotu sdílení \"%s\"." msgid "Current Size (GiB)" msgstr "Současná velikost (GiB)" msgid "DNS IP" msgstr "DNS IP" msgctxt "Current status of replica" msgid "Deleting" msgstr "Mazání" msgctxt "Current status of share" msgid "Deleting" msgstr "Mazání" msgid "Description" msgstr "Popis" msgid "Domain" msgstr "Doména" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "Volby driveru ('volume_id' pro generický driver atd.)" #, python-format msgid "Duplicated keys '%s'." msgstr "Duplikátní klíče '%s'." msgid "Edit" msgstr "Upravit" msgid "Edit Security Service" msgstr "Upravit bezpečnostní službu" msgid "Edit Share" msgstr "Upravit sdílení" msgid "Edit Share Metadata" msgstr "Upravit metadata sdílení" msgid "Edit Share Network" msgstr "Upravit síť sdílení" msgctxt "Current status of replica" msgid "Error" msgstr "Chyba" msgctxt "Current status of share" msgid "Error" msgstr "Chyba" msgctxt "Current status of share network" msgid "Error" msgstr "Chyba" msgctxt "Current status of share server" msgid "Error" msgstr "Chyba" msgctxt "Current status of snapshot" msgid "Error" msgstr "Chyba" msgid "Extend" msgstr "Rozšířit" msgid "Extend Share" msgstr "Rozšířit sdílení" #, python-format msgid "Extend share \"%s\"" msgstr "Zvětšit sdílení \"%s\"" msgid "Extra specs" msgstr "Dodatečné specifikace" msgid "Force Host Assisted Migration" msgstr "Vynutit migraci asistovanou hostitelem" msgid "From here you can update share network info. " msgstr "Zde můžete upravit informace o síti sdílení." msgid "From here you can update the default quotas (max limits)." msgstr "Zde můžete aktualizovat výchozí kvóty (max. limity)." msgid "Host" msgstr "Hostitel" msgid "Host of share" msgstr "Hostitel sdílení" msgid "Host to migrate share" msgstr "Hostitel na který má být sdílení migrováno" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "Hostitel, na němž se sdílení nachází, příklad: some.host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "Verze IP" msgid "Id" msgstr "Id" msgctxt "Current status of share server" msgid "In-use" msgstr "Používá se" msgctxt "Current status of snapshot" msgid "In-use" msgstr "Používá se" msgctxt "Current status of share network" msgid "Inactive" msgstr "Neaktivní" #, python-format msgid "Key '%s' has improper length." msgstr "Klíč '%s' nemá správnou délku." #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "Klíč nemůže obsahovat mezery. Viz řetězec '%s'." #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "Klíče nemohou obsahovat mezery. Chyba v '%s'." msgid "Make visible for all" msgstr "Učinit viditelné pro všechny" msgid "Manage" msgstr "Spravovat" msgctxt "Current status of share" msgid "Manage Error" msgstr "Spravovat chyby" msgid "Manage Rules" msgstr "Správa pravidel" msgid "Manage Share Type Access" msgstr "Spravovat přístup typů sdílení" msgid "Metadata" msgstr "Metadata" msgid "Migrate Share" msgstr "Migrovat sdílení" msgid "Migrate a Share" msgstr "Migrovat sdílení" msgctxt "Current status of share" msgid "Migrating" msgstr "Migrace" msgctxt "Current status of share" msgid "Migrating to" msgstr "Migrace do" #, python-format msgid "Migration of share %(name)s is at %(progress)s percent." msgstr "Migrace sdílení %(name)s je hotová z %(progress)s procent." msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "Informace o projektu a členové projektu modifikováni, ale modifikace kvót " "selhala." msgid "Name" msgstr "Název" msgid "Network Type" msgstr "Typ sítě" msgid "Networks" msgstr "Sítě" msgid "Neutron Net" msgstr "Neutron síť" msgid "Neutron Subnet" msgstr "Neutron podsíť" msgid "New Size (GiB)" msgstr "Nová velkost (GiB)" msgid "New share network to be set in migrated share" msgstr "Nová síť sdílení pro zmigrované sdílení" msgid "New size must be greater than current size." msgstr "Nová velikost musí být větší než současná." msgid "No projects found." msgstr "Nenalezeny žádné projekty." msgid "No projects selected." msgstr "Nevybrány žádné projekty." msgid "No security services found." msgstr "Nenalezeny žádné bezpečnostní služby." msgid "No security services selected." msgstr "Nevybrány žádné bezpečnostní služby." msgid "No source, empty share" msgstr "Žádný zdroj, prázdné sdílení" msgid "Nova Net" msgstr "Nova Net" msgid "Overview" msgstr "Přehled" msgid "Password" msgstr "Heslo" msgid "Passwords do not match." msgstr "Hesla se neshodují." msgid "Preserve Metadata" msgstr "Zachovat metadata" msgid "Project" msgstr "Projekt" msgid "Projects with access to share type" msgstr "Projekty s přístupem k typu sdílení" msgid "Protocol" msgstr "Protokol" msgid "Public" msgstr "Veřejný" msgid "Quota" msgstr "Kvóta" #, python-format msgid "Replica Details: %(replica_display_name)s" msgstr "Detaily repliky: %(replica_display_name)s" msgid "Replica State" msgstr "Stav repliky" msgid "Rules" msgstr "Pravidla" msgid "Save Changes" msgstr "Uložit změny" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "Detaily bezpečnostní služby: %(service_display_name)s" msgid "Security Services" msgstr "Bezpečnostní služby" msgid "Security services within share network" msgstr "Bezpečnostní služby v síti sdílení" msgid "Segmentation Id" msgstr "ID segmentace" msgid "Selected projects" msgstr "Vybrané projekty" msgid "Selected security services" msgstr "Vybrané bezpečnostní služby" msgid "Server" msgstr "Server" msgid "Set Replica as Active" msgstr "Nastavit repliku jako aktivní" msgid "Set as Active" msgstr "Nastavit jako aktivní" msgid "Set maximum quotas for the project." msgstr "Nastavit maximální kvóty pro projekt." #, python-format msgid "Setting replica \"%s\" as active..." msgstr "Nastavování repliky \"%s\" jako aktivní..." #, python-format msgid "Share Details: %(share_display_name)s" msgstr "Detaily sdílení: %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "Detaily sdílení: %(share_name)s" msgid "Share ID" msgstr "Share ID" #, python-format msgid "Share Instance Details: %s" msgstr "Detaily instance sdílení: %s" msgid "Share Instances" msgstr "Instance sdílení" msgid "Share Name" msgstr "Název sdílení" msgid "Share Network" msgstr "Síť sdílení" #, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "Detaily sítě sdílení: %(network_display_name)s" msgid "Share Network Info" msgstr "Informace o síti sdílení" msgid "Share Networks" msgstr "Sítě sdílení" msgid "Share Protocol" msgstr "Protokol sdílení" #, python-format msgid "Share Replicas: %(share_display_name)s" msgstr "Repliky sdílení: %(share_display_name)s" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "Pravidla sdílení: %(share_display_name)s" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "Detaily serveru sdílení: %(server_name)s" msgid "Share Server Id" msgstr "Id serveru sdílení" msgid "Share Servers" msgstr "Servery sdílení" msgid "Share Snapshots" msgstr "Snapshoty sdílení" msgid "Share Snapshots Storage" msgstr "Úložiště snapshotů sdílení" msgid "Share Source" msgstr "Zdroj sdílení" msgid "Share Storage" msgstr "Sdílené úložiště" msgid "Share Type" msgstr "Typ sdílení" msgid "Share Types" msgstr "Typy sdílení" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "Sdílení nemůže být zvětšeno na %(req)iGiB, protože máte dostupných pouze " "%(avail)iGiB z vaší kvóty." msgid "Share name to be assigned" msgstr "Název sdílení, který bude přidělen." #, python-format msgid "Share replica %s has been deleted." msgstr "Replika sdílení %s byla smazána." #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "Velikost sdílení musí být větší nebo roven velikosti snapshotu (%sGiB)" msgid "Shares" msgstr "Sdílení" msgid "Shares Networks" msgstr "Sítě sdílení" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "Velikost" msgid "Size (GiB)" msgstr "Velikost (GiB)" msgid "Snapshot" msgstr "Snapshot" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "Detaily snapshot: %(snapshot_display_name)s" msgid "Source" msgstr "Zdroj" msgid "Start migration" msgstr "Spustit migraci" msgid "Status" msgstr "Status" #, python-format msgid "Successfully created security service: %s" msgstr "Úspěšně vytvořena bezpečnostní služba: %s" #, python-format msgid "Successfully created share network: %s" msgstr "Úspěšně vytvořena síť sdílení: %s" #, python-format msgid "Successfully created share type: %s" msgstr "Úspěšně vytvořen typ sdílení: %s" #, python-format msgid "Successfully sent the request to cancel migration of share: %s." msgstr "Požadavek na zrušení migrace sdílení odeslán úspěšně: %s." #, python-format msgid "Successfully sent the request to complete migration of share: %s." msgstr "Požadavek na dokončení migrace sdílení odeslán úspěšně: %s." #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "Žádost o správu sdílení byla úspěšně odeslána: %s" #, python-format msgid "Successfully sent the request to migrate share: %s." msgstr "Požadavek na migraci sdílení odeslán úspěšně: %s." #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "Žádost o zrušení správy sdílení byla úspěšně odeslána: %s" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "Úspěšně aktualizovány dodatečné specifikace pro typ sdílení '%s'." #, python-format msgid "Successfully updated security service \"%s\"" msgstr "Úspěšně aktualizována bezpečnostní služba: %s" #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "Velikost sdílení nemůže být menší než velikost snapshotu (%sGiB)" msgid "Type" msgstr "Typ" msgid "Unable to add rule." msgstr "Nelze přidat pravidlo." #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "Momentálně nelze zrušit migraci sdílení %s." #, python-format msgid "Unable to complete migration of share %s." msgstr "Nelze dokončit migraci sdílení %s." msgid "Unable to create security service." msgstr "Nelze vytvořit bezpečnostní službu." msgid "Unable to create share network." msgstr "Nelze vytvořit sít sdílení." msgid "Unable to create share replica." msgstr "Nelze vytvořit repliku sdílení." msgid "Unable to create share snapshot." msgstr "Nelze vytvořit snapshot sdílení." msgid "Unable to create share type." msgstr "Nelze vytvořit typ sdílení." msgid "Unable to create share." msgstr "Nelze vytvořit sdílení." #, python-format msgid "Unable to delete rule \"%s\"." msgstr "Nelze smazat pravidlo \"%s\"." #, python-format msgid "Unable to delete share \"%s\". " msgstr "Nelze smazat sdílení \"%s\". " #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "Nelze smazat snapshot \"%s\". Jedno nebo více sdílení na něm závisí." msgid "Unable to extend share." msgstr "Nelze zvětšit sdílení." msgid "Unable to get information about share type access." msgstr "Nelze získat informaci o přístupu ke sdílení" msgid "Unable to get list of projects." msgstr "Nelze získat seznam projektů." msgid "Unable to get the security services hosts" msgstr "Nelze získat hostitele bezpečnostních služeb" msgid "Unable to load the specified snapshot." msgstr "Nelze načíst zadaný snapshot." msgid "Unable to manage share" msgstr "Nelze spravovat sdílení." #, python-format msgid "Unable to migrate share %s." msgstr "Nelze migrovat sdílení %s." #, python-format msgid "Unable to obtain progress of migration of share %s at this moment." msgstr "Momentálně nelze získat stav procesu migrace sdílení %s." #, python-format msgid "Unable to resync replica '%s'." msgstr "Nelze synchronizovat repliku '%s'." msgid "Unable to retrieve list of projects." msgstr "Nelze získat seznam projektů." msgid "Unable to retrieve quotas." msgstr "Nelze získat kvóty." #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "Nelze získat detaily repliky %sdetails." #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "Nelze získat detaily o bezpečnostní službě '%s'." msgid "Unable to retrieve security services" msgstr "Nelze získat bezpečnostní služby." msgid "Unable to retrieve security_service." msgstr "Nelze získat security_service." msgid "Unable to retrieve share details." msgstr "Nelze získat detaily sdílení." msgid "Unable to retrieve share instance details." msgstr "Nelze získat detaily instance sdílení." msgid "Unable to retrieve share instances." msgstr "Nelze získat instance sdílení." msgid "Unable to retrieve share list." msgstr "Nelze získat seznam sdílení." msgid "Unable to retrieve share network details." msgstr "Nelze získat detaily sítě sdílení." msgid "Unable to retrieve share network." msgstr "Nelze získat sít sdílení." msgid "Unable to retrieve share networks" msgstr "Nelze získat sítě sdílení" msgid "Unable to retrieve share replicas." msgstr "Nelze získat repliky sdílení." msgid "Unable to retrieve share rules." msgstr "Nelze získat pravidla sdílení." msgid "Unable to retrieve share server details." msgstr "Nelze získat detaily serveru sdílení." msgid "Unable to retrieve share servers" msgstr "Nelze získat servery sdílení" msgid "Unable to retrieve share snapshots list." msgstr "Nelze získat seznam snapshotů sdílení." msgid "Unable to retrieve share snapshots." msgstr "Nelze získat snapshoty sdílení." msgid "Unable to retrieve share." msgstr "Nelze získat sdílení." #, python-format msgid "Unable to retrieve share. %s" msgstr "Nelze získat sdílení. %s" msgid "Unable to retrieve share_type." msgstr "Nelze získat share_type." msgid "Unable to retrieve snapshot details." msgstr "Nelze získat detaily snapshotu." msgid "Unable to retrieve snapshot." msgstr "Nelze získat snapshot." msgid "Unable to retrieve volume details." msgstr "Nelze získat detaily svazku." msgid "Unable to set project quotas." msgstr "Nelze nastavit kvóty projektu." #, python-format msgid "Unable to set replica '%s' as active." msgstr "Nelze nastavit repliku '%s' jako aktivní." msgid "Unable to unmanage share." msgstr "Nelze zrušit správu sdílení." #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "Nelze aktualizovat přístup pro typ sdílení \"%s\"." msgid "Unable to update default quotas." msgstr "Nelze aktualizovat výchozí kvóty." msgid "Unable to update extra_specs for share type." msgstr "Nelze aktualizovat extra_specs pro typ sdílení." msgid "Unable to update security service." msgstr "Nelze aktualizovat bezpečnostní službu." msgid "Unable to update share metadata." msgstr "Nelze aktualizovat metadata sdílení." #, python-format msgid "Unable to update share network \"%s\"." msgstr "Nelze aktualizovat síť sdílení \"%s\"." msgid "Unable to update share network." msgstr "Nelze aktualizovat síť sdílení." msgid "Unable to update share type." msgstr "Nelze aktualizovat typ sdílení." msgid "Unable to update share." msgstr "Nelze aktualizovat sdílení." msgid "Unknown" msgstr "Neznámé" msgid "Unmanage" msgstr "Zrušit správu" msgid "Update" msgstr "Aktualizovat" msgid "Update Share Network" msgstr "Aktualizovat síť sdílení" msgid "Updated At" msgstr "Aktualizováno" #, python-format msgid "Updated access for share type \"%s\"." msgstr "Aktualizován přístup pro typ sdílení \"%s\"." #, python-format msgid "Updated share network \"%s\"." msgstr "Aktualizována síť sdílení \"%s\"." #, python-format msgid "Updating share \"%s\"" msgstr "Aktualizace sdílení \"%s\"" #, python-format msgid "Updating share metadata \"%s\"" msgstr "Aktualizace metadat sdílení \"%s\"" #, python-format msgid "Updating share network \"%s\"" msgstr "Aktualizace sítě sdílení \"%s\"" msgid "Use snapshot as a source" msgstr "Použít snapshot jako zdroj" msgid "User" msgstr "Uživatel" msgid "Writable" msgstr "Zapisovatelný" manila-ui-2.13.0/manila_ui/locale/de/000077500000000000000000000000001323215354300172375ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/de/LC_MESSAGES/000077500000000000000000000000001323215354300210245ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/de/LC_MESSAGES/django.po000066400000000000000000001206071323215354300226340ustar00rootroot00000000000000# Frank Kloeker , 2016. #zanata # Robert Simai , 2016. #zanata # Frank Kloeker , 2017. #zanata # Robert Simai , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.10.1.dev16\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-08-18 17:02+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-08-20 04:32+0000\n" "Last-Translator: Frank Kloeker \n" "Language-Team: German\n" "Language: de\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #, python-format msgid "%sGiB" msgstr "%sGiB" msgid "(Quota exceeded)" msgstr "(Kontingent überschritten)" msgid "Access Key" msgstr "Zugriffsschlüssel" msgid "Access Level" msgstr "Zugriffsstufe" msgid "Access To" msgstr "Zugriff auf" msgid "Access Type" msgstr "Zugriffstyp" msgid "Access to" msgstr "Zugriff auf" msgctxt "Current status of share network" msgid "Active" msgstr "Aktiv" msgctxt "Current status of share server" msgid "Active" msgstr "Aktiv" msgid "Add" msgstr "Hinzufügen" msgid "Add Rule" msgstr "Regel hinzufügen" msgid "Add Security Service" msgstr "Sicherheitsdienst hinzufügen" msgid "Add Share Snapshot Rule" msgstr "Freigabe Schattenkopie Regel hinzufügen" msgid "Add rule" msgstr "Regel hinzufügen" msgid "Add security services to share network." msgstr "Füge Sicherheitsdienst zu Freigabenetzwerk hinzu." msgid "All keys and values must be in range from 1 to 255." msgstr "Alle Schlüssel und Werte müssen im Bereich zwischen 1 und 255 liegen." msgid "Allow project access to share group type." msgstr "Erlaube Projektzugriff zum Gruppenfreigabentyp" msgid "Allow project access to share type." msgstr "Erlaube Projekt Zugriff auf Freigabetyp." msgid "At least one security service must be specified." msgstr "Wenigstens ein Sicherheitsdienst muss angegeben werden." msgid "At least one share type must be specified." msgstr "Es muss mindestens ein Freigabetyp angegeben werden." msgid "Availability Zone" msgstr "Verfügbarkeitszone" msgid "Availability zone" msgstr "Verfügbarkeitszone" msgctxt "Current status of replica" msgid "Available" msgstr "Verfügbar" msgctxt "Current status of share" msgid "Available" msgstr "Verfügbar" msgctxt "Current status of snapshot" msgid "Available" msgstr "Verfügbar" msgid "Available projects" msgstr "Verfügbare Projekte" msgid "Available security services" msgstr "Verfügbare Sicherheitsdienste" msgid "Cancel Migration" msgstr "Migration abbrechen" msgid "Cancel migration" msgstr "Migration abbrechen" msgid "Cancel migration of a Share" msgstr "Migration einer Freigabe abbrechen" msgid "Choose a snapshot" msgstr "Wählen Sie eine Schattenkopie" msgid "Complete Migration" msgstr "Migration abschliessen" msgid "Complete migration" msgstr "Migration abschließen" msgid "Complete migration of a Share" msgstr "Migration einer Freigabe abschliessen" msgid "Confirm Migration Cancelling of Share" msgstr "Bestätige Abbruch der Migration einer Freigabe" msgid "Confirm Migration Completion of Share" msgstr "Bestätige Abschluss der Migration der Freigabe" msgid "Confirm Obtaining migration progress of Share" msgstr "Bestätige Erhalt des Migrationsfortschritts einer Freigabe" msgid "Confirm Password" msgstr "Bestätige Passwort" msgid "Confirm Unmanage Share" msgstr "Bestätige aufheben der Verwaltung einer Freigabe" msgid "Create" msgstr "Erstellen" msgid "Create Replica" msgstr "Erstelle Replika" msgid "Create Security Service" msgstr "Erstelle Sicherheitsdienst" msgid "Create Share" msgstr "Freigabe erstellen" msgid "Create Share Group" msgstr "Freigabegruppe erstellen" msgid "Create Share Group Snapshot" msgstr "Freigabegruppe Schattenkopie erstellen" msgid "Create Share Group Type" msgstr "Freigabengruppe Typ erstellen" msgid "Create Share Network" msgstr "Erstelle Freigabenetzwerk" msgid "Create Share Snapshot" msgstr "Erstelle Fraigaben-Schattenkopie" msgid "Create Share Type" msgstr "Erstelle Freigabetyp" msgid "Create a Share" msgstr "Erstelle eine Freigabe" msgid "Created At" msgstr "Erstellt um" msgid "Created at" msgstr "Erstellt am" msgctxt "Current status of replica" msgid "Creating" msgstr "Erstellen" msgctxt "Current status of share" msgid "Creating" msgstr "Erstellen" msgctxt "Current status of share server" msgid "Creating" msgstr "Erstellen" msgctxt "Current status of snapshot" msgid "Creating" msgstr "Erstellen" #, python-format msgid "Creating replica for share \"%s\"." msgstr "Erstelle Replika für Freigabe \"%s\"." #, python-format msgid "Creating rule for \"%s\"" msgstr "Erstelle Regel für \"%s\"" #, python-format msgid "Creating share \"%s\"" msgstr "Erstelle Freigabe \"%s\"" #, python-format msgid "Creating share group \"%s\"" msgstr "Erstelle Freigabegruppe \"%s\"" #, python-format msgid "Creating share group snapshot \"%s\"." msgstr "Gruppenfreigabe Schattenkopie \"%s\" erstellen." #, python-format msgid "Creating share snapshot \"%s\"." msgstr "Erstelle geteilte Schattenkopie \"%s\"." #, python-format msgid "Creating snapshot rule for \"%s\"" msgstr "Erstelle Schattenkopie-Regel für \"%s\"" msgid "Current Size (GiB)" msgstr "Aktuelle Größe (GiB)" msgid "DNS IP" msgstr "DNS IP" msgid "Default Quotas" msgstr "Standardkontingente" msgid "Delete Replica" msgid_plural "Delete Replicas" msgstr[0] "Replik entfernen" msgstr[1] "Repliken entfernen" msgid "Delete Rule" msgid_plural "Delete Rules" msgstr[0] "Regel löschen" msgstr[1] "Regeln löschen" msgid "Delete Security Service" msgid_plural "Delete Security Services" msgstr[0] "Lösche Sicherheitsdienst" msgstr[1] "Lösche Sicherheitsdienste" msgid "Delete Share" msgid_plural "Delete Shares" msgstr[0] "Lösche Freigabe" msgstr[1] "Lösche Freigaben" msgid "Delete Share Group" msgid_plural "Delete Share Groups" msgstr[0] "Gruppenfreigabe löschen" msgstr[1] "Gruppenfreigaben löschen" msgid "Delete Share Group Snapshot" msgid_plural "Delete Share Group Snapshots" msgstr[0] "Freigabengruppe Schattenkopie löschen" msgstr[1] "Freigabengruppe Schattenkopien löschen" msgid "Delete Share Group Type" msgid_plural "Delete Share Group Types" msgstr[0] "Freigabengruppe Typ löschen" msgstr[1] "Freigabengruppen Typen löschen" msgid "Delete Share Network" msgid_plural "Delete Share Networks" msgstr[0] "Freigabenetzwerk löschen" msgstr[1] "Freigabenetzwerke löschen" msgid "Delete Share Server" msgid_plural "Delete Share Server" msgstr[0] "Freigabeserver entfernen" msgstr[1] "Freigabeserver entfernen" msgid "Delete Share Snapshot" msgid_plural "Delete Share Snapshots" msgstr[0] "Lösche Freigabeschattenkopie" msgstr[1] "Lösche Freigabeschattenkopien" msgid "Delete Share Snapshot Rule" msgid_plural "Delete Share Snapshot Rules" msgstr[0] "Lösche Regel Freigabeschattenkopie" msgstr[1] "Lösche Regeln Freigabeschattenkopie" msgid "Delete Share Type" msgid_plural "Delete Share Types" msgstr[0] "Freigabetyp löschen" msgstr[1] "Freigabetypen löschen" msgid "Delete Snapshot" msgid_plural "Delete Snapshots" msgstr[0] "Schattenkopie löschen" msgstr[1] "Schattenkopien löschen" msgid "Deleted Replica" msgid_plural "Deleted Replicas" msgstr[0] "Gelöschte Replik" msgstr[1] "Gelöschte Repliken" msgid "Deleted Rule" msgid_plural "Deleted Rules" msgstr[0] "Gelöschte Regel" msgstr[1] "Gelöschte Regeln" msgid "Deleted Security Service" msgid_plural "Deleted Security Services" msgstr[0] "Gelöschter Sicherheitsdienst" msgstr[1] "Gelöschte Sicherheitsdienste" msgid "Deleted Share" msgid_plural "Deleted Shares" msgstr[0] "Gelöschte Freigabe" msgstr[1] "Gelöschte Freigaben" msgid "Deleted Share Group" msgid_plural "Deleted Share Groups" msgstr[0] "Gelöschte Gruppenfreigabe" msgstr[1] "Gelöschte Gruppenfreigaben" msgid "Deleted Share Group Snapshot" msgid_plural "Deleted Share Group Snapshots" msgstr[0] "Gelöschte Freigabengruppe Schattenkopie" msgstr[1] "Gelöschte Freigabengruppe Schattenkopien" msgid "Deleted Share Group Type" msgid_plural "Deleted Share Group Types" msgstr[0] "Gelöschter Freigabengruppe Typ" msgstr[1] "Gelöschte Freigabengruppen Typen" msgid "Deleted Share Network" msgid_plural "Deleted Share Networks" msgstr[0] "Gelöschtes Freigabenetzwerk" msgstr[1] "Gelöschte Freigabennetzwerke" msgid "Deleted Share Server" msgid_plural "Deleted Share Server" msgstr[0] "Gelöschter Freigabeserver" msgstr[1] "Gelöschte Freigabeserver" msgid "Deleted Share Snapshot" msgid_plural "Deleted Share Snapshots" msgstr[0] "Freigabe Schattenkopie löschen" msgstr[1] "Freigabe Schattenkopien löschen" msgid "Deleted Share Snapshot Rule" msgid_plural "Deleted Share Snapshot Rules" msgstr[0] "Gelöschte Regeln Freigabeschattenkopie" msgstr[1] "Gelöschte Regeln Freigabeschattenkopie" msgid "Deleted Share Type" msgid_plural "Deleted Share Types" msgstr[0] "Gelöschter Freigabetyp" msgstr[1] "Gelöschte Freigabetypen" msgid "Deleted Snapshot" msgid_plural "Deleted Snapshots" msgstr[0] "Schattenkopie löschen" msgstr[1] "Schattenkopien löschen" msgctxt "Current status of replica" msgid "Deleting" msgstr "Löschen" msgctxt "Current status of share" msgid "Deleting" msgstr "Löschen" msgid "Description" msgstr "Beschreibung" msgid "Destination host and pool where share will be migrated to." msgstr "Zielhost und Pool, zu dem die Shares migriert werden." msgid "Domain" msgstr "Domäne" msgid "Driver handles share servers" msgstr "Treiberhändler des Freigabeservers" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "Treiberoptionen ('volume_id' für generischen Treiber, etc...)" #, python-format msgid "Duplicated keys '%s'." msgstr "Doppelte Schlüssel '%s'." msgid "Edit" msgstr "Bearbeiten" msgid "Edit Security Service" msgstr "Bearbeite Sicherheitsdienst" msgid "Edit Share" msgstr "Freigabe bearbeiten" msgid "Edit Share Metadata" msgstr "Freigabemetadaten bearbeiten" msgid "Edit Share Network" msgstr "Bearbeite Freigabenetzwerk" msgid "Edit Share Snapshot" msgstr "Freigabe Schattenkopie bearbeiten" msgid "" "Enforces migration of the share snapshots to the destination. If set to " "True, host-assisted migration will not be attempted." msgstr "" "Erzwingt die Migration der Share-Schattenkopien zum Ziel. Wenn aktiviert, " "wird die Host-gestützte Migration nicht verwendet." msgid "" "Enforces migration to be nondisruptive. If set to True, host-assisted " "migration will not be attempted." msgstr "" "Erzwingt unterbrechungsfreie Migration. Wenn aktiviert, wird die Host-" "gestützte Migration ausgelassen." msgid "" "Enforces migration to keep the share writable while contents are being " "moved. If set to True, host-assisted migration will not be attempted." msgstr "" "Erzwingt, dass bei der Migration die Shares schreibbar bleiben, während " "deren Inhalt bewegt wird. Wenn aktiviert, wird die Host-gestützte Migration " "ausgelassen." msgid "" "Enforces migration to preserve all file metadata when moving its contents. " "If set to True, host-assisted migration will not be attempted." msgstr "" "Erzwingt, dass bei der Migration alle Datei-Metadaten bewahrt werden, " "während der Inhalt verschoben wird. Wenn aktiviert, wird die Host-gestützte " "Migration ausgelassen." msgid "" "Enforces the use of the host-assisted migration approach, which bypasses " "driver optimizations." msgstr "" "Erzwingt die Verwendung der Host-gestützten Migration, welche " "Treiberoptimierungen umgeht." msgctxt "Current status of replica" msgid "Error" msgstr "Fehler" msgctxt "Current status of share" msgid "Error" msgstr "Fehler" msgctxt "Current status of share network" msgid "Error" msgstr "Fehler" msgctxt "Current status of share server" msgid "Error" msgstr "Fehler" msgctxt "Current status of snapshot" msgid "Error" msgstr "Fehler" msgid "Expected only pairs of key=value." msgstr "Erwartet nur Schlüssel=Wert Paare." msgid "Export location" msgstr "Exportiere Lokation" msgid "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgstr "" "Exportiere Lokation der Freigabe. Beispiel für NFS: 1.2.3.4:/path/to/share" msgid "Extend" msgstr "Erweitern" msgid "Extend Share" msgstr "Freigabe erweitern" #, python-format msgid "Extend share \"%s\"" msgstr "Erweitere Freigabe \"%s\"" msgctxt "Current status of share" msgid "Extending Error" msgstr "Erweiterungsfehler" msgid "Extra specs" msgstr "Extra Spezifikationen" msgid "Force Host Assisted Migration" msgstr "Erzwinge durch Host unterstützte Migration" msgid "From here you can update share network info. " msgstr "Hier können Sie Informationen zum Freigabenetzwerk aktualisieren." msgid "From here you can update the default quotas (max limits)." msgstr "Hier können Sie Standardkontingente (maximale Limits) aktualisieren." msgid "Get migration progress" msgstr "Migrationsfortschritt abrufen" msgid "" "Got improper value for field 'driver_options'. Expected only pairs of " "key=value." msgstr "" "Falscher Wert für das Feld 'driver_options' erhalten. Erwartet werden nur " "Schlüssel=Wert Paare." msgid "Group specs" msgstr "Gruppenspezifikationen" msgid "Host" msgstr "Host" msgid "Host of share" msgstr "Host der Freigabe" msgid "Host to migrate share" msgstr "Host zur Migration der Freigabe" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "" "Host, auf dem die Freigabe beheimatet ist, Beispiel: some.host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "IP Version" msgid "Id" msgstr "Id" #, python-format msgid "" "Improper value set to required extra spec " "'spec_driver_handles_share_servers'. Allowed values are %s. Case insensitive." msgstr "" "Falscher Wert zum Setzen der Extra Spezifikation " "'spec_driver_handles_share_servers'. Erlaubte Werte sind %s. Gross- und " "Kleinschreibung wird ignoriert." msgctxt "Current status of share server" msgid "In-use" msgstr "In Benutzung" msgctxt "Current status of snapshot" msgid "In-use" msgstr "In Benutzung" msgctxt "Current status of share network" msgid "Inactive" msgstr "Inaktiv" #, python-format msgid "Key '%s' has improper length." msgstr "Schlüssel '%s' hat die falsche Länge." #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "Der Schlüssel darf keine Leerzeichen enthalten. Prüfen Sie '%s'." #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "Schlüssel dürfen keine Leerzeichen enthalten. Fehler in '%s'." msgid "Make visible for all" msgstr "Für alle sichtbar machen" msgid "Manage" msgstr "Verwalten" msgctxt "Current status of share" msgid "Manage Error" msgstr "Fehler verwalten" msgid "Manage Replicas" msgstr "Verwalte Replikas" msgid "Manage Rules" msgstr "Regeln verwalten" msgid "Manage Share" msgstr "Verwalte Freigabe" msgid "Manage Share Group Type Access" msgstr "Freigabengruppe Typzugriff verwalten" msgid "Manage Share Snapshot Rules" msgstr "Verwalte Regeln Freigabeschattenkopie" msgid "Manage Share Type Access" msgstr "Verwalte Freigabetypzugriff" msgid "Metadata" msgstr "Metadaten" msgid "Migrate Share" msgstr "Migriere Freigabe" msgid "Migrate a Share" msgstr "Freigabe migrieren" msgctxt "Current status of share" msgid "Migrating" msgstr "Migrieren" msgctxt "Current status of share" msgid "Migrating to" msgstr "Migriere nach" #, python-format msgid "Migration of share %(name)s is at %(progress)s percent." msgstr "Migration der Freigabe %(name)s ist bei %(progress)s Prozent." msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "Projektinformationen und Mitglieder wurden geändert, aber Projektkontingente " "können nicht aktualisieren werden." msgid "Name" msgstr "Name" msgid "Network Type" msgstr "Netzwerktyp" msgid "Networks" msgstr "Netzwerke" msgid "Neutron Net" msgstr "Neutron Netz" msgid "Neutron Subnet" msgstr "Neutron Subnetz" msgid "New Size (GiB)" msgstr "Neue Größe (GiB)" msgid "New share network to be set in migrated share" msgstr "Neues Freigabenetzwerk, um es in der migrierten Freigabe zu setzen." msgid "New share type to be set in migrating share" msgstr "Neuer Freigabetyp, um ihn in der migrierten Freigabe zu setzen" msgid "New size must be greater than current size." msgstr "Neue Größe muss grösser als die derzeitige Größe sein." msgid "No projects found." msgstr "Keine Projekte gefunden." msgid "No projects selected." msgstr "Keine Projekte ausgewählt." msgid "No security services found." msgstr "Keine Sicherheitsdienste gefunden." msgid "No security services selected." msgstr "Keine Sicherheitsdienste ausgewählt." msgid "No source, empty share" msgstr "Keine Quelle, leere Freigabe" msgid "No source, empty share group" msgstr "Keine Quelle, leere Gruppenfreigabe" msgid "Nondisruptive" msgstr "Ohne Unterbrechung" msgid "Nova Net" msgstr "Nova Netz" msgid "Obtain Progress" msgstr "Erhalte Fortschritt" msgid "Obtain migration progress of a Share" msgstr "Erhalte Fortschritt der Migration einer Freigabe" msgid "Overview" msgstr "Übersicht" msgid "Password" msgstr "Passwort" msgid "Passwords do not match." msgstr "Passwörter stimmen nicht überein." msgid "Preserve Metadata" msgstr "Metadaten behalten" msgid "Preserve Snapshots" msgstr "Schattenkopien aufbewahren" msgid "Project" msgstr "Projekt" msgid "Projects with access to share group type" msgstr "Projekte mit Zugriff auf Gruppenfreigabetypen" msgid "Projects with access to share type" msgstr "Projekte mit Zugriff auf Freigabetypen" msgid "Protocol" msgstr "Protokoll" msgid "Public" msgstr "Öffentlich" msgid "Quota" msgstr "Kontingente" #, python-format msgid "Replica Details: %(replica_display_name)s" msgstr "Replika Details: %(replica_display_name)s" msgid "Replica State" msgstr "Replika Zustand" msgid "Replicas" msgstr "Replikas" msgid "Reset Replica State" msgstr "Replika Zustand zurücksetzen" msgid "Reset Replica Status" msgstr "Replika Status zurücksetzen" msgid "Reset Share Group Snapshot Status" msgstr "Rücksetzung des Status der Schattenkopie der Gruppenfreigabe" msgid "Reset Share Group Status" msgstr "Gruppenfreigaben Status zurücksetzen" msgid "Reset Status" msgstr "Status zurücksetzen" msgid "Reset replica state" msgstr "Replika Zustand zurücksetzen" msgid "Reset replica status" msgstr "Replika-Status zurücksetzen" msgid "Reset state" msgstr "Zustand zurücksetzen" msgid "Reset status" msgstr "Status zurücksetzen" #, python-format msgid "Reseting replica ('%(id)s') state from '%(from)s' to '%(to)s'." msgstr "" "Setze Status von Replika ('%(id)s') von '%(from)s' auf '%(to)s' zurück." #, python-format msgid "Reseting replica ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "Zurücksetzen des Status von Replika ('%(id)s') von '%(from)s' zu '%(to)s'." #, python-format msgid "Reseting share group ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "Gruppenfreigabe ('%(id)s') Status zurücksetzen von '%(from)s' zu '%(to)s'." #, python-format msgid "" "Reseting share group snapshot ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "Rücksetzung der Schattenkopie der Freigabegruppe ('%(id)s') Status von " "'%(from)s' zu '%(to)s'." msgid "Resync" msgstr "Resynchronisieren" msgid "Resync Replica" msgstr "Resynchronisiere Replika" msgid "Resync replica" msgstr "Resynchronisiere Replika" #, python-format msgid "Resync'ing replica '%s'" msgstr "Resynchronisiere Replika '%s'" msgid "Revert Share" msgstr "Freigabe zurückstellen" msgid "Revert Share to a Snapshot" msgstr "Share auf Schattenkopie zurücksetzen" msgid "Revert share to a snapshot" msgstr "Freigabe auf Schattenkopie zurückstellen" msgctxt "Current status of share" msgid "Reverting Error" msgstr "Fehler beim Zurückstellen" msgid "Rules" msgstr "Regeln" msgid "Save Changes" msgstr "Änderungen speichern" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "Sicherheitsdienst-Details: %(service_display_name)s" msgid "Security Service Overview" msgstr "Sicherheitsdienst Überblick" msgid "Security Services" msgstr "Sicherheitsdienste" msgid "Security services within share network" msgstr "Sicherheitsdienste in Freigabenetzwerk" msgid "Segmentation Id" msgstr "Segmentierungs-ID" msgid "Selected projects" msgstr "Ausgewählte Projekte" msgid "Selected security services" msgstr "Gewählte SIcherheitsdienste" msgid "Server" msgstr "Server" msgid "Set Replica as Active" msgstr "Setze Replika auf aktiv" msgid "Set as Active" msgstr "Setze auf aktiv" msgid "Set maximum quotas for the project." msgstr "Setze maximale Kontingente für dieses Projekt." #, python-format msgid "Setting replica \"%s\" as active..." msgstr "Setze Replika \"%s\" auf aktiv..." #, python-format msgid "Share \"%(s)s\" has been reverted to \"%(ss)s\" snapshot successfully" msgstr "Freigabe \"%(s)s\" wurde auf Schattenkkopie \"%(ss)s\" zurückgestellt" #, python-format msgid "Share Details: %(share_display_name)s" msgstr "Details Freigabe: %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "Freigabedetails: %(share_name)s" msgid "Share Group" msgstr "Freigabegruppe" #, python-format msgid "Share Group Details: %s" msgstr "Gruppenfreigaben Details: %s" msgid "Share Group Name" msgstr "Freigabegruppe Name" msgid "Share Group Overview" msgstr "Gruppenfreigabe Übersicht" msgid "Share Group Snapshot" msgstr "Freigabegruppe Schattenkopie" #, python-format msgid "Share Group Snapshot Details: %(sgs_display_name)s" msgstr "Details der Schattenkopie der Gruppenfreigabe: %(sgs_display_name)s" msgid "Share Group Snapshot Overview" msgstr "Übersicht der Schattenkopien der Freigabegruppen" msgid "Share Group Snapshots" msgstr "Freigabengruppe Schattenkopien" msgid "Share Group Type" msgstr "Gruppenfreigabetyp" msgid "Share Group Types" msgstr "Freigabengruppe Typen" msgid "Share Groups" msgstr "Gruppenfreigaben" msgid "Share ID" msgstr "Freigabe-ID" #, python-format msgid "Share Instance Details: %s" msgstr "Details Freigabeinstanz: %s" msgid "Share Instance Overview" msgstr "Freigegebene Instanzen Übersicht" msgid "Share Instances" msgstr "Freigabeinstanzen" msgid "Share Name" msgstr "Freigabename" msgid "Share Network" msgstr "Freigabenetzwerk" #, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "Details Freigabenetzwerk: %(network_display_name)s" msgid "Share Network Info" msgstr "Freigabenetzwerk Informationen" msgid "Share Network Overview" msgstr "Freigabenetzwerke Übersicht" msgid "Share Networks" msgstr "Freigabenetzwerke" msgid "Share Overview" msgstr "Freigaben Übersicht" msgid "Share Protocol" msgstr "Freigabenprotokoll" #, python-format msgid "Share Replicas: %(share_display_name)s" msgstr "Freigaben-Replikas: %(share_display_name)s" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "Freigaberegeln: %(share_display_name)s" msgid "Share Server" msgstr "Freigabeserver" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "Details Freigabeserver: %(server_name)s" msgid "Share Server Id" msgstr "Freigabeserver-ID" msgid "Share Server Overview" msgstr "Freigabeserver Übersicht" msgid "Share Servers" msgstr "Freigabeserver" msgid "Share Snapshot Name" msgstr "Freigegebene Schattenkopie Name" msgid "Share Snapshot Overview" msgstr "Schattenkopieübersicht teilen" msgid "Share Snapshot Rules" msgstr "Schattenkopie-Regeln löschen" msgid "Share Snapshots" msgstr "Freigabe Schattenkopien" msgid "Share Snapshots Storage" msgstr "Freigabe Schattenkopienspeicher" msgid "Share Source" msgstr "Freigabequelle" msgid "Share Storage" msgstr "Freigabespeicher" msgid "Share Type" msgstr "Freigabetyp" msgid "Share Types" msgstr "Freigabetypen" msgid "Share Types (multiple available)" msgstr "Freigabetypen (mehrere verfügbar)" msgid "Share Types (one available)" msgstr "Freigabetypen (eine verfügbar)" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "Die Freigabe kann nicht auf %(req)iGiB erweitert werden, da nur %(avail)iGiB " "in Ihrem Kontingent verfügbar sind." msgid "Share gigabytes" msgstr "Freigabe Gigabyte" msgid "Share name to be assigned" msgstr "Zuzuweisender Freigabename" #, python-format msgid "Share replica %s has been deleted." msgstr "Freigabe Replika %s wurde gelöscht." #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "" "Freigabegrösse muss gleich oder grösser als die Grösse der Schattenkopie " "sein (%sGiB)" msgid "Share snapshot gigabytes" msgstr " Freigabeschattenkopie gigabytes" msgid "Share snapshots" msgstr " Freigabeschattenkopien" msgid "Share types" msgstr "Freigabetypen" msgid "Shares" msgstr "Freigaben" msgid "Shares Networks" msgstr "Freigabenetzwerke" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "Grösse" msgid "Size (GiB)" msgstr "Grösse (GiB)" msgid "Snapshot" msgstr "Schattenkopie" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "Schattenkopiedetails: %(snapshot_display_name)s" #, python-format msgid "Snapshot Rules: %(snapshot_display_name)s" msgstr "Schattenkopie-Regeln: %(snapshot_display_name)s" msgid "Source" msgstr "Quelle" msgid "Source Share Group Snapshot" msgstr "Quelle Schattenkopie Gruppenfreigabe" msgid "Source Type" msgstr "Quellentyp" msgid "" "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." msgstr "" "Geben Sie das neue Share-Netzwerk für das Share an. Geben Sie diesen " "Parameter nicht an, wenn das Migrations-Share im aktuellen Share-Netzwerk " "verbleiben soll." msgid "" "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." msgstr "" "Geben Sie den neuen Share-Typ für das Share an. Geben Sie diesen Parameter " "nicht an, wenn das Migrations-Share seinen aktuellen Share-Typ behalten soll." msgid "Start migration" msgstr "Migration starten" msgid "Status" msgstr "Status" #, python-format msgid "Successfully created security service: %s" msgstr "Sicherheitsdienst erfolgreich erstellt: %s" #, python-format msgid "Successfully created share group type: %s" msgstr "Gruppenfreigabe Typ erfolgreich erstellt: %s" #, python-format msgid "Successfully created share network: %s" msgstr "Freigabenetzwerk erfolgreich erstellt: %s" #, python-format msgid "Successfully created share type: %s" msgstr "Freigabetyp erfolgreich erstellt: %s" #, python-format msgid "Successfully sent the request to cancel migration of share: %s." msgstr "" "Anfrage zum Abbruch der Migration der Freigabe erfolgreich gesendet: %s" #, python-format msgid "Successfully sent the request to complete migration of share: %s." msgstr "" "Anfrage zum Abschließen der Migration der Freigabe erfolgreich gesendet: %s" #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "Anfrage zur Verwaltung der Freigabe erfolgreich gesendet: %s" #, python-format msgid "Successfully sent the request to migrate share: %s." msgstr "Anfrage zur Migration der Freigabe erfolgreich gesendet: %s" #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "" "Anfrage zum Aufheben der Verwaltung der Freigabe erfolgreich gesendet: %s" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "Extra-Spezifikationen des Freigabetypes '%s' erfolgreich aktualisiert." #, python-format msgid "Successfully updated group specs for share group type '%s'." msgstr "Spezifikationen für Gruppenfreigabe Typ '%s' erfolgreich aktualisiert." #, python-format msgid "Successfully updated security service \"%s\"" msgstr "Erfolgreiche Aktualisierung des Sicherheitsdienstes \"%s\"" #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "" "Die Größe der Freigabe kann nicht kleiner als die der Schattenkopie sein " "(%sGiB)" msgid "Type" msgstr "Typ" msgid "Unable to add rule." msgstr "Konnte Regel nicht hinzufügen." msgid "Unable to add snapshot rule." msgstr "Schattenkopie-Regel kann nicht hinzugefügt werden." #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "Kann Migration der Freigabe %s momentan nicht abbrechen." #, python-format msgid "Unable to complete migration of share %s." msgstr "Konnte Migration der Freigabe %s nicht fertigstellen." msgid "Unable to create security service." msgstr "Konnte Sicherheitsdienst nicht erstellen." msgid "Unable to create share group snapshot." msgstr "Konnte Schattenkopie von Gruppenfreigabe nicht erstellen." msgid "Unable to create share group type." msgstr "Gruppenfreigabe Typ kann nicht erstellt werden." msgid "Unable to create share group." msgstr "Konnte Gruppenfreigabe nicht erstellen." msgid "Unable to create share network." msgstr "Konnte Freigabenetzwerk nicht erstellen." msgid "Unable to create share replica." msgstr "Konnte Freigabe-Replika nicht erstellen." msgid "Unable to create share snapshot." msgstr "Konnte Freigaben-Schattenkopie nicht erstellen." msgid "Unable to create share type." msgstr "Konnte Freigabetyp nicht erstellen." msgid "Unable to create share." msgstr "Konnte Freigabe nicht erstellen." #, python-format msgid "Unable to create share. %s" msgstr "Freigabe kann nicht erstellt werden. %s" #, python-format msgid "Unable to delete replica \"%s\"." msgstr "Konnte Replika \"%s\" nicht löschen." #, python-format msgid "Unable to delete rule \"%s\"." msgstr "Konnte Regel \"%s\" nicht löschen." #, python-format msgid "Unable to delete share \"%s\". " msgstr "Konnte Freigabe \"%s\" nicht löschen." #, python-format msgid "" "Unable to delete share group snapshot \"%s\". One or more share groups " "depend on it." msgstr "" "Konnte die Schattenkopie \"%s\" der Freigabegruppe nicht löschen. Eine oder " "mehre Freigabegruppen hängen davon ab." #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "" "Konnte Schattenkopie \"%s\" nicht löschen. Eine oder mehrere Freigaben sind " "davon abhängig." #, python-format msgid "Unable to delete snapshot rule \"%s\"." msgstr "Schattenkopie-Regel \"%s\" kann nicht gelöscht werden." msgid "Unable to extend share." msgstr "Konnte Freigabe nicht erweitern." msgid "Unable to get information about share group type access." msgstr "" "Informationen über den Zugriff auf Gruppenfreigaben können nicht abgerufen " "werden." msgid "Unable to get information about share type access." msgstr "Konnte Informationen über Freigabetypenzugriff nicht abrufen." msgid "Unable to get list of projects." msgstr "Konnte Projektliste nicht abrufen." msgid "Unable to get the security services hosts" msgstr "Konnte die Sicherheitsdienst-Hosts nicht abrufen" #, python-format msgid "Unable to get the specified share group '%s' for snapshot creation." msgstr "" "Konnte die Spezifikationen zur Gruppenfreigabe '%s' für " "Schattenkopieerstellung nicht empfangen." msgid "Unable to load the specified share group snapshot." msgstr "Konnte spezifizierte Schattenkopie der Gruppenfreigabe nicht laden." msgid "Unable to load the specified snapshot." msgstr "Konnte angegebene Schattenkopie nicht laden." msgid "Unable to manage share" msgstr "Konnte Freigabe nicht verwalten" #, python-format msgid "Unable to migrate share %s." msgstr "Konnte Freigabe %s nicht migrieren." #, python-format msgid "Unable to obtain progress of migration of share %s at this moment." msgstr "" "Kann den Fortschritt der Migration der Freigaben %s momentan nicht abrufen." #, python-format msgid "Unable to reset state of replica '%s'." msgstr "Konnte Status des Replika %s nicht zurücksetzen." #, python-format msgid "Unable to reset status of replica '%s'." msgstr "Konnte Status des Replika %s nicht zurücksetzen." #, python-format msgid "Unable to reset status of share group '%s'." msgstr "Status der Gruppenfreigabe '%s' kann nicht zurückgesetzt werden." #, python-format msgid "Unable to reset status of share group snapshot '%s'." msgstr "Konnte die Schattenkopie '%s' der Freigabegruppe nicht zurücksetzen." #, python-format msgid "Unable to resync replica '%s'." msgstr "Resynchronisieren von Replika '%s' nicht möglich ." msgid "Unable to retrieve list of projects." msgstr "Konnte Projektliste nicht abrufen" msgid "Unable to retrieve quotas." msgstr "Konnte Kontingente nicht abrufen." #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "Konnte Replika %sdetails nicht abrufen." #, python-format msgid "Unable to retrieve replica '%s'." msgstr "Konnte Replika '%s' nicht abrufen." #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "Konnte Details zu Sicherheitsdienst '%s' nicht abrufen." msgid "Unable to retrieve security services" msgstr "Konnte Sicherheitsdienste nicht abrufen" msgid "Unable to retrieve security_service." msgstr "Konnte Sicherheitsdienst nicht abrufen." msgid "Unable to retrieve share details." msgstr "Konnte Freigabendetails nicht abrufen." #, python-format msgid "Unable to retrieve share group '%s'." msgstr "Gruppenfreigabe '%s' kann nicht abgerufen werden." msgid "Unable to retrieve share group details." msgstr "Gruppenfreigaben Details können nicht abgerufen werden." #, python-format msgid "Unable to retrieve share group snapshot '%s'." msgstr "Freigabengruppe Schattenkopie '%s' kann nicht abgerufen werden." msgid "Unable to retrieve share group snapshot details." msgstr "" "Konnte die Details der Schattenkopie der Gruppenfreigabe nicht abrufen." msgid "Unable to retrieve share group snapshot list." msgstr "Konnte die Liste der Schattenkopien der Freigabegruppen nicht abrufen." msgid "Unable to retrieve share group snapshot." msgstr "Konnte Schattenkopie der Gruppenfreigabe nicht empfangen." msgid "Unable to retrieve share group snapshots." msgstr "Konnte Schattenkopien der Gruppenfreigabe nicht empfangen." msgid "Unable to retrieve share group types." msgstr "Freigabengruppe Typen können nicht abgerufen werden." msgid "Unable to retrieve share group." msgstr "Konnte Gruppenfreigabe nicht abrufen" msgid "Unable to retrieve share groups." msgstr "Gruppenfreigaben können nicht abgerufen werden." msgid "Unable to retrieve share instance details." msgstr "Konnte Freigabeinstanzdetails nicht abrufen." msgid "Unable to retrieve share instances." msgstr "Konnte Freigabeinstanzen nicht abrufen" msgid "Unable to retrieve share limit information." msgstr "Konnte Informationen zu Freigabenlimits nicht abrufen." msgid "Unable to retrieve share list." msgstr "Konnte Liste der Freigaben nicht abrufen" msgid "Unable to retrieve share network details." msgstr "Konnte Details zum Freigabenetzwerk nicht abrufen." msgid "Unable to retrieve share network." msgstr "Konnte Freigabenetzwerk nicht abrufen." msgid "Unable to retrieve share networks" msgstr "Konnte Freigabenetzwerke nicht abrufen" msgid "Unable to retrieve share replicas." msgstr "Konnte Freigaben-Replikas nicht abrufen." msgid "Unable to retrieve share rules." msgstr "Konnte Freigaberegeln nicht abrufen." msgid "Unable to retrieve share server details." msgstr "Konnte Details zum Freigabeserver nicht abrufen." msgid "Unable to retrieve share servers" msgstr "Konnte Freigabeserver nicht abrufen" msgid "Unable to retrieve share snapshot list." msgstr "Konnte Liste der geteilten Schattenkopien nicht abrufen." msgid "Unable to retrieve share snapshot rules." msgstr "Konnte Regeln für Freigabeschattenkopie nicht abrufen." msgid "Unable to retrieve share snapshot." msgstr "Konnte Freigabeschattenkopie nicht abrufen." msgid "Unable to retrieve share snapshots list." msgstr "Konnte Freigaben-Schattenkopieliste nicht abrufen." msgid "Unable to retrieve share snapshots." msgstr "Konnte freigegebene Schattenkopien nicht abrufen." msgid "Unable to retrieve share types." msgstr "Freigabetypen können nicht abgerufen werden." msgid "Unable to retrieve share." msgstr "Konnte Freigabe nicht abrufen." #, python-format msgid "Unable to retrieve share. %s" msgstr "Konnte Freigabe nicht abrufen. %s" msgid "Unable to retrieve share_gruop_type." msgstr "Konnte share_gruop_type nicht abrufen." msgid "Unable to retrieve share_type." msgstr "Konnte den Freigabetyp nicht abrufen." msgid "Unable to retrieve snapshot details." msgstr "Konnte Schattenkopiedetails nicht abrufen." msgid "Unable to retrieve snapshot." msgstr "Konnte Schattenkopie nicht abrufen." msgid "Unable to retrieve volume details." msgstr "Konnte Datenträgerdetails nicht abrufen." msgid "Unable to revert share to the snapshot." msgstr "Freigabe kann nicht auf Schattenkopie zurückgestellt werden." msgid "Unable to set project quotas." msgstr "Konnte Projektkontingente nicht setzen." #, python-format msgid "Unable to set replica '%s' as active." msgstr "Konnte Replika \"%s\" nicht auf aktiv setzen." msgid "Unable to unmanage share." msgstr "Konnte Verwaltung der Freigabe nicht aufheben" #, python-format msgid "Unable to update access for share group type \"%s\"." msgstr "" "Zugriff zum Gruppenfreigabetyp \"%s\" konnte nicht aktualisiert werden." #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "Konnte Zugriff für Freigabetyp \"%s\" nicht aktualisieren." msgid "Unable to update default quotas." msgstr "Konnte Standardkontingente nicht aktualisieren." msgid "Unable to update extra_specs for share type." msgstr "Konnte Extra-Spezifikationen für Freigabetyp nicht aktualisieren." msgid "Unable to update group_specs for share group type." msgstr "" "Spezifikationen für Gruppenfreigabe Typ können nicht aktualisiert werden." msgid "Unable to update security service." msgstr "Konnte Sicherheitsdienst nicht aktualisieren." msgid "Unable to update share group snapshot." msgstr "Freigabegruppe Schattenkopie kann nicht aktualisiert werden." msgid "Unable to update share group type." msgstr "Gruppenfreigabetyp konnte nicht aktualisiert werden." msgid "Unable to update share group." msgstr "Konnte Gruppenfreigabe nicht aktualisieren." msgid "Unable to update share metadata." msgstr "Konnte Freigabe Metadaten nicht aktualisieren." #, python-format msgid "Unable to update share network \"%s\"." msgstr "Konnte Freigabenetzwerk \"%s\" nicht aktualisieren." msgid "Unable to update share network." msgstr "Konnte Freigabenetzwerk nicht aktualisieren." msgid "Unable to update share snapshot." msgstr "Konnte Schattenkopie Gruppenfreigabe nicht aktualisieren." msgid "Unable to update share type." msgstr "Konnte Freigabetyp nicht aktualisieren." msgid "Unable to update share." msgstr "Konnte Freigabe nicht aktualisieren." msgid "Unknown" msgstr "Unbekannt" msgid "Unmanage" msgstr "Verwaltung aufheben" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "Fehlerverwaltung aufheben" msgid "Unmanage Share" msgstr "Verwaltung der Freigabe aufheben" msgid "Update" msgstr "Aktualisieren" msgid "Update Share Group" msgstr "Freigabegruppe aktualisieren" msgid "Update Share Group Snapshot" msgstr "Freigabegruppe Schattenkopie aktualisieren" msgid "Update Share Group Type" msgstr "Freigabengruppe Typ aktualisieren" msgid "Update Share Network" msgstr "Aktualisiere Freigabenetzwerk" msgid "Update Share Snapshot" msgstr "Aktualisiere Freigabeschattenkopie" msgid "Update Share Type" msgstr "Aktualisiere Freigabetyp" msgid "Update Share group Type" msgstr "Freigabengruppe Typ aktualisieren" msgid "Updated At" msgstr "Aktualisiert um" #, python-format msgid "Updated access for share group type \"%s\"." msgstr "Zugriff zum Gruppenfreigabetyp aktualisiert \"%s\"." #, python-format msgid "Updated access for share type \"%s\"." msgstr "Zugriff für Freigabetyp \"%s\" aktualisiert." #, python-format msgid "Updated share network \"%s\"." msgstr "Aktualisiere Freigabenetzwerk \"%s\"." #, python-format msgid "Updating share \"%s\"" msgstr "Aktualisiere Freigabe \"%s\"" #, python-format msgid "Updating share group \"%s\"" msgstr "Aktualisiere Gruppenfreigabe \"%s\"" #, python-format msgid "Updating share group snapshot \"%s\"" msgstr "Gruppenfreigabe Schattenkopie \"%s\" wird aktualisiert." #, python-format msgid "Updating share metadata \"%s\"" msgstr "Aktualisiere Freigabe Metadaten \"%s\"" #, python-format msgid "Updating share network \"%s\"" msgstr "Aktualisiere Freigabenetzwerk \"%s\"" #, python-format msgid "Updating share snapshot \"%s\"" msgstr "Aktualisiere Schattenkopie Gruppenfreigabe \"%s\"" msgid "Use share group snapshot as a source" msgstr "Benutze Gruppenfreigabe Schattenkopie als Quelle" msgid "Use snapshot as a source" msgstr "Benutze Schattenkopie als Quelle" msgid "User" msgstr "Benutzer" msgid "Visibility" msgstr "Sichtbarkeit" msgid "Writable" msgstr "Beschreibbar" msgid "key=value pairs per line can be set" msgstr "Schlüssel=Wert Paare pro Zeile können gesetzt werden" manila-ui-2.13.0/manila_ui/locale/en_GB/000077500000000000000000000000001323215354300176215ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/en_GB/LC_MESSAGES/000077500000000000000000000000001323215354300214065ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/en_GB/LC_MESSAGES/django.po000066400000000000000000001114211323215354300232100ustar00rootroot00000000000000# Andi Chandler , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.10.2.dev25\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-10-13 14:46+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-10-15 07:37+0000\n" "Last-Translator: Andi Chandler \n" "Language-Team: English (United Kingdom)\n" "Language: en-GB\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #, python-format msgid "%sGiB" msgstr "%sGiB" msgid "(Quota exceeded)" msgstr "(Quota exceeded)" msgid "Access Key" msgstr "Access Key" msgid "Access Level" msgstr "Access Level" msgid "Access To" msgstr "Access To" msgid "Access Type" msgstr "Access Type" msgid "Access to" msgstr "Access to" msgctxt "Current status of share network" msgid "Active" msgstr "Active" msgctxt "Current status of share server" msgid "Active" msgstr "Active" msgid "Add" msgstr "Add" msgid "Add Rule" msgstr "Add Rule" msgid "Add Security Service" msgstr "Add Security Service" msgid "Add Share Snapshot Rule" msgstr "Add Share Snapshot Rule" msgid "Add rule" msgstr "Add rule" msgid "Add security services to share network." msgstr "Add security services to share network." msgid "All keys and values must be in range from 1 to 255." msgstr "All keys and values must be in range from 1 to 255." msgid "Allow project access to share group type." msgstr "Allow project access to share group type." msgid "Allow project access to share type." msgstr "Allow project access to share type." msgid "At least one security service must be specified." msgstr "At least one security service must be specified." msgid "At least one share type must be specified." msgstr "At least one share type must be specified." msgid "Availability Zone" msgstr "Availability Zone" msgid "Availability zone" msgstr "Availability zone" msgctxt "Current status of replica" msgid "Available" msgstr "Available" msgctxt "Current status of share" msgid "Available" msgstr "Available" msgctxt "Current status of snapshot" msgid "Available" msgstr "Available" msgid "Available projects" msgstr "Available projects" msgid "Available security services" msgstr "Available security services" msgid "Cancel Migration" msgstr "Cancel Migration" msgid "Cancel migration" msgstr "Cancel migration" msgid "Cancel migration of a Share" msgstr "Cancel migration of a Share" msgid "Choose a snapshot" msgstr "Choose a snapshot" msgid "Complete Migration" msgstr "Complete Migration" msgid "Complete migration" msgstr "Complete migration" msgid "Complete migration of a Share" msgstr "Complete migration of a Share" msgid "Confirm Migration Cancelling of Share" msgstr "Confirm Migration Cancelling of Share" msgid "Confirm Migration Completion of Share" msgstr "Confirm Migration Completion of Share" msgid "Confirm Obtaining migration progress of Share" msgstr "Confirm Obtaining migration progress of Share" msgid "Confirm Password" msgstr "Confirm Password" msgid "Confirm Unmanage Share" msgstr "Confirm Unmanage Share" msgid "Create" msgstr "Create" msgid "Create Replica" msgstr "Create Replica" msgid "Create Security Service" msgstr "Create Security Service" msgid "Create Share" msgstr "Create Share" msgid "Create Share Group" msgstr "Create Share Group" msgid "Create Share Group Snapshot" msgstr "Create Share Group Snapshot" msgid "Create Share Group Type" msgstr "Create Share Group Type" msgid "Create Share Network" msgstr "Create Share Network" msgid "Create Share Snapshot" msgstr "Create Share Snapshot" msgid "Create Share Type" msgstr "Create Share Type" msgid "Create a Share" msgstr "Create a Share" msgid "Created At" msgstr "Created At" msgid "Created at" msgstr "Created at" msgctxt "Current status of replica" msgid "Creating" msgstr "Creating" msgctxt "Current status of share" msgid "Creating" msgstr "Creating" msgctxt "Current status of share server" msgid "Creating" msgstr "Creating" msgctxt "Current status of snapshot" msgid "Creating" msgstr "Creating" #, python-format msgid "Creating replica for share \"%s\"." msgstr "Creating replica for share \"%s\"." #, python-format msgid "Creating rule for \"%s\"" msgstr "Creating rule for \"%s\"" #, python-format msgid "Creating share \"%s\"" msgstr "Creating share \"%s\"" #, python-format msgid "Creating share group \"%s\"" msgstr "Creating share group \"%s\"" #, python-format msgid "Creating share group snapshot \"%s\"." msgstr "Creating share group snapshot \"%s\"." #, python-format msgid "Creating share snapshot \"%s\"." msgstr "Creating share snapshot \"%s\"." #, python-format msgid "Creating snapshot rule for \"%s\"" msgstr "Creating snapshot rule for \"%s\"" msgid "Current Size (GiB)" msgstr "Current Size (GiB)" msgid "DNS IP" msgstr "DNS IP" msgid "Default Quotas" msgstr "Default Quotas" msgid "Delete Replica" msgid_plural "Delete Replicas" msgstr[0] "Delete Replica" msgstr[1] "Delete Replicas" msgid "Delete Rule" msgid_plural "Delete Rules" msgstr[0] "Delete Rule" msgstr[1] "Delete Rules" msgid "Delete Security Service" msgid_plural "Delete Security Services" msgstr[0] "Delete Security Service" msgstr[1] "Delete Security Services" msgid "Delete Share" msgid_plural "Delete Shares" msgstr[0] "Delete Share" msgstr[1] "Delete Shares" msgid "Delete Share Group" msgid_plural "Delete Share Groups" msgstr[0] "Delete Share Group" msgstr[1] "Delete Share Groups" msgid "Delete Share Group Snapshot" msgid_plural "Delete Share Group Snapshots" msgstr[0] "Delete Share Group Snapshot" msgstr[1] "Delete Share Group Snapshots" msgid "Delete Share Group Type" msgid_plural "Delete Share Group Types" msgstr[0] "Delete Share Group Type" msgstr[1] "Delete Share Group Types" msgid "Delete Share Network" msgid_plural "Delete Share Networks" msgstr[0] "Delete Share Network" msgstr[1] "Delete Share Networks" msgid "Delete Share Server" msgid_plural "Delete Share Server" msgstr[0] "Delete Share Server" msgstr[1] "Delete Share Server" msgid "Delete Share Snapshot" msgid_plural "Delete Share Snapshots" msgstr[0] "Delete Share Snapshot" msgstr[1] "Delete Share Snapshots" msgid "Delete Share Snapshot Rule" msgid_plural "Delete Share Snapshot Rules" msgstr[0] "Delete Share Snapshot Rule" msgstr[1] "Delete Share Snapshot Rules" msgid "Delete Share Type" msgid_plural "Delete Share Types" msgstr[0] "Delete Share Type" msgstr[1] "Delete Share Types" msgid "Delete Snapshot" msgid_plural "Delete Snapshots" msgstr[0] "Delete Snapshot" msgstr[1] "Delete Snapshots" msgid "Deleted Replica" msgid_plural "Deleted Replicas" msgstr[0] "Deleted Replica" msgstr[1] "Deleted Replicas" msgid "Deleted Rule" msgid_plural "Deleted Rules" msgstr[0] "Deleted Rule" msgstr[1] "Deleted Rules" msgid "Deleted Security Service" msgid_plural "Deleted Security Services" msgstr[0] "Deleted Security Service" msgstr[1] "Deleted Security Services" msgid "Deleted Share" msgid_plural "Deleted Shares" msgstr[0] "Deleted Share" msgstr[1] "Deleted Shares" msgid "Deleted Share Group" msgid_plural "Deleted Share Groups" msgstr[0] "Deleted Share Group" msgstr[1] "Deleted Share Groups" msgid "Deleted Share Group Snapshot" msgid_plural "Deleted Share Group Snapshots" msgstr[0] "Deleted Share Group Snapshot" msgstr[1] "Deleted Share Group Snapshots" msgid "Deleted Share Group Type" msgid_plural "Deleted Share Group Types" msgstr[0] "Deleted Share Group Type" msgstr[1] "Deleted Share Group Types" msgid "Deleted Share Network" msgid_plural "Deleted Share Networks" msgstr[0] "Deleted Share Network" msgstr[1] "Deleted Share Networks" msgid "Deleted Share Server" msgid_plural "Deleted Share Server" msgstr[0] "Deleted Share Server" msgstr[1] "Deleted Share Server" msgid "Deleted Share Snapshot" msgid_plural "Deleted Share Snapshots" msgstr[0] "Deleted Share Snapshot" msgstr[1] "Deleted Share Snapshots" msgid "Deleted Share Snapshot Rule" msgid_plural "Deleted Share Snapshot Rules" msgstr[0] "Deleted Share Snapshot Rule" msgstr[1] "Deleted Share Snapshot Rules" msgid "Deleted Share Type" msgid_plural "Deleted Share Types" msgstr[0] "Deleted Share Type" msgstr[1] "Deleted Share Types" msgid "Deleted Snapshot" msgid_plural "Deleted Snapshots" msgstr[0] "Deleted Snapshot" msgstr[1] "Deleted Snapshots" msgctxt "Current status of replica" msgid "Deleting" msgstr "Deleting" msgctxt "Current status of share" msgid "Deleting" msgstr "Deleting" msgid "Description" msgstr "Description" msgid "Destination host and pool where share will be migrated to." msgstr "Destination host and pool where share will be migrated to." msgid "Domain" msgstr "Domain" msgid "Driver handles share servers" msgstr "Driver handles share servers" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "Driver options ('volume_id' for Generic driver, etc...)" #, python-format msgid "Duplicated keys '%s'." msgstr "Duplicated keys '%s'." msgid "Edit" msgstr "Edit" msgid "Edit Security Service" msgstr "Edit Security Service" msgid "Edit Share" msgstr "Edit Share" msgid "Edit Share Metadata" msgstr "Edit Share Metadata" msgid "Edit Share Network" msgstr "Edit Share Network" msgid "Edit Share Snapshot" msgstr "Edit Share Snapshot" msgid "" "Enforces migration of the share snapshots to the destination. If set to " "True, host-assisted migration will not be attempted." msgstr "" "Enforces migration of the share snapshots to the destination. If set to " "True, host-assisted migration will not be attempted." msgid "" "Enforces migration to be nondisruptive. If set to True, host-assisted " "migration will not be attempted." msgstr "" "Enforces migration to be non-disruptive. If set to True, host-assisted " "migration will not be attempted." msgid "" "Enforces migration to keep the share writable while contents are being " "moved. If set to True, host-assisted migration will not be attempted." msgstr "" "Enforces migration to keep the share writable while contents are being " "moved. If set to True, host-assisted migration will not be attempted." msgid "" "Enforces migration to preserve all file metadata when moving its contents. " "If set to True, host-assisted migration will not be attempted." msgstr "" "Enforces migration to preserve all file metadata when moving its contents. " "If set to True, host-assisted migration will not be attempted." msgid "" "Enforces the use of the host-assisted migration approach, which bypasses " "driver optimizations." msgstr "" "Enforces the use of the host-assisted migration approach, which bypasses " "driver optimisations." msgctxt "Current status of replica" msgid "Error" msgstr "Error" msgctxt "Current status of share" msgid "Error" msgstr "Error" msgctxt "Current status of share network" msgid "Error" msgstr "Error" msgctxt "Current status of share server" msgid "Error" msgstr "Error" msgctxt "Current status of snapshot" msgid "Error" msgstr "Error" msgid "Expected only pairs of key=value." msgstr "Expected only pairs of key=value." msgid "Export location" msgstr "Export location" msgid "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgstr "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgid "Extend" msgstr "Extend" msgid "Extend Share" msgstr "Extend Share" #, python-format msgid "Extend share \"%s\"" msgstr "Extend share \"%s\"" msgctxt "Current status of share" msgid "Extending Error" msgstr "Extending Error" msgid "Extra specs" msgstr "Extra specs" msgid "Force Host Assisted Migration" msgstr "Force Host Assisted Migration" msgid "From here you can update share network info. " msgstr "From here you can update share network info. " msgid "From here you can update the default quotas (max limits)." msgstr "From here you can update the default quotas (max limits)." msgid "Get migration progress" msgstr "Get migration progress" msgid "" "Got improper value for field 'driver_options'. Expected only pairs of " "key=value." msgstr "" "Got improper value for field 'driver_options'. Expected only pairs of " "key=value." msgid "Group specs" msgstr "Group specs" msgid "Host" msgstr "Host" msgid "Host of share" msgstr "Host of share" msgid "Host to migrate share" msgstr "Host to migrate share" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "Host where share is located, example: some.host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "IP Version" msgid "Id" msgstr "Id" #, python-format msgid "" "Improper value set to required extra spec " "'spec_driver_handles_share_servers'. Allowed values are %s. Case insensitive." msgstr "" "Improper value set to required extra spec " "'spec_driver_handles_share_servers'. Allowed values are %s. Case insensitive." msgctxt "Current status of share server" msgid "In-use" msgstr "In-use" msgctxt "Current status of snapshot" msgid "In-use" msgstr "In-use" msgctxt "Current status of share network" msgid "Inactive" msgstr "Inactive" #, python-format msgid "Key '%s' has improper length." msgstr "Key '%s' has improper length." #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "Key can not contain spaces. See string '%s'." #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "Keys should not contain spaces. Error in '%s'." msgid "Make visible for all" msgstr "Make visible for all" msgid "Manage" msgstr "Manage" msgctxt "Current status of share" msgid "Manage Error" msgstr "Managed Error" msgid "Manage Replicas" msgstr "Manage Replicas" msgid "Manage Rules" msgstr "Manage Rules" msgid "Manage Share" msgstr "Manage Share" msgid "Manage Share Group Type Access" msgstr "Manage Share Group Type Access" msgid "Manage Share Snapshot Rules" msgstr "Manage Share Snapshot Rules" msgid "Manage Share Type Access" msgstr "Manage Share Type Access" msgid "Metadata" msgstr "Metadata" msgid "Migrate Share" msgstr "Migrate Share" msgid "Migrate a Share" msgstr "Migrate a Share" msgctxt "Current status of share" msgid "Migrating" msgstr "Migrating" msgctxt "Current status of share" msgid "Migrating to" msgstr "Migrating to" #, python-format msgid "Migration of share %(name)s is at %(progress)s percent." msgstr "Migration of share %(name)s is at %(progress)s percent." msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "Modified project information and members, but unable to modify project " "quotas." msgid "Name" msgstr "Name" msgid "Network Type" msgstr "Network Type" msgid "Networks" msgstr "Networks" msgid "Neutron Net" msgstr "Neutron Net" msgid "Neutron Subnet" msgstr "Neutron Subnet" msgid "New Size (GiB)" msgstr "New Size (GiB)" msgid "New share network to be set in migrated share" msgstr "New share network to be set in migrated share" msgid "New share type to be set in migrating share" msgstr "New share type to be set in migrating share" msgid "New size must be greater than current size." msgstr "New size must be greater than current size." msgid "No projects found." msgstr "No projects found." msgid "No projects selected." msgstr "No projects selected." msgid "No security services found." msgstr "No security services found." msgid "No security services selected." msgstr "No security services selected." msgid "No source, empty share" msgstr "No source, empty share" msgid "No source, empty share group" msgstr "No source, empty share group" msgid "Nondisruptive" msgstr "Non-disruptive" msgid "Nova Net" msgstr "Nova Net" msgid "Obtain Progress" msgstr "Obtain Progress" msgid "Obtain migration progress of a Share" msgstr "Obtain migration progress of a Share" msgid "Overview" msgstr "Overview" msgid "Password" msgstr "Password" msgid "Passwords do not match." msgstr "Passwords do not match." msgid "Preserve Metadata" msgstr "Preserve Metadata" msgid "Preserve Snapshots" msgstr "Preserve Snapshots" msgid "Project" msgstr "Project" msgid "Projects with access to share group type" msgstr "Projects with access to share group type" msgid "Projects with access to share type" msgstr "Projects with access to share type" msgid "Protocol" msgstr "Protocol" msgid "Public" msgstr "Public" msgid "Quota" msgstr "Quota" #, python-format msgid "Replica Details: %(replica_display_name)s" msgstr "Replica Details: %(replica_display_name)s" msgid "Replica State" msgstr "Replica State" msgid "Replicas" msgstr "Replicas" msgid "Reset Replica State" msgstr "Reset Replica State" msgid "Reset Replica Status" msgstr "Reset Replica Status" msgid "Reset Share Group Snapshot Status" msgstr "Reset Share Group Snapshot Status" msgid "Reset Share Group Status" msgstr "Reset Share Group Status" msgid "Reset Status" msgstr "Reset Status" msgid "Reset replica state" msgstr "Reset replica state" msgid "Reset replica status" msgstr "Reset replica status" msgid "Reset state" msgstr "Reset state" msgid "Reset status" msgstr "Reset status" #, python-format msgid "Reseting replica ('%(id)s') state from '%(from)s' to '%(to)s'." msgstr "Resetting replica ('%(id)s') state from '%(from)s' to '%(to)s'." #, python-format msgid "Reseting replica ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "Resetting replica ('%(id)s') status from '%(from)s' to '%(to)s'." #, python-format msgid "Reseting share group ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "Reseting share group ('%(id)s') status from '%(from)s' to '%(to)s'." #, python-format msgid "" "Reseting share group snapshot ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "Reseting share group snapshot ('%(id)s') status from '%(from)s' to '%(to)s'." msgid "Resync" msgstr "Resync" msgid "Resync Replica" msgstr "Resync Replica" msgid "Resync replica" msgstr "Resync replica" #, python-format msgid "Resync'ing replica '%s'" msgstr "Resync'ing replica '%s'" msgid "Revert Share" msgstr "Revert Share" msgid "Revert Share to a Snapshot" msgstr "Revert Share to a Snapshot" msgid "Revert share to a snapshot" msgstr "Revert share to a snapshot" msgctxt "Current status of share" msgid "Reverting Error" msgstr "Reverting Error" msgid "Rules" msgstr "Rules" msgid "Save Changes" msgstr "Save Changes" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "Security Service Details: %(service_display_name)s" msgid "Security Service Overview" msgstr "Security Service Overview" msgid "Security Services" msgstr "Security Services" msgid "Security services within share network" msgstr "Security services within share network" msgid "Segmentation Id" msgstr "Segmentation Id" msgid "Selected projects" msgstr "Selected projects" msgid "Selected security services" msgstr "Selected security services" msgid "Server" msgstr "Server" msgid "Set Replica as Active" msgstr "Set Replica as Active" msgid "Set as Active" msgstr "Set as Active" msgid "Set maximum quotas for the project." msgstr "Set maximum quotas for the project." #, python-format msgid "Setting replica \"%s\" as active..." msgstr "Setting replica \"%s\" as active..." #, python-format msgid "Share \"%(s)s\" has been reverted to \"%(ss)s\" snapshot successfully" msgstr "Share \"%(s)s\" has been reverted to \"%(ss)s\" snapshot successfully" #, python-format msgid "Share Details: %(share_display_name)s" msgstr "Share Details: %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "Share Details: %(share_name)s" msgid "Share Group" msgstr "Share Group" #, python-format msgid "Share Group Details: %s" msgstr "Share Group Details: %s" msgid "Share Group Name" msgstr "Share Group Name" msgid "Share Group Overview" msgstr "Share Group Overview" msgid "Share Group Snapshot" msgstr "Share Group Snapshot" #, python-format msgid "Share Group Snapshot Details: %(sgs_display_name)s" msgstr "Share Group Snapshot Details: %(sgs_display_name)s" msgid "Share Group Snapshot Overview" msgstr "Share Group Snapshot Overview" msgid "Share Group Snapshots" msgstr "Share Group Snapshots" msgid "Share Group Type" msgstr "Share Group Type" msgid "Share Group Types" msgstr "Share Group Types" msgid "Share Groups" msgstr "Share Groups" msgid "Share ID" msgstr "Share ID" #, python-format msgid "Share Instance Details: %s" msgstr "Share Instance Details: %s" msgid "Share Instance Overview" msgstr "Share Instance Overview" msgid "Share Instances" msgstr "Share Instances" msgid "Share Name" msgstr "Share Name" msgid "Share Network" msgstr "Share Network" #, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "Share Network Details: %(network_display_name)s" msgid "Share Network Info" msgstr "Share Network Info" msgid "Share Network Overview" msgstr "Share Network Overview" msgid "Share Networks" msgstr "Share Networks" msgid "Share Overview" msgstr "Share Overview" msgid "Share Protocol" msgstr "Share Protocol" #, python-format msgid "Share Replicas: %(share_display_name)s" msgstr "Share Replicas: %(share_display_name)s" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "Share Rules: %(share_display_name)s" msgid "Share Server" msgstr "Share Server" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "Share Server Details: %(server_name)s" msgid "Share Server Id" msgstr "Share Server Id" msgid "Share Server Overview" msgstr "Share Server Overview" msgid "Share Servers" msgstr "Share Servers" msgid "Share Snapshot Name" msgstr "Share Snapshot Name" msgid "Share Snapshot Overview" msgstr "Share Snapshot Overview" msgid "Share Snapshot Rules" msgstr "Share Snapshot Rules" msgid "Share Snapshots" msgstr "Share Snapshots" msgid "Share Snapshots Storage" msgstr "Share Snapshots Storage" msgid "Share Source" msgstr "Share Source" msgid "Share Storage" msgstr "Share Storage" msgid "Share Type" msgstr "Share Type" msgid "Share Types" msgstr "Share Types" msgid "Share Types (multiple available)" msgstr "Share Types (multiple available)" msgid "Share Types (one available)" msgstr "Share Types (one available)" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgid "Share gigabytes" msgstr "Share gigabytes" msgid "Share name to be assigned" msgstr "Share name to be assigned" #, python-format msgid "Share replica %s has been deleted." msgstr "Share replica %s has been deleted." #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "Share size must be equal to or greater than the snapshot size (%sGiB)" msgid "Share snapshot gigabytes" msgstr "Share snapshot gigabytes" msgid "Share snapshots" msgstr "Share snapshots" msgid "Share types" msgstr "Share types" msgid "Shares" msgstr "Shares" msgid "Shares Networks" msgstr "Shares Networks" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "Size" msgid "Size (GiB)" msgstr "Size (GiB)" msgid "Snapshot" msgstr "Snapshot" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "Snapshot Details: %(snapshot_display_name)s" #, python-format msgid "Snapshot Rules: %(snapshot_display_name)s" msgstr "Snapshot Rules: %(snapshot_display_name)s" msgid "Source" msgstr "Source" msgid "Source Share Group Snapshot" msgstr "Source Share Group Snapshot" msgid "Source Type" msgstr "Source Type" msgid "" "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." msgstr "" "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." msgid "" "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." msgstr "" "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." msgid "Start migration" msgstr "Start migration" msgid "Status" msgstr "Status" #, python-format msgid "Successfully created security service: %s" msgstr "Successfully created security service: %s" #, python-format msgid "Successfully created share group type: %s" msgstr "Successfully created share group type: %s" #, python-format msgid "Successfully created share network: %s" msgstr "Successfully created share network: %s" #, python-format msgid "Successfully created share type: %s" msgstr "Successfully created share type: %s" #, python-format msgid "Successfully sent the request to cancel migration of share: %s." msgstr "Successfully sent the request to cancel migration of share: %s." #, python-format msgid "Successfully sent the request to complete migration of share: %s." msgstr "Successfully sent the request to complete migration of share: %s." #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "Successfully sent the request to manage share: %s" #, python-format msgid "Successfully sent the request to migrate share: %s." msgstr "Successfully sent the request to migrate share: %s." #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "Successfully sent the request to unmanage share: %s" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "Successfully updated extra specs for share type '%s'." #, python-format msgid "Successfully updated group specs for share group type '%s'." msgstr "Successfully updated group specs for share group type '%s'." #, python-format msgid "Successfully updated security service \"%s\"" msgstr "Successfully updated security service \"%s\"" #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "The share size cannot be less than the snapshot size (%sGiB)" msgid "Type" msgstr "Type" msgid "Unable to add rule." msgstr "Unable to add rule." msgid "Unable to add snapshot rule." msgstr "Unable to add snapshot rule." #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "Unable to cancel migration of share %s at this moment." #, python-format msgid "Unable to complete migration of share %s." msgstr "Unable to complete migration of share %s." msgid "Unable to create security service." msgstr "Unable to create security service." msgid "Unable to create share group snapshot." msgstr "Unable to create share group snapshot." msgid "Unable to create share group type." msgstr "Unable to create share group type." msgid "Unable to create share group." msgstr "Unable to create share group." msgid "Unable to create share network." msgstr "Unable to create share network." msgid "Unable to create share replica." msgstr "Unable to create share replica." msgid "Unable to create share snapshot." msgstr "Unable to create share snapshot." msgid "Unable to create share type." msgstr "Unable to create share type." msgid "Unable to create share." msgstr "Unable to create share." #, python-format msgid "Unable to create share. %s" msgstr "Unable to create share. %s" #, python-format msgid "Unable to delete replica \"%s\"." msgstr "Unable to delete replica \"%s\"." #, python-format msgid "Unable to delete rule \"%s\"." msgstr "Unable to delete rule \"%s\"." #, python-format msgid "Unable to delete share \"%s\". " msgstr "Unable to delete share \"%s\". " #, python-format msgid "" "Unable to delete share group snapshot \"%s\". One or more share groups " "depend on it." msgstr "" "Unable to delete share group snapshot \"%s\". One or more share groups " "depend on it." #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "Unable to delete snapshot \"%s\". One or more shares depend on it." #, python-format msgid "Unable to delete snapshot rule \"%s\"." msgstr "Unable to delete snapshot rule \"%s\"." msgid "Unable to extend share." msgstr "Unable to extend share." msgid "Unable to get information about share group type access." msgstr "Unable to get information about share group type access." msgid "Unable to get information about share type access." msgstr "Unable to get information about share type access." msgid "Unable to get list of projects." msgstr "Unable to get list of projects." msgid "Unable to get the security services hosts" msgstr "Unable to get the security services hosts" #, python-format msgid "Unable to get the specified share group '%s' for snapshot creation." msgstr "Unable to get the specified share group '%s' for snapshot creation." msgid "Unable to load the specified share group snapshot." msgstr "Unable to load the specified share group snapshot." msgid "Unable to load the specified snapshot." msgstr "Unable to load the specified snapshot." msgid "Unable to manage share" msgstr "Unable to manage share" #, python-format msgid "Unable to migrate share %s." msgstr "Unable to migrate share %s." #, python-format msgid "Unable to obtain progress of migration of share %s at this moment." msgstr "Unable to obtain progress of migration of share %s at this moment." #, python-format msgid "Unable to reset state of replica '%s'." msgstr "Unable to reset state of replica '%s'." #, python-format msgid "Unable to reset status of replica '%s'." msgstr "Unable to reset status of replica '%s'." #, python-format msgid "Unable to reset status of share group '%s'." msgstr "Unable to reset status of share group '%s'." #, python-format msgid "Unable to reset status of share group snapshot '%s'." msgstr "Unable to reset status of share group snapshot '%s'." #, python-format msgid "Unable to resync replica '%s'." msgstr "Unable to resync replica '%s'." msgid "Unable to retrieve list of projects." msgstr "Unable to retrieve list of projects." msgid "Unable to retrieve quotas." msgstr "Unable to retrieve quotas." #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "Unable to retrieve replica %sdetails." #, python-format msgid "Unable to retrieve replica '%s'." msgstr "Unable to retrieve replica '%s'." #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "Unable to retrieve security service '%s' details." msgid "Unable to retrieve security services" msgstr "Unable to retrieve security services" msgid "Unable to retrieve security_service." msgstr "Unable to retrieve security_service." msgid "Unable to retrieve share details." msgstr "Unable to retrieve share details." #, python-format msgid "Unable to retrieve share group '%s'." msgstr "Unable to retrieve share group '%s'." msgid "Unable to retrieve share group details." msgstr "Unable to retrieve share group details." #, python-format msgid "Unable to retrieve share group snapshot '%s'." msgstr "Unable to retrieve share group snapshot '%s'." msgid "Unable to retrieve share group snapshot details." msgstr "Unable to retrieve share group snapshot details." msgid "Unable to retrieve share group snapshot list." msgstr "Unable to retrieve share group snapshot list." msgid "Unable to retrieve share group snapshot." msgstr "Unable to retrieve share group snapshot." msgid "Unable to retrieve share group snapshots." msgstr "Unable to retrieve share group snapshots." msgid "Unable to retrieve share group types." msgstr "Unable to retrieve share group types." msgid "Unable to retrieve share group." msgstr "Unable to retrieve share group." msgid "Unable to retrieve share groups." msgstr "Unable to retrieve share groups." msgid "Unable to retrieve share instance details." msgstr "Unable to retrieve share instance details." msgid "Unable to retrieve share instances." msgstr "Unable to retrieve share instances." msgid "Unable to retrieve share limit information." msgstr "Unable to retrieve share limit information." msgid "Unable to retrieve share list." msgstr "Unable to retrieve share list." msgid "Unable to retrieve share network details." msgstr "Unable to retrieve share network details." msgid "Unable to retrieve share network." msgstr "Unable to retrieve share network." msgid "Unable to retrieve share networks" msgstr "Unable to retrieve share networks" msgid "Unable to retrieve share replicas." msgstr "Unable to retrieve share replicas." msgid "Unable to retrieve share rules." msgstr "Unable to retrieve share rules." msgid "Unable to retrieve share server details." msgstr "Unable to retrieve share server details." msgid "Unable to retrieve share servers" msgstr "Unable to retrieve share servers" msgid "Unable to retrieve share snapshot list." msgstr "Unable to retrieve share snapshot list." msgid "Unable to retrieve share snapshot rules." msgstr "Unable to retrieve share snapshot rules." msgid "Unable to retrieve share snapshot." msgstr "Unable to retrieve share snapshot." msgid "Unable to retrieve share snapshots list." msgstr "Unable to retrieve share snapshots list." msgid "Unable to retrieve share snapshots." msgstr "Unable to retrieve share snapshots." msgid "Unable to retrieve share types." msgstr "Unable to retrieve share types." msgid "Unable to retrieve share." msgstr "Unable to retrieve share." #, python-format msgid "Unable to retrieve share. %s" msgstr "Unable to retrieve share. %s" msgid "Unable to retrieve share_gruop_type." msgstr "Unable to retrieve share_group_type." msgid "Unable to retrieve share_type." msgstr "Unable to retrieve share_type." msgid "Unable to retrieve snapshot details." msgstr "Unable to retrieve snapshot details." msgid "Unable to retrieve snapshot." msgstr "Unable to retrieve snapshot." msgid "Unable to retrieve volume details." msgstr "Unable to retrieve volume details." msgid "Unable to revert share to the snapshot." msgstr "Unable to revert share to the snapshot." msgid "Unable to set project quotas." msgstr "Unable to set project quotas." #, python-format msgid "Unable to set replica '%s' as active." msgstr "Unable to set replica '%s' as active." msgid "Unable to unmanage share." msgstr "Unable to unmanage share." #, python-format msgid "Unable to update access for share group type \"%s\"." msgstr "Unable to update access for share group type \"%s\"." #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "Unable to update access for share type \"%s\"." msgid "Unable to update default quotas." msgstr "Unable to update default quotas." msgid "Unable to update extra_specs for share type." msgstr "Unable to update extra_specs for share type." msgid "Unable to update group_specs for share group type." msgstr "Unable to update group_specs for share group type." msgid "Unable to update security service." msgstr "Unable to update security service." msgid "Unable to update share group snapshot." msgstr "Unable to update share group snapshot." msgid "Unable to update share group type." msgstr "Unable to update share group type." msgid "Unable to update share group." msgstr "Unable to update share group." msgid "Unable to update share metadata." msgstr "Unable to update share metadata." #, python-format msgid "Unable to update share network \"%s\"." msgstr "Unable to update share network \"%s\"." msgid "Unable to update share network." msgstr "Unable to update share network." msgid "Unable to update share snapshot." msgstr "Unable to update share snapshot." msgid "Unable to update share type." msgstr "Unable to update share type." msgid "Unable to update share." msgstr "Unable to update share." msgid "Unknown" msgstr "Unknown" msgid "Unmanage" msgstr "Unmanage" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "Unmanaged Error" msgid "Unmanage Share" msgstr "Unmanage Share" msgid "Update" msgstr "Update" msgid "Update Share Group" msgstr "Update Share Group" msgid "Update Share Group Snapshot" msgstr "Update Share Group Snapshot" msgid "Update Share Group Type" msgstr "Update Share Group Type" msgid "Update Share Network" msgstr "Update Share Network" msgid "Update Share Snapshot" msgstr "Update Share Snapshot" msgid "Update Share Type" msgstr "Update Share Type" msgid "Update Share group Type" msgstr "Update Share group Type" msgid "Updated At" msgstr "Updated At" #, python-format msgid "Updated access for share group type \"%s\"." msgstr "Updated access for share group type \"%s\"." #, python-format msgid "Updated access for share type \"%s\"." msgstr "Updated access for share type \"%s\"." #, python-format msgid "Updated share network \"%s\"." msgstr "Updated share network \"%s\"." #, python-format msgid "Updating share \"%s\"" msgstr "Updating share \"%s\"" #, python-format msgid "Updating share group \"%s\"" msgstr "Updating share group \"%s\"" #, python-format msgid "Updating share group snapshot \"%s\"" msgstr "Updating share group snapshot \"%s\"" #, python-format msgid "Updating share metadata \"%s\"" msgstr "Updating share metadata \"%s\"" #, python-format msgid "Updating share network \"%s\"" msgstr "Updating share network \"%s\"" #, python-format msgid "Updating share snapshot \"%s\"" msgstr "Updating share snapshot \"%s\"" msgid "Use share group snapshot as a source" msgstr "Use share group snapshot as a source" msgid "Use snapshot as a source" msgstr "Use snapshot as a source" msgid "User" msgstr "User" msgid "Visibility" msgstr "Visibility" msgid "Writable" msgstr "Writable" msgid "key=value pairs per line can be set" msgstr "key=value pairs per line can be set" manila-ui-2.13.0/manila_ui/locale/fr/000077500000000000000000000000001323215354300172565ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/fr/LC_MESSAGES/000077500000000000000000000000001323215354300210435ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/fr/LC_MESSAGES/django.po000066400000000000000000000617151323215354300226570ustar00rootroot00000000000000# Gérald LONLAS , 2016. #zanata # Benjamin ACH , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.9.1.dev1\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-06-08 22:16+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-02-25 11:57+0000\n" "Last-Translator: Benjamin ACH \n" "Language-Team: French\n" "Language: fr\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" #, python-format msgid "%sGiB" msgstr "%sGio" msgid "(Quota exceeded)" msgstr "(Quota dépassé)" msgid "Access Key" msgstr "Clef d’accès" msgid "Access Level" msgstr "Niveau d'accès" msgid "Access To" msgstr "Accès à" msgid "Access Type" msgstr "Type d'accès" msgid "Access to" msgstr "Accès à" msgctxt "Current status of share network" msgid "Active" msgstr "Actif" msgctxt "Current status of share server" msgid "Active" msgstr "Actif" msgid "Add" msgstr "Ajouter" msgid "Add Rule" msgstr "Ajouter une règle" msgid "Add Security Service" msgstr "Ajout d'un service de sécurité " msgid "Add rule" msgstr "Ajouter une règle" msgid "Add security services to share network." msgstr "Ajout du service de sécurité au partage réseau." msgid "All keys and values must be in range from 1 to 255." msgstr "Toutes les clés doit avoir une valeur comprise dans la plage 1 à 255." msgid "Allow project access to share type." msgstr "Autoriser un projet à accéder au type de partage." msgid "At least one security service must be specified." msgstr "Au moins un service de sécurité doit être indiqué." msgid "Availability Zone" msgstr "Zone de disponibilité" msgid "Availability zone" msgstr "Zone de disponibilité" msgctxt "Current status of replica" msgid "Available" msgstr "Disponible" msgctxt "Current status of share" msgid "Available" msgstr "Disponible" msgctxt "Current status of snapshot" msgid "Available" msgstr "Disponible" msgid "Available projects" msgstr "Projets disponibles" msgid "Available security services" msgstr "Service de sécurité disponible." msgid "Cancel Migration" msgstr "Annuler la migration" msgid "Cancel migration" msgstr "Annuler la migration" msgid "Cancel migration of a Share" msgstr "Annuler la migration d'un partage" msgid "Choose a snapshot" msgstr "Choisir un instantané" msgid "Complete Migration" msgstr "Migration terminée" msgid "Complete migration" msgstr "Migration terminée" msgid "Complete migration of a Share" msgstr "Migration du partage avec succès" msgid "Confirm Migration Cancelling of Share" msgstr "Confirmer l'annulation de la migration du partage" msgid "Confirm Migration Completion of Share" msgstr "Confirmer l'avancement de la migration du partage" msgid "Confirm Password" msgstr "Confirmer le mot de passe" msgid "Confirm Unmanage Share" msgstr "Confirmer le partage non-géré" msgid "Create" msgstr "Créer" msgid "Create Replica" msgstr "Créer un replica" msgid "Create Security Service" msgstr "Créer un service de sécurité " msgid "Create Share" msgstr "Créer un partage" msgid "Create Share Network" msgstr "Créer un partage réseau" msgid "Create Share Snapshot" msgstr "Créer l'instantané du partage" msgid "Create Share Type" msgstr "Créer un type de partage" msgid "Create a Share" msgstr "Créer un partage" msgid "Created At" msgstr "Créé le" msgctxt "Current status of replica" msgid "Creating" msgstr "Création en cours" msgctxt "Current status of share" msgid "Creating" msgstr "Création en cours" msgctxt "Current status of share server" msgid "Creating" msgstr "Création en cours" msgctxt "Current status of snapshot" msgid "Creating" msgstr "Création en cours" #, python-format msgid "Creating replica for share \"%s\"." msgstr "Création du réplica pour le partage \"%s\"." #, python-format msgid "Creating rule for \"%s\"" msgstr "Création de la règle pour \"%s\"" #, python-format msgid "Creating share \"%s\"" msgstr "Création du partage \"%s\"" #, python-format msgid "Creating share snapshot \"%s\"." msgstr "Création de l'instantané partagé \"%s\"." msgid "Current Size (GiB)" msgstr "Taille actuelle (Gio)" msgid "DNS IP" msgstr "IP DNS" msgctxt "Current status of replica" msgid "Deleting" msgstr "Suppression en cours" msgctxt "Current status of share" msgid "Deleting" msgstr "Suppression en cours" msgid "Description" msgstr "Description" msgid "Destination host and pool where share will be migrated to." msgstr "Hôte de destination et pool où le partage sera migré." msgid "Domain" msgstr "Domaine" msgid "Driver handles share servers" msgstr "Pilote qui supporte les partages serveur" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "Option du pilote ('volume_id' pour les Generic driver, etc...)" #, python-format msgid "Duplicated keys '%s'." msgstr "Clés dupliquées '%s'." msgid "Edit" msgstr "Éditer" msgid "Edit Security Service" msgstr "Éditer le service de sécurité " msgid "Edit Share" msgstr "Éditer le partage" msgid "Edit Share Metadata" msgstr "Éditer les métadonnées du partage" msgid "Edit Share Network" msgstr "Éditer le partage réseau" msgctxt "Current status of replica" msgid "Error" msgstr "Erreur" msgctxt "Current status of share" msgid "Error" msgstr "Erreur" msgctxt "Current status of share network" msgid "Error" msgstr "Erreur" msgctxt "Current status of share server" msgid "Error" msgstr "Erreur" msgctxt "Current status of snapshot" msgid "Error" msgstr "Erreur" msgid "Expected only pairs of key=value." msgstr "Seule les paires de clé-valeur key=value sont attendus." msgid "Export location" msgstr "Emplacement de l'export" msgid "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgstr "" "Emplacement de l'export du partage. Par exemple pour NFS : 1.2.3.4:/path/to/" "share" msgid "Extend" msgstr "Étendre" msgid "Extend Share" msgstr "Étendre le partage" #, python-format msgid "Extend share \"%s\"" msgstr "Étendre le partage \"%s\"" msgctxt "Current status of share" msgid "Extending Error" msgstr "Erreur étendue" msgid "Extra specs" msgstr "Spécifications supplémentaires" msgid "Force Host Assisted Migration" msgstr "Forcer la migration assisté de l'hôte" msgid "From here you can update share network info. " msgstr "D'ici, vous pouvez mettre à jour les informations du partage réseau." msgid "From here you can update the default quotas (max limits)." msgstr "" "Ici, vous pouvez mettre à jour les quotas par défaut (limites maximales)." msgid "Get migration progress" msgstr "Voir l'avancement de la migration" msgid "Host" msgstr "Hôte" msgid "Host of share" msgstr "Hôte du partage" msgid "Host to migrate share" msgstr "Hôte pour la migration du partage" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "Hôte où se trouve le partage, exemple : some.host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "Version d'IP" msgid "Id" msgstr "ID" msgctxt "Current status of share server" msgid "In-use" msgstr "En cours d'utilisation" msgctxt "Current status of snapshot" msgid "In-use" msgstr "En cours d'utilisation" msgctxt "Current status of share network" msgid "Inactive" msgstr "Inactif" #, python-format msgid "Key '%s' has improper length." msgstr "La clé '%s' a une longueur inappropriée." #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "La clé ne peut pas contenir d'espace. Voir la chaine '%s'." #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "La clé ne peut pas contenir d'espace. Erreur dans '%s'." msgid "Make visible for all" msgstr "Rendre visible pour tous" msgid "Manage" msgstr "Gérer" msgctxt "Current status of share" msgid "Manage Error" msgstr "Erreur gérée" msgid "Manage Replicas" msgstr "Gérer les réplicas" msgid "Manage Rules" msgstr "Gérer les règles" msgid "Manage Share" msgstr "Gérer le partage" msgid "Manage Share Type Access" msgstr "Gérer les accès du type de partage" msgid "Metadata" msgstr "Métadonnées" msgid "Migrate Share" msgstr "Migrer le partage" msgid "Migrate a Share" msgstr "Migrer le partage" msgctxt "Current status of share" msgid "Migrating" msgstr "Migration en cours" msgctxt "Current status of share" msgid "Migrating to" msgstr "Migration vers" #, python-format msgid "Migration of share %(name)s is at %(progress)s percent." msgstr "Migration du partage %(name)s est à %(progress)s pourcent(s)." msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "Les informations et les membres du projet ont bien été modifiés, mais " "impossible de modifier les quotas." msgid "Name" msgstr "Nom" msgid "Network Type" msgstr "Type de réseau" msgid "Networks" msgstr "Réseaux" msgid "Neutron Net" msgstr "Neutron Net" msgid "Neutron Subnet" msgstr "Sous-réseau Neutron" msgid "New Size (GiB)" msgstr "Nouvelle taille (Gio)" msgid "New share network to be set in migrated share" msgstr "Le nouveau partage réseau doit être mis dans le partage migré" msgid "New share type to be set in migrating share" msgstr "" "Nouveau type de partage qui doit être appliqué dans la migration de partage" msgid "New size must be greater than current size." msgstr "La nouvelle taille doit être supérieure à la taille en cours." msgid "No projects found." msgstr "Aucun projet trouvé." msgid "No projects selected." msgstr "Aucun projet sélectionné." msgid "No security services found." msgstr "Aucun service de sécurité trouvé." msgid "No security services selected." msgstr "Aucun service de sécurité sélectionné." msgid "No source, empty share" msgstr "Aucune source, partage vide" msgid "Nondisruptive" msgstr "Non perturbateur " msgid "Nova Net" msgstr "Nova Net" msgid "Obtain Progress" msgstr "" "\t\n" "Voir l'avancement" msgid "Obtain migration progress of a Share" msgstr "Voir l'avancement de la migration d'un partage" msgid "Overview" msgstr "Vue d'ensemble" msgid "Password" msgstr "Mot de passe" msgid "Passwords do not match." msgstr "Les mots de passe ne correspondent pas." msgid "Preserve Metadata" msgstr "Préserver les métadonnées" msgid "Preserve Snapshots" msgstr "Conserver les instantanés" msgid "Project" msgstr "Projet" msgid "Projects with access to share type" msgstr "Projets avec un accès au type de partage" msgid "Protocol" msgstr "Protocole" msgid "Public" msgstr "Public" msgid "Quota" msgstr "Quota" #, python-format msgid "Replica Details: %(replica_display_name)s" msgstr "Détail du replica : %(replica_display_name)s" msgid "Replica State" msgstr "État du replica" msgid "Replicas" msgstr "Réplicas" msgid "Reset Replica State" msgstr "Réinitialiser l'état du replica" msgid "Reset Replica Status" msgstr "Réinitialiser le statut du replica" msgid "Reset replica state" msgstr "Réinitialiser l'état du replica" msgid "Reset replica status" msgstr "Réinitialiser le statut du replica" msgid "Reset state" msgstr "Réinitialiser l'état" msgid "Reset status" msgstr "Réinitialiser le statut" #, python-format msgid "Reseting replica ('%(id)s') state from '%(from)s' to '%(to)s'." msgstr "" "Réinitialisation de l'état du replica ('%(id)s') de '%(from)s' à '%(to)s'." #, python-format msgid "Reseting replica ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "Réinitialisation du statut du replica ('%(id)s') de '%(from)s' à '%(to)s'." msgid "Resync" msgstr "Resynchroniser" msgid "Resync Replica" msgstr "Resynchroniser le replica" msgid "Resync replica" msgstr "Resynchroniser le replica" #, python-format msgid "Resync'ing replica '%s'" msgstr "Resynchronisation du replica \"%s\"" msgid "Rules" msgstr "Règles" msgid "Save Changes" msgstr "Sauvegarder les modifications" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "Détail du service de sécurité : %(service_display_name)s" msgid "Security Services" msgstr "Services de sécurité" msgid "Security services within share network" msgstr "Service de sécurité dans le partage réseau" msgid "Segmentation Id" msgstr "ID segmentation" msgid "Selected projects" msgstr "Projets sélectionnés" msgid "Selected security services" msgstr "Service de sécurité sélectionné" msgid "Server" msgstr "Serveur" msgid "Set Replica as Active" msgstr "Mettre le replica \"%s\" à actif" msgid "Set as Active" msgstr "Mettre à actif" msgid "Set maximum quotas for the project." msgstr "Définir les quotas maximum pour le projet." #, python-format msgid "Setting replica \"%s\" as active..." msgstr "Mettre le replica \"%s\" à actif" #, python-format msgid "Share Details: %(share_display_name)s" msgstr "Détails du partage : %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "Détails du partage : %(share_name)s" msgid "Share ID" msgstr "ID du partage" #, python-format msgid "Share Instance Details: %s" msgstr "Détails du partage d'instance : %s" msgid "Share Instances" msgstr "Partage d'instance" msgid "Share Name" msgstr "Nom du partage" msgid "Share Network" msgstr "Partage réseau" #, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "Détail du partage réseau : %(network_display_name)s" msgid "Share Network Info" msgstr "Informations du partage réseau" msgid "Share Networks" msgstr "Partages réseau" msgid "Share Protocol" msgstr "Protocole de partage" #, python-format msgid "Share Replicas: %(share_display_name)s" msgstr "Replicas du partage : %(share_display_name)s" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "Règles du partage : %(share_display_name)s" msgid "Share Server" msgstr "Partage serveur" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "Détails du partage serveur : %(server_name)s" msgid "Share Server Id" msgstr "ID du partage serveur" msgid "Share Servers" msgstr "Partages serveur" msgid "Share Snapshots" msgstr "Instantanés de partage" msgid "Share Snapshots Storage" msgstr "Instantané du partage de stockage" msgid "Share Source" msgstr "Source du partage" msgid "Share Storage" msgstr "Partage de stockage" msgid "Share Type" msgstr "Type de partage" msgid "Share Types" msgstr "Types de partage" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "Le partage ne peut pas être étendu à %(req)iGio car vous avez disposez " "uniquement d'un quota de %(avail)iGio." msgid "Share name to be assigned" msgstr "Nom du partage à donner" #, python-format msgid "Share replica %s has been deleted." msgstr "Le partage de replica %s a été supprimé." #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "" "La taille du partage doit être supérieure ou égale à la taille de " "l'instantané (%sGio)" msgid "Shares" msgstr "Partages" msgid "Shares Networks" msgstr "Partage réseau" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "Taille" msgid "Size (GiB)" msgstr "Taille (Gio)" msgid "Snapshot" msgstr "Instantané" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "Détails de l'instantané : %(snapshot_display_name)s" msgid "Source" msgstr "Source" msgid "Start migration" msgstr "Démarrer la migration" msgid "Status" msgstr "Statut" #, python-format msgid "Successfully created security service: %s" msgstr "Service de sécurité créé avec succès : %s" #, python-format msgid "Successfully created share network: %s" msgstr "Partage réseau créé avec succès : %s" #, python-format msgid "Successfully created share type: %s" msgstr "Le type de partage a été créé : %s" #, python-format msgid "Successfully sent the request to cancel migration of share: %s." msgstr "" "La demande pour annuler la migration du partage a été envoyée avec succès : " "%s" #, python-format msgid "Successfully sent the request to complete migration of share: %s." msgstr "" "La demande pour finir la migration du partage a été envoyée avec succès : %s" #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "La demande de gestion du partage a été envoyée avec succès : %s" #, python-format msgid "Successfully sent the request to migrate share: %s." msgstr "La demande de migration du partage a été envoyée avec succès : %s" #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "La demande de non-gestion du partage a été envoyée avec succès : %s" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "Spécification supplémentaire \"%s\" mise à jour avec succès." #, python-format msgid "Successfully updated security service \"%s\"" msgstr "Service de sécurité \"%s\" mis à jour avec succès" #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "" "La taille du partage ne peut pas être inférieure à la taille de l'instantané " "(%sGio)" msgid "Type" msgstr "Type" msgid "Unable to add rule." msgstr "Impossible d'ajouter la règle." #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "Il est impossible pour le moment d'annuler la migration du partage %s." #, python-format msgid "Unable to complete migration of share %s." msgstr "Impossible de finir la migration du partage %s." msgid "Unable to create security service." msgstr "Impossible de créer le service de sécurité." msgid "Unable to create share network." msgstr "Impossible de créer le partage réseau." msgid "Unable to create share replica." msgstr "Impossible de créer le partage de replica." msgid "Unable to create share snapshot." msgstr "Impossible de créer un instantané partagé." msgid "Unable to create share type." msgstr "Impossible de créer le type de partage." msgid "Unable to create share." msgstr "Impossible de créer le partage." #, python-format msgid "Unable to delete replica \"%s\"." msgstr "Impossible de supprimer le replica \"%s\"." #, python-format msgid "Unable to delete rule \"%s\"." msgstr "Impossible de supprimer la règle \"%s\"." #, python-format msgid "Unable to delete share \"%s\". " msgstr "Impossible de supprimer le partage \"%s\"" #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "" "Impossible de supprimer l'instantané \"%s\". Un ou plusieurs partages " "dépendent de lui." msgid "Unable to extend share." msgstr "Impossible d'étendre le partage." msgid "Unable to get information about share type access." msgstr "" "Impossible de récupérer les information au sujet des accès sur le type de " "partage." msgid "Unable to get list of projects." msgstr "Impossible d'obtenir la liste des projets" msgid "Unable to get the security services hosts" msgstr "Impossible de récupérer les hôtes des services de sécurité" msgid "Unable to load the specified snapshot." msgstr "Impossible de charger l'instantané spécifié." msgid "Unable to manage share" msgstr "Impossible de gérer le partage." #, python-format msgid "Unable to migrate share %s." msgstr "Impossible de migrer le partage %s." #, python-format msgid "Unable to obtain progress of migration of share %s at this moment." msgstr "" "Il est impossible pour le moment d'obtenir la progression de la migration du " "partage %s." #, python-format msgid "Unable to reset state of replica '%s'." msgstr "Impossible de réinitialiser l'état du replica \"%s\"." #, python-format msgid "Unable to reset status of replica '%s'." msgstr "Impossible de réinitialiser le statut du replica \"%s\"." #, python-format msgid "Unable to resync replica '%s'." msgstr "Impossible de synchroniser le replica \"%s\"." msgid "Unable to retrieve list of projects." msgstr "Impossible de récupérer la liste des projets." msgid "Unable to retrieve quotas." msgstr "Impossible de récupérer les quotas." #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "Impossible de récupérer les détails du replica \"%s\"." #, python-format msgid "Unable to retrieve replica '%s'." msgstr "Impossible de récupérer le replica \"%s\"." #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "Impossible de récupérer les détails du service de sécurité \"%s\"." msgid "Unable to retrieve security services" msgstr "Impossible de récupérer les services de sécurité." msgid "Unable to retrieve security_service." msgstr "Impossible de récupérer security_service." msgid "Unable to retrieve share details." msgstr "Impossible de récupérer les détails du partage." msgid "Unable to retrieve share instance details." msgstr "Impossible de récupérer les détails du partage d'instance." msgid "Unable to retrieve share instances." msgstr "Impossible de récupérer les partages d'instance" msgid "Unable to retrieve share limit information." msgstr "Impossible de récupérer les informations de limite du partage." msgid "Unable to retrieve share list." msgstr "Impossible de récupérer la liste des partages." msgid "Unable to retrieve share network details." msgstr "Impossible de récupérer les détails du partage réseau." msgid "Unable to retrieve share network." msgstr "Impossible de récupérer le partage réseau." msgid "Unable to retrieve share networks" msgstr "Impossible de récupérer les partages réseau" msgid "Unable to retrieve share replicas." msgstr "Impossible de récupérer les partages de replica." msgid "Unable to retrieve share rules." msgstr "Impossible de récupérer la liste des partages." msgid "Unable to retrieve share server details." msgstr "Impossible de récupérer les détails du partage serveur." msgid "Unable to retrieve share servers" msgstr "Impossible de récupérer les partages de serveur" msgid "Unable to retrieve share snapshots list." msgstr "Impossible de récupérer la liste des instantanés partagés." msgid "Unable to retrieve share snapshots." msgstr "Impossible de récupérer les instantanés du partage." msgid "Unable to retrieve share." msgstr "Impossible de récupérer le partage." #, python-format msgid "Unable to retrieve share. %s" msgstr "Impossible de récupérer les partages \"%s\"." msgid "Unable to retrieve share_type." msgstr "Impossible de récupérer le share_type." msgid "Unable to retrieve snapshot details." msgstr "Impossible de récupérer les détails de l'instantané." msgid "Unable to retrieve snapshot." msgstr "Impossible de récupérer l'instantané." msgid "Unable to retrieve volume details." msgstr "Impossible de récupérer les détails du volume." msgid "Unable to set project quotas." msgstr "Impossible de définir les quotas du projet." #, python-format msgid "Unable to set replica '%s' as active." msgstr "Impossible de mettre le replica \"%s\" à actif." msgid "Unable to unmanage share." msgstr "Impossible de ne pas gérer le partage." #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "Impossible de mettre à jour le type de partage \"%s\"." msgid "Unable to update default quotas." msgstr "Impossible de mettre à jour les quotas par défaut." msgid "Unable to update extra_specs for share type." msgstr "Impossible de mettre à jour extra_specs pour le type de partage." msgid "Unable to update security service." msgstr "Impossible de mettre à jour le service de sécurité." msgid "Unable to update share metadata." msgstr "Impossible de mettre à jour les métadonnées du partage." #, python-format msgid "Unable to update share network \"%s\"." msgstr "Impossible de mettre à jour le partage réseau \"%s\"." msgid "Unable to update share network." msgstr "Impossible de mettre à jour le partage réseau." msgid "Unable to update share type." msgstr "Impossible de mettre à jour le type de partage." msgid "Unable to update share." msgstr "Impossible de mettre à jour le partage." msgid "Unknown" msgstr "Inconnu" msgid "Unmanage" msgstr "Non-géré" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "Erreur non-gérée" msgid "Unmanage Share" msgstr "Partage non-géré" msgid "Update" msgstr "Mettre à jour" msgid "Update Share Network" msgstr "Mettre à jour le partage réseau" msgid "Update Share Type" msgstr "Mise à jour du type de partage" msgid "Updated At" msgstr "Mis à jour à" #, python-format msgid "Updated access for share type \"%s\"." msgstr "Mise à jour des accès pour le type de partage : \"%s\"." #, python-format msgid "Updated share network \"%s\"." msgstr "Partage réseau mis à jour \"%s\"." #, python-format msgid "Updating share \"%s\"" msgstr "Mise à jour du partage \"%s\"" #, python-format msgid "Updating share metadata \"%s\"" msgstr "Mise à jour des métadonnées du partage \"%s\"" #, python-format msgid "Updating share network \"%s\"" msgstr "Mise à jour en cours du partage réseau \"%s\"" msgid "Use snapshot as a source" msgstr "Utiliser un instantané comme source" msgid "User" msgstr "Utilisateur" msgid "Visibility" msgstr "Visibilité" msgid "Writable" msgstr "Accessible en écriture" msgid "key=value pairs per line can be set" msgstr "paires de clé-valeur key=value par ligne peut être mise" manila-ui-2.13.0/manila_ui/locale/id/000077500000000000000000000000001323215354300172435ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/id/LC_MESSAGES/000077500000000000000000000000001323215354300210305ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/id/LC_MESSAGES/django.po000066400000000000000000001162701323215354300226410ustar00rootroot00000000000000# suhartono , 2016. #zanata # Andreas Jaeger , 2017. #zanata # suhartono , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.10.1.dev10\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-08-11 13:00+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-08-13 10:37+0000\n" "Last-Translator: Andreas Jaeger \n" "Language-Team: Indonesian\n" "Language: id\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=1; plural=0\n" #, python-format msgid "%sGiB" msgstr "%sGiB" msgid "(Quota exceeded)" msgstr "(Kuota terlampaui)" msgid "Access Key" msgstr "Access Key (kunci akses)" msgid "Access Level" msgstr "Access Level (tingkat akses)" msgid "Access To" msgstr "Access To (akses ke)" msgid "Access Type" msgstr "Access Type (tipe akses)" msgid "Access to" msgstr "Access to (akses ke)" msgctxt "Current status of share network" msgid "Active" msgstr "Active (aktif)" msgctxt "Current status of share server" msgid "Active" msgstr "Active (aktif)" msgid "Add" msgstr "Add (tambah)" msgid "Add Rule" msgstr "Add Rule (tambah aturan)" msgid "Add Security Service" msgstr "Add Security Service (tambah layanan keamanan)" msgid "Add Share Snapshot Rule" msgstr "Menambahkan Share Snapshot Rule" msgid "Add rule" msgstr "Tambah aturan" msgid "Add security services to share network." msgstr "Menambahkan layanan keamanan untuk jaringan berbagi." msgid "All keys and values must be in range from 1 to 255." msgstr "Semua key dan nilai-nilai harus dalam kisaran 1 sampai 255." msgid "Allow project access to share group type." msgstr "Izinkan akses proyek ke share group type." msgid "Allow project access to share type." msgstr "Membolehkan akses proyek untuk tipe share." msgid "At least one security service must be specified." msgstr "Setidaknya satu layanan keamanan harus ditentukan." msgid "At least one share type must be specified." msgstr "Setidaknya satu share type harus ditentukan." msgid "Availability Zone" msgstr "Availability Zone (zona ketersediaan)" msgid "Availability zone" msgstr "Zona ketersediaan" msgctxt "Current status of replica" msgid "Available" msgstr "Available (tersedia)" msgctxt "Current status of share" msgid "Available" msgstr "Available (tersedia)" msgctxt "Current status of snapshot" msgid "Available" msgstr "Available (tersedia)" msgid "Available projects" msgstr "Proyek yang tersedia" msgid "Available security services" msgstr "Layanan keamanan yang tersedia" msgid "Cancel Migration" msgstr "Cancel Migration (pembatalan migrasi)" msgid "Cancel migration" msgstr "Membatalkan migrasi" msgid "Cancel migration of a Share" msgstr "Pembatalan migrasi share " msgid "Choose a snapshot" msgstr "Pilih snapshot" msgid "Complete Migration" msgstr "Complete Migration (menyelsaikan migrasi)" msgid "Complete migration" msgstr "Migrasi lengkap" msgid "Complete migration of a Share" msgstr "Menyelesaikan migrasi share" msgid "Confirm Migration Cancelling of Share" msgstr "" "Confirm Migration Cancelling of Share (mengkonfirmasi pembatalan migrasi " "share)" msgid "Confirm Migration Completion of Share" msgstr "" "Confirm Migration Completion of Share (mengkonfirmasi penyelesaian migrasi " "share)" msgid "Confirm Obtaining migration progress of Share" msgstr "Konfirmasi perolehan kemajuan migrasi share" msgid "Confirm Password" msgstr "Confirm Password (konfirmasi sandi)" msgid "Confirm Unmanage Share" msgstr "Confirm Unmanage Share (Konfirmasi share yang tidak dikelola)" msgid "Create" msgstr "Create (buat)" msgid "Create Replica" msgstr "Create Replica (buat replika)" msgid "Create Security Service" msgstr "Create Security Service (buat layanan keamanan)" msgid "Create Share" msgstr "Create Share (buat share)" msgid "Create Share Group" msgstr "Membuat Share Group" msgid "Create Share Group Snapshot" msgstr "Membuat Share Group Snapshot" msgid "Create Share Group Type" msgstr "Membuat Share Group Type" msgid "Create Share Network" msgstr "Create Share Network (Buat jaringan berbagi)" msgid "Create Share Snapshot" msgstr "Create Share Snapshot (buat snapshot berbagi)" msgid "Create Share Type" msgstr "Create Share Type (membuat tipe share)" msgid "Create a Share" msgstr "Create a Share (Buat share)" msgid "Created At" msgstr "Created At" msgid "Created at" msgstr "Dibuat di" msgctxt "Current status of replica" msgid "Creating" msgstr "Creating (Pembuatan)" msgctxt "Current status of share" msgid "Creating" msgstr "Creating (pembuatan)" msgctxt "Current status of share server" msgid "Creating" msgstr "Creating (pembuatan)" msgctxt "Current status of snapshot" msgid "Creating" msgstr "Creating (pembuatan)" #, python-format msgid "Creating replica for share \"%s\"." msgstr "Menciptakan replika untuk berbagi \"%s\"." #, python-format msgid "Creating rule for \"%s\"" msgstr "Membuat aturan untuk \"%s\"" #, python-format msgid "Creating share \"%s\"" msgstr "Pembuatan share \"%s\"" #, python-format msgid "Creating share group \"%s\"" msgstr "Membuat share group \"%s\"" #, python-format msgid "Creating share group snapshot \"%s\"." msgstr "Membuat share group snapshot \"%s\"." #, python-format msgid "Creating share snapshot \"%s\"." msgstr "Pembuatan snapshot berbagi \"%s\"." #, python-format msgid "Creating snapshot rule for \"%s\"" msgstr "Membuat aturan snapshot untuk \"%s\"" msgid "Current Size (GiB)" msgstr "Current Size (ukuran saat ini) (GiB)" msgid "DNS IP" msgstr "DNS IP" msgid "Default Quotas" msgstr "Default Quota" msgid "Delete Replica" msgid_plural "Delete Replicas" msgstr[0] "Delete Replica" msgid "Delete Rule" msgid_plural "Delete Rules" msgstr[0] "Delete Rule" msgid "Delete Security Service" msgid_plural "Delete Security Services" msgstr[0] "Delete Security Service" msgid "Delete Share" msgid_plural "Delete Shares" msgstr[0] "Delete Share" msgid "Delete Share Group" msgid_plural "Delete Share Groups" msgstr[0] "Delete Share Group" msgid "Delete Share Group Snapshot" msgid_plural "Delete Share Group Snapshots" msgstr[0] "Delete Share Group Snapshot" msgid "Delete Share Group Type" msgid_plural "Delete Share Group Types" msgstr[0] "Delete Share Group Type" msgid "Delete Share Network" msgid_plural "Delete Share Networks" msgstr[0] "Delete Share Network" msgid "Delete Share Server" msgid_plural "Delete Share Server" msgstr[0] "Delete Share Server" msgid "Delete Share Snapshot" msgid_plural "Delete Share Snapshots" msgstr[0] "Delete Share Snapshot" msgid "Delete Share Snapshot Rule" msgid_plural "Delete Share Snapshot Rules" msgstr[0] "Delete Share Snapshot Rule" msgid "Delete Share Type" msgid_plural "Delete Share Types" msgstr[0] "Delete Share Type" msgid "Delete Snapshot" msgid_plural "Delete Snapshots" msgstr[0] "Delete Snapshot" msgid "Deleted Replica" msgid_plural "Deleted Replicas" msgstr[0] "Deleted Replica" msgid "Deleted Rule" msgid_plural "Deleted Rules" msgstr[0] "Deleted Rule" msgid "Deleted Security Service" msgid_plural "Deleted Security Services" msgstr[0] "Deleted Security Service" msgid "Deleted Share" msgid_plural "Deleted Shares" msgstr[0] "Deleted Share" msgid "Deleted Share Group" msgid_plural "Deleted Share Groups" msgstr[0] "Deleted Share Group" msgid "Deleted Share Group Snapshot" msgid_plural "Deleted Share Group Snapshots" msgstr[0] "Deleted Share Group Snapshot" msgid "Deleted Share Group Type" msgid_plural "Deleted Share Group Types" msgstr[0] "Deleted Share Group Type" msgid "Deleted Share Network" msgid_plural "Deleted Share Networks" msgstr[0] "Deleted Share Network" msgid "Deleted Share Server" msgid_plural "Deleted Share Server" msgstr[0] "Deleted Share Server" msgid "Deleted Share Snapshot" msgid_plural "Deleted Share Snapshots" msgstr[0] "Deleted Share Snapshot" msgid "Deleted Share Snapshot Rule" msgid_plural "Deleted Share Snapshot Rules" msgstr[0] "Deleted Share Snapshot Rule" msgid "Deleted Share Type" msgid_plural "Deleted Share Types" msgstr[0] "Deleted Share Type" msgid "Deleted Snapshot" msgid_plural "Deleted Snapshots" msgstr[0] "Deleted Snapshot" msgctxt "Current status of replica" msgid "Deleting" msgstr "Deleting" msgctxt "Current status of share" msgid "Deleting" msgstr "Deleting (penghapusan)" msgid "Description" msgstr "Deskripsi" msgid "Destination host and pool where share will be migrated to." msgstr "Host tujuan dan ke kolam dimana share akan bermigrasi." msgid "Domain" msgstr "Domain" msgid "Driver handles share servers" msgstr "Driver menangani server share" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "Opsi driver ('volume_id' untuk driver Generic, dll ...)" #, python-format msgid "Duplicated keys '%s'." msgstr "Key duplikat '%s'." msgid "Edit" msgstr "Edit (perbaharui)" msgid "Edit Security Service" msgstr "Edit Security Service (perbaharui layanan keamanan)" msgid "Edit Share" msgstr "Edit Share (perbaharui share)" msgid "Edit Share Metadata" msgstr "Edit Share Metadata (mengedit metadata berbagi)" msgid "Edit Share Network" msgstr "Edit Share Network (mengedit jaringan berbagi)" msgid "Edit Share Snapshot" msgstr "Edit Share Snapshot" msgid "" "Enforces migration of the share snapshots to the destination. If set to " "True, host-assisted migration will not be attempted." msgstr "" "Memberlakukan migrasi dari snapshot share ke tujuan. Jika diatur ke True, " "migrasi host-assisted tidak akan diusahakan." msgid "" "Enforces migration to be nondisruptive. If set to True, host-assisted " "migration will not be attempted." msgstr "" "Memberlakukan migrasi menjadi nondisruptive. Jika diatur ke True, migrasi " "host-assisted tidak akan diusahakan." msgid "" "Enforces migration to keep the share writable while contents are being " "moved. If set to True, host-assisted migration will not be attempted." msgstr "" "Memberlakukan migrasi untuk menjaga share dapat ditulis sementara isinya " "dipindahkan. Jika diatur ke True, migrasi host-assisted tidak akan " "diusahakan." msgid "" "Enforces migration to preserve all file metadata when moving its contents. " "If set to True, host-assisted migration will not be attempted." msgstr "" "Memberlakukan migrasi untuk melestarikan semua metadata file yang ketika " "bergerak isinya. Jika diatur ke True, migrasi host-assisted tidak akan " "diusahakan." msgid "" "Enforces the use of the host-assisted migration approach, which bypasses " "driver optimizations." msgstr "" "Memberlakukan penggunaan pendekatan migrasi host-assisted, yang melewati " "optimasi driver." msgctxt "Current status of replica" msgid "Error" msgstr "Error (kesalahan)" msgctxt "Current status of share" msgid "Error" msgstr "Error (kesalahan)" msgctxt "Current status of share network" msgid "Error" msgstr "Error (kesalahan)" msgctxt "Current status of share server" msgid "Error" msgstr "Error (kesalahan)" msgctxt "Current status of snapshot" msgid "Error" msgstr "Error (kesalahan)" msgid "Expected only pairs of key=value." msgstr "Diharapkan hanya pasang key=value." msgid "Export location" msgstr "Lokasi ekspor" msgid "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgstr "Lokasi ekspor share. misalnya untuk NFS: 1.2.3.4:/path/to/share" msgid "Extend" msgstr "Extend (memperluas)" msgid "Extend Share" msgstr "Extend Share (memperluas share)" #, python-format msgid "Extend share \"%s\"" msgstr "Memperluas share \"%s\"" msgctxt "Current status of share" msgid "Extending Error" msgstr "Extending Error (kesalahan meluas)" msgid "Extra specs" msgstr "Spesifikasi tambahan" msgid "Force Host Assisted Migration" msgstr "Force Host Assisted Migration" msgid "From here you can update share network info. " msgstr "Dari sini Anda dapat memperbarui informasi jaringan berbagi." msgid "From here you can update the default quotas (max limits)." msgstr "Dari sini Anda dapat memperbarui kuota default (batas max)." msgid "Get migration progress" msgstr "Dapatkan kemajuan migrasi" msgid "" "Got improper value for field 'driver_options'. Expected only pairs of " "key=value." msgstr "" "Punya nilai yang tidak benar untuk kolom 'driver_options'. Diharapkan hanya " "pasangan kunci = nilai (key=value)" msgid "Group specs" msgstr "Group specs" msgid "Host" msgstr "Host" msgid "Host of share" msgstr "Host share" msgid "Host to migrate share" msgstr "Host memigrasikan share" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "Host dimana share berada, misalnya: some.host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "IP Version" msgid "Id" msgstr "Id" #, python-format msgid "" "Improper value set to required extra spec " "'spec_driver_handles_share_servers'. Allowed values are %s. Case insensitive." msgstr "" "Pengaturan nilai yang tidak benar untuk spesifikasi tambahan yang " "diperlukan 'spec_driver_handles_share_servers'. Nilai yang diperbolehkan " "adalah %s. Case insensitive." msgctxt "Current status of share server" msgid "In-use" msgstr "In-use" msgctxt "Current status of snapshot" msgid "In-use" msgstr "In-use" msgctxt "Current status of share network" msgid "Inactive" msgstr "Inactive (tidak aktif)" #, python-format msgid "Key '%s' has improper length." msgstr "Key '%s' memiliki panjang yang tidak benar." #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "Key tidak bisa berisi spasi. Lihat string '%s'." #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "Key harus tidak mengandung spasi. Kesalahan dalam '%s'." msgid "Make visible for all" msgstr "Membuat terlihat untuk semuanya" msgid "Manage" msgstr "Manage (mengelola)" msgctxt "Current status of share" msgid "Manage Error" msgstr "Manage Error (mengelola kesalahan)" msgid "Manage Replicas" msgstr "Manage Replicas (mengelola replika)" msgid "Manage Rules" msgstr "Manage Rules (mengelola aturan)" msgid "Manage Share" msgstr "Manage Share (mengelola share)" msgid "Manage Share Group Type Access" msgstr "Mengelola Share Group Type Access" msgid "Manage Share Snapshot Rules" msgstr "Mengelola Share Snapshot Rules" msgid "Manage Share Type Access" msgstr "Manage Share Type Access (mengelola akses tipe share)" msgid "Metadata" msgstr "Metadata" msgid "Migrate Share" msgstr "Migrate Share (migrasi share)" msgid "Migrate a Share" msgstr "Migrate a Share (memigrasi share)" msgctxt "Current status of share" msgid "Migrating" msgstr "Migrating (migrasi)" msgctxt "Current status of share" msgid "Migrating to" msgstr "Bermigrasi ke" #, python-format msgid "Migration of share %(name)s is at %(progress)s percent." msgstr "Migrasi dari share %(name)s berada pada %(progress)s persen." msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "Informasi proyek dan anggota dimodifikasi, tetapi tidak dapat memodifikasi " "kuota proyek." msgid "Name" msgstr "Name (nama)" msgid "Network Type" msgstr "Network Type (tipe jaringan)" msgid "Networks" msgstr "Networks (jaringan)" msgid "Neutron Net" msgstr "Neutron Net" msgid "Neutron Subnet" msgstr "Neutron Subnet (subnet Neutron)" msgid "New Size (GiB)" msgstr "New Size (ukuran baru) (GiB)" msgid "New share network to be set in migrated share" msgstr "Jaringan share baru yang akan ditetapkan di share bermigrasi" msgid "New share type to be set in migrating share" msgstr "Jenis share baru yang akan diatur dalam migrasi share" msgid "New size must be greater than current size." msgstr "" "Ukuran baru (new size) harus lebih besar dari ukuran saat ini (current size)." msgid "No projects found." msgstr "Tidak ada proyek yang ditemukan." msgid "No projects selected." msgstr "Tidak ada proyek yang dipilih." msgid "No security services found." msgstr "Tidak ada layanan keamanan ditemukan." msgid "No security services selected." msgstr "Tidak ada layanan keamanan yang dipilih." msgid "No source, empty share" msgstr "Tidak ada sumber, share kosong" msgid "No source, empty share group" msgstr "Tidak ada sumber, kosong share group" msgid "Nondisruptive" msgstr "Nondisruptive" msgid "Nova Net" msgstr "Nova Net" msgid "Obtain Progress" msgstr "Obtain Progress (mendapatkan kemajuan)" msgid "Obtain migration progress of a Share" msgstr "Mendapatkan kemajuan migrasi share" msgid "Overview" msgstr "Overview (ikhtisar)" msgid "Password" msgstr "Password (sandi)" msgid "Passwords do not match." msgstr "Sandi tidak cocok" msgid "Preserve Metadata" msgstr "Preserve Metadata (pertahankan metadata)" msgid "Preserve Snapshots" msgstr "Preserve Snapshots" msgid "Project" msgstr "Project (proyek)" msgid "Projects with access to share group type" msgstr "Proyek dengan akses keshare group type" msgid "Projects with access to share type" msgstr "Proyek dengan akses untuk tipe share" msgid "Protocol" msgstr "Protocol (protokol)" msgid "Public" msgstr "Public (publik)" msgid "Quota" msgstr "Quota (kuota)" #, python-format msgid "Replica Details: %(replica_display_name)s" msgstr "Rincian replika: %(replica_display_name)s" msgid "Replica State" msgstr "Replica State (keadaan replika)" msgid "Replicas" msgstr "Replicas (replika)" msgid "Reset Replica State" msgstr "Reset Replica State (mengatur ulang keadaan replika)" msgid "Reset Replica Status" msgstr "Reset Replica Status (menyetel ulang status replika)" msgid "Reset Share Group Snapshot Status" msgstr "Reset Share Group Snapshot Status" msgid "Reset Share Group Status" msgstr "Reset Share Group Status" msgid "Reset Status" msgstr "Reset Status" msgid "Reset replica state" msgstr "Mengatur ulang keadaan replika" msgid "Reset replica status" msgstr "Mengatur ulang status replika" msgid "Reset state" msgstr "Reset state (mengatur slang status)" msgid "Reset status" msgstr "Mengatur ulang status" #, python-format msgid "Reseting replica ('%(id)s') state from '%(from)s' to '%(to)s'." msgstr "Atur ulang replika ('%(id)s') keadaan dari '%(from)s' ke '%(to)s'." #, python-format msgid "Reseting replica ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "Atur ulang replika ('%(id)s') status dari '%(from)s' ke'%(to)s'." #, python-format msgid "Reseting share group ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "Menyetel ulang status share group ('%(id)s') dari '%(from)s' ke '%(to)s'." #, python-format msgid "" "Reseting share group snapshot ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "Menyetel ulang status share group snapshot ('%(id)s') dari '%(from)s' ke " "'%(to)s'." msgid "Resync" msgstr "Resync" msgid "Resync Replica" msgstr "Resync Replica" msgid "Resync replica" msgstr "Resync replika" #, python-format msgid "Resync'ing replica '%s'" msgstr "Resync'ing replika '%s'" msgid "Revert Share" msgstr "Kembalikan Berbagi" msgid "Revert Share to a Snapshot" msgstr "Kembalikan Berbagi ke Snapshot" msgid "Revert share to a snapshot" msgstr "Kembalikan berbagi ke snapshot" msgctxt "Current status of share" msgid "Reverting Error" msgstr "Mengembalikan Kesalahan" msgid "Rules" msgstr "Rules (aturan)" msgid "Save Changes" msgstr "Save Changes (simpan perubahan)" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "Rincian layanan keamanan: %(service_display_name)s" msgid "Security Service Overview" msgstr "Security Service Overview" msgid "Security Services" msgstr "Security Services (layanan keamanan)" msgid "Security services within share network" msgstr "layanan keamanan dalam jaringan berbagi" msgid "Segmentation Id" msgstr "Segmentation Id (segmentasi Id)" msgid "Selected projects" msgstr "Proyek yang dipilih" msgid "Selected security services" msgstr "layanan keamanan terpilih" msgid "Server" msgstr "Server" msgid "Set Replica as Active" msgstr "Menetapkan replika menjadi aktif" msgid "Set as Active" msgstr "Set as Active (Atur ke aktif)" msgid "Set maximum quotas for the project." msgstr "Menetapkan kuota maksimum untuk proyek tersebut." #, python-format msgid "Setting replica \"%s\" as active..." msgstr "Pengaturan replika \"%s\" aktif ..." #, python-format msgid "Share \"%(s)s\" has been reverted to \"%(ss)s\" snapshot successfully" msgstr "Berbagi \"%(s)s\" has been reverted to \"%(ss)s\" snapshot berhasil" #, python-format msgid "Share Details: %(share_display_name)s" msgstr "Share Details (rincian share): %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "Rincian share: %(share_name)s" msgid "Share Group" msgstr "Share Group" #, python-format msgid "Share Group Details: %s" msgstr "Share Group Details: %s" msgid "Share Group Name" msgstr "Share Group Name" msgid "Share Group Overview" msgstr "Share Group Overview" msgid "Share Group Snapshot" msgstr "Share Group Snapshot" #, python-format msgid "Share Group Snapshot Details: %(sgs_display_name)s" msgstr "Share Group Snapshot Details: %(sgs_display_name)s" msgid "Share Group Snapshot Overview" msgstr "Share Group Snapshot Overview" msgid "Share Group Snapshots" msgstr "Share Group Snapshots" msgid "Share Group Type" msgstr "Share Group Type" msgid "Share Group Types" msgstr "Share Group Types" msgid "Share Groups" msgstr "Share Groups" msgid "Share ID" msgstr "Share ID" #, python-format msgid "Share Instance Details: %s" msgstr "Share Instance Details (rincian instance berbagai): %s" msgid "Share Instance Overview" msgstr "Share Instance Overview" msgid "Share Instances" msgstr "Share Instances (instance berbagi)" msgid "Share Name" msgstr "Share Name" msgid "Share Network" msgstr "Share Network (jaringan berbagi)" #, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "" "Share Network Details (rincian jaringan berbagi): %(network_display_name)s" msgid "Share Network Info" msgstr "Share Network Info (info jaringan berbagi)" msgid "Share Network Overview" msgstr "Share Network Overview" msgid "Share Networks" msgstr "Share Networks (jaringan berbagi)" msgid "Share Overview" msgstr "Share Overview" msgid "Share Protocol" msgstr "Share Protocol (protokol share)" #, python-format msgid "Share Replicas: %(share_display_name)s" msgstr " Replika berbagi: %(share_display_name)s" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "Share Rules (aturan share): %(share_display_name)s" msgid "Share Server" msgstr "Share Server" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "Share Server Details (rincian server berbagi): %(server_name)s" msgid "Share Server Id" msgstr "Share Server Id" msgid "Share Server Overview" msgstr "Share Server Overview" msgid "Share Servers" msgstr "Share Servers (server berbagi)" msgid "Share Snapshot Name" msgstr "Share Snapshot Name" msgid "Share Snapshot Overview" msgstr "Share Snapshot Overview" msgid "Share Snapshot Rules" msgstr "Share Snapshot Rules" msgid "Share Snapshots" msgstr "Share Snapshots (snapshots bersama)" msgid "Share Snapshots Storage" msgstr "Share Snapshots Storage (penyimpanan snapshot bersama)" msgid "Share Source" msgstr "Share Source (berbagi sumber)" msgid "Share Storage" msgstr "Share Storage (penyimpanan bersama)" msgid "Share Type" msgstr "Share Type (tipe share)" msgid "Share Types" msgstr "Share Types (tipe share)" msgid "Share Types (multiple available)" msgstr "Share Types (multiple available)" msgid "Share Types (one available)" msgstr "Share Types (one available)" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "Share tidak dapat diperpanjang untuk %(req)iGiB karena Anda hanya memiliki " "%(avail)iGiB dari kuota Anda yang tersedia." msgid "Share gigabytes" msgstr "Berbagi gigabyte" msgid "Share name to be assigned" msgstr "Nama share yang akan ditetapkan" #, python-format msgid "Share replica %s has been deleted." msgstr "Berbagi replika %s sudah dihapus." #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "" "Ukuran berbagi (share size) harus sama atau lebih besar dari ukuran snapshot " "(%sGiB)" msgid "Share snapshot gigabytes" msgstr "Berbagi snapshot gigabyte" msgid "Share snapshots" msgstr "Berbagi snapshot" msgid "Share types" msgstr "Share types" msgid "Shares" msgstr "Shares" msgid "Shares Networks" msgstr "Shares Networks (jaringan bersama)" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "Size (ukuran)" msgid "Size (GiB)" msgstr "Size (GiB)" msgid "Snapshot" msgstr "Snapshot" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "Snapshot Details (rincian snapshot) : %(snapshot_display_name)s" #, python-format msgid "Snapshot Rules: %(snapshot_display_name)s" msgstr "Snapshot Rules (aturan snapshot): %(snapshot_display_name)s" msgid "Source" msgstr "Source (sumber)" msgid "Source Share Group Snapshot" msgstr "Source Share Group Snapshot" msgid "Source Type" msgstr "Source Type" msgid "" "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." msgstr "" "Tentukan jaringan share baru untuk berbagi. Jangan menentukan parameter ini " "jika share yang bermigrasi harus dipertahankan dalam jaringan share saat ini." msgid "" "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." msgstr "" "Tentukan tipe share baru untuk berbagi. Tidak menentukan parameter ini jika " "share yang bermigrasi harus dipertahankan dengan tipe share saat ini." msgid "Start migration" msgstr "Start migration (memulai migrasi)" msgid "Status" msgstr "Status" #, python-format msgid "Successfully created security service: %s" msgstr "Berhasil menciptakan layanan keamanan: %s" #, python-format msgid "Successfully created share group type: %s" msgstr "Berhasil membuat share group type: %s" #, python-format msgid "Successfully created share network: %s" msgstr "Berhasil menciptakan jaringan bersama (share) :%s" #, python-format msgid "Successfully created share type: %s" msgstr "Berhasil menciptakan tipe share: %s" #, python-format msgid "Successfully sent the request to cancel migration of share: %s." msgstr "Berhasil mengirim permintaan untuk membatalkan migrasi share: %s." #, python-format msgid "Successfully sent the request to complete migration of share: %s." msgstr "Berhasil dikirim permintaan untuk menyelesaikan migrasi share: %s." #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "Berhasil dikirim permintaan untuk mengelola share: %s" #, python-format msgid "Successfully sent the request to migrate share: %s." msgstr "Berhasil dikirim permintaan memigrasikan share: %s." #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "" "Berhasil mengirimkan permintaan untuk tidak mengelola (unmanaged) share: %s" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "Berhasil diperbarui spesifikasi tambahan untuk tipe share '%s'." #, python-format msgid "Successfully updated group specs for share group type '%s'." msgstr "Spesifikasi grup yang berhasil diperbarui untuk share group type '%s'." #, python-format msgid "Successfully updated security service \"%s\"" msgstr "layanan keamanan berhasil diperbarui \"%s\"" #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "" "Ukuran berbagi (share size) tidak bisa kurang dari ukuran snapshot (%sGiB)" msgid "Type" msgstr "Type (tipe)" msgid "Unable to add rule." msgstr "Tidak dapat menambahkan aturan." msgid "Unable to add snapshot rule." msgstr "Tidak dapat menambahkan aturan snapshot." #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "Tidak dapat membatalkan migrasi share %s saat ini." #, python-format msgid "Unable to complete migration of share %s." msgstr "Tidak dapat menyelesaikan migrasi share %s." msgid "Unable to create security service." msgstr "Tidak dapat membuat layanan keamanan." msgid "Unable to create share group snapshot." msgstr "Tidak dapat membuat share group snapshot." msgid "Unable to create share group type." msgstr "Tidak dapat membuat share group type." msgid "Unable to create share group." msgstr "Tidak dapat membuat share group." msgid "Unable to create share network." msgstr "Tidak dapat membuat jaringan berbagi (share)." msgid "Unable to create share replica." msgstr "Tidak dapat membuat replika share." msgid "Unable to create share snapshot." msgstr "Tidak dapat membuat snapshot berbagi." msgid "Unable to create share type." msgstr "Tidak dapat membuat tipe share" msgid "Unable to create share." msgstr "Tidak dapat membuat share." #, python-format msgid "Unable to create share. %s" msgstr "Tidak dapat membuat share. %s" #, python-format msgid "Unable to delete replica \"%s\"." msgstr "Tidak dapat menghapus replika \"%s\"." #, python-format msgid "Unable to delete rule \"%s\"." msgstr "Tidak dapat menghapus aturan \"%s\"." #, python-format msgid "Unable to delete share \"%s\". " msgstr "Tidak dapat menghapus share \"%s\". " #, python-format msgid "" "Unable to delete share group snapshot \"%s\". One or more share groups " "depend on it." msgstr "" "Tidak dapat menghapus share group snapshot \"%s\". Satu atau lebih share " "group bergantung padanya." #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "" "Tidak dapat menghapus snapshot \"%s\". Satu atau lebih share bergantung " "padanya." #, python-format msgid "Unable to delete snapshot rule \"%s\"." msgstr "Tidak dapat menghapus aturan snapshot \"%s\"." msgid "Unable to extend share." msgstr "Tidak dapat memperluas share." msgid "Unable to get information about share group type access." msgstr "Tidak dapat memperoleh informasi tentang share group type access." msgid "Unable to get information about share type access." msgstr "Tidak dapat mendapatkan informasi tentang akses tipe share." msgid "Unable to get list of projects." msgstr "Tidak dapat mendapatkan daftar proyek." msgid "Unable to get the security services hosts" msgstr "Tidak dapat mendapatkan host layanan keamanan" #, python-format msgid "Unable to get the specified share group '%s' for snapshot creation." msgstr "" "Tidak dapat memperoleh share group yang ditentukan '%s' untuk pembuatan " "snapshot." msgid "Unable to load the specified share group snapshot." msgstr "Tidak dapat memuat share group snapshot yang ditentukan." msgid "Unable to load the specified snapshot." msgstr "Tidak dapat memuat snapshot spesifik." msgid "Unable to manage share" msgstr "Tidak mampu mengelola share" #, python-format msgid "Unable to migrate share %s." msgstr "Tidak dapat bermigrasi share %s." #, python-format msgid "Unable to obtain progress of migration of share %s at this moment." msgstr "Tidak dapat memperoleh kemajuan migrasi share %s saat ini." #, python-format msgid "Unable to reset state of replica '%s'." msgstr "Tidak dapat mengatur ulang keadaan replika '%s'." #, python-format msgid "Unable to reset status of replica '%s'." msgstr "Tidak dapat mengatur ulang status replika '%s'." #, python-format msgid "Unable to reset status of share group '%s'." msgstr "Tidak dapat mengatur ulang status share group '%s'." #, python-format msgid "Unable to reset status of share group snapshot '%s'." msgstr "Tidak dapat mengatur ulang status share group snapshot '%s'." #, python-format msgid "Unable to resync replica '%s'." msgstr "Tidak dapat resync replika '%s'." msgid "Unable to retrieve list of projects." msgstr "Tidak dapat mengambil daftar proyek." msgid "Unable to retrieve quotas." msgstr "Tidak dapat mengambil kuota." #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "Tidak dapat mengambil replika %sdetails." #, python-format msgid "Unable to retrieve replica '%s'." msgstr "Tidak dapat mengambil replika '%s'." #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "Tidak dapat mengambil layanan keamanan '%s' rincian." msgid "Unable to retrieve security services" msgstr "Tidak dapat mengambil layanan keamanan" msgid "Unable to retrieve security_service." msgstr "Tidak dapat mengambil security_service." msgid "Unable to retrieve share details." msgstr "Tidak dapat mengambil rincian saham." #, python-format msgid "Unable to retrieve share group '%s'." msgstr "Tidak dapat mengambil share group '%s'." msgid "Unable to retrieve share group details." msgstr "Tidak dapat mengambil share group details." #, python-format msgid "Unable to retrieve share group snapshot '%s'." msgstr "Tidak dapat mengambil share group snapshot '%s'." msgid "Unable to retrieve share group snapshot details." msgstr "Tidak dapat mengambil share group snapshot details." msgid "Unable to retrieve share group snapshot list." msgstr "Tidak dapat mengambil daftar share group snapshot." msgid "Unable to retrieve share group snapshot." msgstr "Tidak dapat mengambil share group snapshot." msgid "Unable to retrieve share group snapshots." msgstr "Tidak dapat mengambil share group snapshots." msgid "Unable to retrieve share group types." msgstr "Tidak dapat mengambil share group types." msgid "Unable to retrieve share group." msgstr "Tidak dapat mengambil share group." msgid "Unable to retrieve share groups." msgstr "Tidak dapat mengambil share groups." msgid "Unable to retrieve share instance details." msgstr "Tidak dapat mengambil rincian instance berbagi." msgid "Unable to retrieve share instances." msgstr "Tidak dapat mengambil instance berbagi." msgid "Unable to retrieve share limit information." msgstr "Tidak dapat mengambil informasi batas share." msgid "Unable to retrieve share list." msgstr "Tidak dapat mengambil daftar share." msgid "Unable to retrieve share network details." msgstr "Tidak dapat mengambil rincian jaringan berbagi." msgid "Unable to retrieve share network." msgstr "Tidak dapat mengambil jaringan berbagi." msgid "Unable to retrieve share networks" msgstr "Tidak dapat mengambil jaringan berbagi" msgid "Unable to retrieve share replicas." msgstr "Tidak dapat mengambil replika berbagi." msgid "Unable to retrieve share rules." msgstr "Tidak dapat mengambil aturan share." msgid "Unable to retrieve share server details." msgstr "Tidak dapat mengambil rincian server share." msgid "Unable to retrieve share servers" msgstr "Tidak dapat mengambil server berbagi" msgid "Unable to retrieve share snapshot list." msgstr "Tidak dapat mengambil daftar share snapshot." msgid "Unable to retrieve share snapshot rules." msgstr "Tidak dapat mengambil share snapshot rule." msgid "Unable to retrieve share snapshot." msgstr "Tidak dapat mengambil share snapshot." msgid "Unable to retrieve share snapshots list." msgstr "Tidak dapat mengambil daftar snapshot berbagi." msgid "Unable to retrieve share snapshots." msgstr "Tidak dapat mengambil snapshot berbagi." msgid "Unable to retrieve share types." msgstr "Tidak dapat mengambil share types." msgid "Unable to retrieve share." msgstr "Tidak dapat mengambil share." #, python-format msgid "Unable to retrieve share. %s" msgstr "Tidak dapat mengambil share. %s" msgid "Unable to retrieve share_gruop_type." msgstr "Tidak dapat mengambil share_gruop_type." msgid "Unable to retrieve share_type." msgstr "Tidak dapat mengambil share_type." msgid "Unable to retrieve snapshot details." msgstr "Tidak dapat mengambil rincian snapshot." msgid "Unable to retrieve snapshot." msgstr "Tidak dapat mengambil snapshot." msgid "Unable to retrieve volume details." msgstr "" "Unable to retrieve volume details. (tidak dapat mengambil rincian volume)" msgid "Unable to revert share to the snapshot." msgstr "Tidak dapat kembali berbagi dengan snapshot." msgid "Unable to set project quotas." msgstr "Tidak dapat mengatur kuota proyek." #, python-format msgid "Unable to set replica '%s' as active." msgstr "Tidak dapat mengatur replika '%s' aktif." msgid "Unable to unmanage share." msgstr "Tidak dapat tidak mengelola (unmanage) share." #, python-format msgid "Unable to update access for share group type \"%s\"." msgstr "Tidak dapat memperbarui akses untuk share group type \"%s\"." #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "Tidak dapat memperbarui akses untuk tipe share \"%s\"." msgid "Unable to update default quotas." msgstr "Tidak dapat memperbarui kuota default." msgid "Unable to update extra_specs for share type." msgstr "Tidak dapat memperbarui extra_specsuntuk tipe share." msgid "Unable to update group_specs for share group type." msgstr "Tidak dapat memperbarui group_specs untuk share group type." msgid "Unable to update security service." msgstr "Tidak dapat memperbarui layanan keamanan." msgid "Unable to update share group snapshot." msgstr "Tidak dapat memperbarui share group snapshot." msgid "Unable to update share group type." msgstr "Tidak dapat memperbarui share group type." msgid "Unable to update share group." msgstr "Tidak dapat memperbarui share group." msgid "Unable to update share metadata." msgstr "Tidak dapat memperbarui metadata berbagi." #, python-format msgid "Unable to update share network \"%s\"." msgstr "Tidak dapat memperbarui jaringan berbagi \"%s\"." msgid "Unable to update share network." msgstr "Tidak dapat memperbarui jaringan berbagi." msgid "Unable to update share snapshot." msgstr "Tidak dapat memperbarui share snapshot." msgid "Unable to update share type." msgstr "Tidak dapat memperbarui tipe share." msgid "Unable to update share." msgstr "Tidak dapat memperbarui share." msgid "Unknown" msgstr "Unknown (tidak diketahui)" msgid "Unmanage" msgstr "Unmanage (tidak dikelola)" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "Unmanage Error (kesalahan tidak dikelola)" msgid "Unmanage Share" msgstr "Unmanage Share (share tidak terkelola)" msgid "Update" msgstr "Update (perbarui)" msgid "Update Share Group" msgstr "Memperbarui Share Group" msgid "Update Share Group Snapshot" msgstr "Memperbarui Share Group Snapshot" msgid "Update Share Group Type" msgstr "Update Share Group Type" msgid "Update Share Network" msgstr "Update Share Network (memperharui jaringan berbagi)" msgid "Update Share Snapshot" msgstr "Memperbarui Share Snapshot" msgid "Update Share Type" msgstr "Update Share Type (Memperbarui tipe share)" msgid "Update Share group Type" msgstr "Update Share group Type" msgid "Updated At" msgstr "Updated At" #, python-format msgid "Updated access for share group type \"%s\"." msgstr "Akses yang diperbarui untuk share group type \"%s\"." #, python-format msgid "Updated access for share type \"%s\"." msgstr "Diperbaharui akses untuk tipe share \"%s\"." #, python-format msgid "Updated share network \"%s\"." msgstr "Diperbarui jaringan berbagi \"%s\"." #, python-format msgid "Updating share \"%s\"" msgstr "Perbaharui share \"%s\"" #, python-format msgid "Updating share group \"%s\"" msgstr "Memperbarui share group \"%s\"" #, python-format msgid "Updating share group snapshot \"%s\"" msgstr "Memperbarui share group snapshot \"%s\"" #, python-format msgid "Updating share metadata \"%s\"" msgstr "Memperbarui metadata berbagi \"%s\"" #, python-format msgid "Updating share network \"%s\"" msgstr "Memperbarui jaringan berbagi \"%s\"" #, python-format msgid "Updating share snapshot \"%s\"" msgstr "Memperbarui share snapshot \"%s\"" msgid "Use share group snapshot as a source" msgstr "Menggunakan share group snapshot sebagai sumber" msgid "Use snapshot as a source" msgstr "Gunakan snapshot sebagai sumber" msgid "User" msgstr "User (pengguna)" msgid "Visibility" msgstr "Visibility (keterlihatan)" msgid "Writable" msgstr "Writable (dapat ditulis)" msgid "key=value pairs per line can be set" msgstr "Pasasngan key=value per baris dapat diatur" manila-ui-2.13.0/manila_ui/locale/ja/000077500000000000000000000000001323215354300172415ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/ja/LC_MESSAGES/000077500000000000000000000000001323215354300210265ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/ja/LC_MESSAGES/django.po000066400000000000000000000544321323215354300226400ustar00rootroot00000000000000# Akihiro Motoki , 2016. #zanata # Shu Muto , 2016. #zanata # Kyohei Moriyama , 2017. #zanata # Yuko Katabami , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.10.2.dev14\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-13 12:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-09-14 05:37+0000\n" "Last-Translator: Kyohei Moriyama \n" "Language-Team: Japanese\n" "Language: ja\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=1; plural=0\n" #, python-format msgid "%sGiB" msgstr "%sGiB" msgid "(Quota exceeded)" msgstr "(クォータを超過しました)" msgid "Access Level" msgstr "アクセスレベル" msgid "Access To" msgstr "接続先" msgid "Access Type" msgstr "アクセス種別" msgid "Access to" msgstr "接続先" msgctxt "Current status of share network" msgid "Active" msgstr "稼働中" msgctxt "Current status of share server" msgid "Active" msgstr "稼働中" msgid "Add" msgstr "追加" msgid "Add Rule" msgstr "ルールの追加" msgid "Add Security Service" msgstr "セキュリティーサービスの追加" msgid "Add rule" msgstr "ルールの追加" msgid "Add security services to share network." msgstr "ファイル共有ネットワークにセキュリティーサービスを追加します。" msgid "All keys and values must be in range from 1 to 255." msgstr "すべてのキーと値は 1 から 255 の範囲でなければいけません。" msgid "Allow project access to share type." msgstr "ファイル共有種別への接続をプロジェクトに許可します。" msgid "At least one security service must be specified." msgstr "少なくとも 1 つのセキュリティサービスを指定する必要があります。" msgid "Availability Zone" msgstr "アベイラビリティーゾーン" msgctxt "Current status of share" msgid "Available" msgstr "利用可能" msgctxt "Current status of snapshot" msgid "Available" msgstr "利用可能" msgid "Available projects" msgstr "使用可能なプロジェクト" msgid "Available security services" msgstr "利用可能なセキュリティーサービス" msgid "Cancel Migration" msgstr "移行の取り消し" msgid "Cancel migration of a Share" msgstr "ファイル共有の移行の取り消し" msgid "Choose a snapshot" msgstr "スナップショットを選択してください" msgid "Confirm Migration Cancelling of Share" msgstr "ファイル共有の移行の確認" msgid "Confirm Password" msgstr "パスワード(確認)" msgid "Confirm Unmanage Share" msgstr "ファイル共有の管理解除の確認" msgid "Create" msgstr "作成" msgid "Create Security Service" msgstr "セキュリティーサービスの作成" msgid "Create Share" msgstr "ファイル共有の作成" #, fuzzy msgid "Create Share Network" msgstr "ファイル共有ネットワークの作成" msgid "Create Share Snapshot" msgstr "ファイル共有スナップショットの作成" msgid "Create Share Type" msgstr "ファイル共有種別の作成" msgid "Create a Share" msgstr "ファイル共有の作成" msgctxt "Current status of share" msgid "Creating" msgstr "作成中" msgctxt "Current status of share server" msgid "Creating" msgstr "作成中" msgctxt "Current status of snapshot" msgid "Creating" msgstr "作成中" #, python-format msgid "Creating rule for \"%s\"" msgstr "「%s」のルールを作成中" #, python-format msgid "Creating share \"%s\"" msgstr "ファイル共有「%s」を作成中" #, python-format msgid "Creating share snapshot \"%s\"." msgstr "ファイル共有スナップショット \"%s\" を作成しています。" msgid "Current Size (GiB)" msgstr "現在のサイズ (GiB)" msgid "DNS IP" msgstr "DNS IP" msgid "Delete Security Service" msgid_plural "Delete Security Services" msgstr[0] "セキュリティサービスを削除します" msgid "Delete Share Group Snapshot" msgid_plural "Delete Share Group Snapshots" msgstr[0] "共有グループスナップショットを削除する" msgid "Deleted Security Service" msgid_plural "Deleted Security Services" msgstr[0] "セキュリティサービスを削除しました" msgctxt "Current status of share" msgid "Deleting" msgstr "削除中" msgid "Description" msgstr "説明" msgid "Domain" msgstr "ドメイン" msgid "Driver handles share servers" msgstr "ファイル共有サーバーを処理するドライバー" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "ドライバーオプション(Genericドライバーの「volume_id」、など)" #, python-format msgid "Duplicated keys '%s'." msgstr "キー「%s」が重複しています" msgid "Edit" msgstr "編集" msgid "Edit Security Service" msgstr "セキュリティーサービスの編集" msgid "Edit Share" msgstr "ファイル共有の編集" msgid "Edit Share Metadata" msgstr "ファイル共有のメタデータの編集" #, fuzzy msgid "Edit Share Network" msgstr "ファイル共有ネットワークの編集" msgctxt "Current status of share" msgid "Error" msgstr "エラー" msgctxt "Current status of share network" msgid "Error" msgstr "エラー" msgctxt "Current status of share server" msgid "Error" msgstr "エラー" msgctxt "Current status of snapshot" msgid "Error" msgstr "エラー" msgid "Expected only pairs of key=value." msgstr "キー=値のペアのみ設定できます。" msgid "Export location" msgstr "エクスポート場所" msgid "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgstr "ファイル共有のエクスポート場所。NFSの例: 1.2.3.4:/path/to/share" msgid "Extend" msgstr "拡張" msgid "Extend Share" msgstr "ファイル共有の拡張" #, python-format msgid "Extend share \"%s\"" msgstr "ファイル共有「%s」の拡張" msgctxt "Current status of share" msgid "Extending Error" msgstr "拡張中のエラー" msgid "Extra specs" msgstr "追加スペック" msgid "From here you can update share network info. " msgstr "ここから、ファイル共有ネットワーク情報を更新できます。" msgid "From here you can update the default quotas (max limits)." msgstr "ここから標準のクォータ (上限) を更新できます。" msgid "" "Got improper value for field 'driver_options'. Expected only pairs of " "key=value." msgstr "" "フィールド「driver_options」に不適切な値があります。キー=値のペアのみ設定でき" "ます。" msgid "Host" msgstr "ホスト" msgid "Host of share" msgstr "ファイル共有のホスト" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "ファイル共有が配置されるホスト。例: some.host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "IP バージョン" msgid "Id" msgstr "ID" #, python-format msgid "" "Improper value set to required extra spec " "'spec_driver_handles_share_servers'. Allowed values are %s. Case insensitive." msgstr "" "必須の追加のスペック「spec_driver_handles_share_servers」に不適切な値が設定さ" "れました。%s が使用できます。 大文字小文字を区別しません。" msgctxt "Current status of share server" msgid "In-use" msgstr "使用中" msgctxt "Current status of snapshot" msgid "In-use" msgstr "使用中" msgctxt "Current status of share network" msgid "Inactive" msgstr "非稼働" #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "キーに空白は使えません。「%s」を確認してください。" #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "キーに空白は使えません。「%s」にエラーがあります。" msgid "Make visible for all" msgstr "全ユーザーに公開する" msgid "Manage" msgstr "管理" msgctxt "Current status of share" msgid "Manage Error" msgstr "管理エラー" msgid "Manage Rules" msgstr "ルールの管理" msgid "Manage Share" msgstr "ファイル共有の管理" msgid "Manage Share Type Access" msgstr "ファイル共有種別の接続の管理" msgid "Metadata" msgstr "メタデータ" msgid "Migrate a Share" msgstr "ファイル共有の移行" msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "プロジェクトの情報とメンバーを変更しましたが、プロジェクトのクォータを変更で" "きません。" msgid "Name" msgstr "名前" msgid "Network Type" msgstr "ネットワーク種別" msgid "Networks" msgstr "ネットワーク" msgid "Neutron Net" msgstr "Neutron ネットワーク" msgid "Neutron Subnet" msgstr "Neutron サブネット" msgid "New Size (GiB)" msgstr "新しいサイズ (GiB)" msgid "New size must be greater than current size." msgstr "変更後のサイズは現在のサイズより大きくなければいけません。" msgid "No projects found." msgstr "プロジェクトが見つかりませんでした。" msgid "No projects selected." msgstr "どのプロジェクトも選択されていません。" msgid "No security services found." msgstr "セキュリティサービスがありません。" msgid "No security services selected." msgstr "セキュリティサービスが選択されていません。" msgid "No source, empty share" msgstr "ソースの指定なし (空のファイル共有)" msgid "Nova Net" msgstr "Nova ネットワーク" msgid "Overview" msgstr "概要" msgid "Password" msgstr "パスワード" msgid "Passwords do not match." msgstr "パスワードが一致しません。" msgid "Project" msgstr "プロジェクト" msgid "Projects with access to share type" msgstr "ファイル共有種別に接続するプロジェクト" msgid "Protocol" msgstr "プロトコル" msgid "Public" msgstr "パブリック" msgid "Quota" msgstr "クォータ" #, python-format msgid "" "Reseting share group snapshot ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "共有グループスナップショット ('%(id)s')状態を '%(from)s' から '%(to)s'へリ" "セットします" msgid "Rules" msgstr "ルール" msgid "Save Changes" msgstr "変更の保存" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "セキュリティサービスの詳細: %(service_display_name)s" msgid "Security Service Overview" msgstr "セキュリティサービス概要" msgid "Security Services" msgstr "セキュリティーサービス" msgid "Security services within share network" msgstr "ファイル共有ネットワーク内のセキュリティーサービス" msgid "Segmentation Id" msgstr "セグメント ID" msgid "Selected projects" msgstr "選択済みのプロジェクト" msgid "Selected security services" msgstr "選択済みのセキュリティーサービス" msgid "Server" msgstr "サーバー" msgid "Set maximum quotas for the project." msgstr "このプロジェクトの最大クォータを設定します。" #, python-format msgid "Share Details: %(share_display_name)s" msgstr "ファイル共有の詳細: %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "ファイル共有の詳細: %(share_name)s" msgid "Share Group Snapshots" msgstr "共有グループスナップショット" msgid "Share ID" msgstr "ファイル共有 ID" #, python-format msgid "Share Instance Details: %s" msgstr "ファイル共有インスタンスの詳細: %s" msgid "Share Instances" msgstr "ファイル共有インスタンス" msgid "Share Name" msgstr "ファイル共有名" msgid "Share Network" msgstr "ファイル共有ネットワーク" #, fuzzy, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "ファイル共有ネットワークの詳細: %(network_display_name)s" #, fuzzy msgid "Share Network Info" msgstr "ファイル共有ネットワーク情報" msgid "Share Networks" msgstr "ファイル共有ネットワーク" msgid "Share Protocol" msgstr "ファイル共有プロトコル" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "ファイル共有ルール: %(share_display_name)s" msgid "Share Server" msgstr "ファイル共有サーバー" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "ファイル共有サーバーの詳細: %(server_name)s" msgid "Share Server Id" msgstr "ファイル共有サーバー ID" msgid "Share Servers" msgstr "ファイル共有サーバー" msgid "Share Snapshots" msgstr "ファイル共有のスナップショット" msgid "Share Snapshots Storage" msgstr "ファイル共有のスナップショットストレージ" msgid "Share Source" msgstr "ファイル共有ソース" msgid "Share Storage" msgstr "ファイル共有のストレージ" msgid "Share Type" msgstr "ファイル共有種別" msgid "Share Types" msgstr "ファイル共有種別" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "ファイル共有を %(req)iGiB に拡張することができません。利用できるクォータは " "%(avail)iGiB しかありません。" msgid "Share name to be assigned" msgstr "割り当てらるファイル共有名" #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "" "ファイル共有サイズはスナップショットサイズ (%sGiB) 以上でなければいけません。" msgid "Shares" msgstr "ファイル共有" #, fuzzy msgid "Shares Networks" msgstr "ファイル共有ネットワーク" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "サイズ" msgid "Size (GiB)" msgstr "サイズ (GiB)" msgid "Snapshot" msgstr "スナップショット" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "スナップショットの詳細: %(snapshot_display_name)s" msgid "Source" msgstr "ソース" msgid "Status" msgstr "ステータス" #, python-format msgid "Successfully created security service: %s" msgstr "セキュリティーサービス %s を正常に作成しました。" #, python-format msgid "Successfully created share network: %s" msgstr "ファイル共有ネットワークが正常に作成されました: %s" #, python-format msgid "Successfully created share type: %s" msgstr "ファイル共有種別が正常に作成されました: %s" #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "ファイル共有 %s の管理要求は正常に行われました。" #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "ファイル共有 %s の管理解除要求は正常に行われました。" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "ファイル共有種別「%s」の追加スペックの更新に成功しました。" #, python-format msgid "Successfully updated security service \"%s\"" msgstr "セキュリティーサービス %s を正常に更新しました" #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "" "ファイル共有サイズはスナップショットサイズ (%sGiB) 未満にはできません。" msgid "Type" msgstr "種別" msgid "Unable to add rule." msgstr "ルールを追加できません。" msgid "Unable to create security service." msgstr "セキュリティーサービスを作成できません。" msgid "Unable to create share network." msgstr "ファイル共有ネットワークを作成できません。" msgid "Unable to create share snapshot." msgstr "ファイル共有スナップショットを作成できません。" msgid "Unable to create share type." msgstr "ファイル共有種別を作成できません。" msgid "Unable to create share." msgstr "ファイル共有を作成できません。" #, python-format msgid "Unable to delete rule \"%s\"." msgstr "ルール「%s」を削除できません。" #, python-format msgid "Unable to delete share \"%s\". " msgstr "ファイル共有 「%s」を削除できません。" #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "" "スナップショット「%s」は削除できません。 1 つ以上のファイル共有が依存してい" "ます。" msgid "Unable to extend share." msgstr "ファイル共有を拡張できません。" msgid "Unable to get information about share type access." msgstr "ファイル共有種別の接続に関する情報を取得できません。" msgid "Unable to get list of projects." msgstr "プロジェクトの一覧を取得できません" msgid "Unable to get the security services hosts" msgstr "セキュリティーサービスのホストを取得できません。" msgid "Unable to load the specified snapshot." msgstr "指定されたスナップショットを読み込めません。" msgid "Unable to manage share" msgstr "ファイル共有を管理できません。" #, python-format msgid "Unable to reset status of share group snapshot '%s'." msgstr "共有グループスナップショット'%s'の状態をリセットできません" msgid "Unable to retrieve list of projects." msgstr "プロジェクトの一覧を取得できません。" msgid "Unable to retrieve quotas." msgstr "クォータを取得できません。" #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "セキュリティーサービス「%s」の詳細を取得できません。" msgid "Unable to retrieve security services" msgstr "セキュリティーサービスの一覧を取得できません" msgid "Unable to retrieve security_service." msgstr "セキュリティサービスを取得できません。" msgid "Unable to retrieve share details." msgstr "ファイル共有の詳細を取得できません。" msgid "Unable to retrieve share instance details." msgstr "ファイル共有インスタンスの詳細を取得できません。" msgid "Unable to retrieve share instances." msgstr "ファイル共有インスタンスの一覧を取得できません" msgid "Unable to retrieve share limit information." msgstr "ファイル共有のリソース上限情報を取得できません。" msgid "Unable to retrieve share list." msgstr "ファイル共有の一覧を取得できません。" #, fuzzy msgid "Unable to retrieve share network details." msgstr "ファイル共有ネットワークの詳細を取得できません。" msgid "Unable to retrieve share network." msgstr "ファイル共有ネットワークを取得できません。" msgid "Unable to retrieve share networks" msgstr "ファイル共有ネットワークの一覧を取得できません" msgid "Unable to retrieve share rules." msgstr "ファイル共有ルールの一覧を取得できません。" msgid "Unable to retrieve share server details." msgstr "ファイル共有サーバーの詳細を取得できません。" msgid "Unable to retrieve share servers" msgstr "ファイル共有サーバーの一覧を取得できません" msgid "Unable to retrieve share snapshots list." msgstr "ファイル共有スナップショットの一覧を取得できません。" msgid "Unable to retrieve share snapshots." msgstr "ファイル共有スナップショットの一覧を取得できません。" msgid "Unable to retrieve share." msgstr "ファイル共有を取得できません。" msgid "Unable to retrieve share_type." msgstr "ファイル共有種別を取得できません。" msgid "Unable to retrieve snapshot details." msgstr "スナップショットの詳細を取得できません。" msgid "Unable to retrieve snapshot." msgstr "スナップショットを取得できません。" msgid "Unable to retrieve volume details." msgstr "ボリュームの詳細を取得できません。" msgid "Unable to set project quotas." msgstr "プロジェクトのクォータを設定できません。" msgid "Unable to unmanage share." msgstr "ファイル共有の管理を解除できません。" #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "ファイル共有種別「%s」の接続を更新できません。" msgid "Unable to update default quotas." msgstr "標準のクォータを更新できません。" msgid "Unable to update extra_specs for share type." msgstr "ファイル共有種別の追加スペックを更新できません。" msgid "Unable to update security service." msgstr "セキュリティーサービスを更新できません。" msgid "Unable to update share metadata." msgstr "ファイル共有のメタデータを更新できません。" #, python-format msgid "Unable to update share network \"%s\"." msgstr "ファイル共有ネットワーク「%s」を更新できません。" msgid "Unable to update share network." msgstr "ファイル共有ネットワークを更新できません。" msgid "Unable to update share type." msgstr "ファイル共有種別を更新できません。" msgid "Unable to update share." msgstr "ファイル共有を更新できません。" msgid "Unknown" msgstr "不明" msgid "Unmanage" msgstr "管理解除" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "管理解除エラー" msgid "Unmanage Share" msgstr "ファイル共有の管理解除" msgid "Update" msgstr "更新" #, fuzzy msgid "Update Share Network" msgstr "ファイル共有ネットワークの更新" msgid "Update Share Type" msgstr "ファイル共有種別の更新" #, python-format msgid "Updated access for share type \"%s\"." msgstr "ファイル共有種別「%s」の接続を更新しました。" #, python-format msgid "Updated share network \"%s\"." msgstr "ファイル共有ネットワーク「%s」を更新しました。" #, python-format msgid "Updating share \"%s\"" msgstr "ファイル共有 \"%s\" を更新中" #, python-format msgid "Updating share metadata \"%s\"" msgstr "ファイル共有のメタデータ \"%s\" を更新中" #, python-format msgid "Updating share network \"%s\"" msgstr "ファイル共有ネットワーク「%s」を更新しています" msgid "Use snapshot as a source" msgstr "スナップショットをソースとして使用する" msgid "User" msgstr "ユーザー" msgid "Visibility" msgstr "公開範囲" msgid "key=value pairs per line can be set" msgstr "「キー=値」のペアを行ごとに設定できます" manila-ui-2.13.0/manila_ui/locale/ko_KR/000077500000000000000000000000001323215354300176545ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/ko_KR/LC_MESSAGES/000077500000000000000000000000001323215354300214415ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/ko_KR/LC_MESSAGES/django.po000066400000000000000000000664051323215354300232560ustar00rootroot00000000000000# Eunseop Shin , 2016. #zanata # Ian Y. Choi , 2016. #zanata # Sungjin Kang , 2017. #zanata # minwook-shin , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.10.1.dev12\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-08-15 16:55+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-08-16 07:50+0000\n" "Last-Translator: minwook-shin \n" "Language-Team: Korean (South Korea)\n" "Language: ko-KR\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=1; plural=0\n" #, python-format msgid "%sGiB" msgstr "%sGiB" msgid "(Quota exceeded)" msgstr "(Quota 초과)" msgid "Access Key" msgstr "접근 키" msgid "Access Level" msgstr "엑세스 레벨" msgid "Access To" msgstr "에 엑세스" msgid "Access Type" msgstr "엑세스 타입" msgid "Access to" msgstr "에 접근" msgctxt "Current status of share network" msgid "Active" msgstr "활성화됨" msgctxt "Current status of share server" msgid "Active" msgstr "활성화됨" msgid "Add" msgstr "추가" msgid "Add Rule" msgstr "규칙 추가" msgid "Add Security Service" msgstr "보안 서비스 추가" msgid "Add rule" msgstr "규칙 추가" msgid "Add security services to share network." msgstr "공유 네트워크에 보안 서비스 추가." msgid "All keys and values must be in range from 1 to 255." msgstr "모든 키와 값은 1 에서 255까지의 범위에 있어야 합니다." msgid "Allow project access to share type." msgstr "프로젝트가 공유 유형에 엑세스하도록 허용합니다." msgid "At least one security service must be specified." msgstr "최소한 하나의 보안 서비스를 지정해야 합니다." msgid "Availability Zone" msgstr "가용 구역" msgid "Availability zone" msgstr "가용성 존" msgctxt "Current status of replica" msgid "Available" msgstr "사용 가능" msgctxt "Current status of share" msgid "Available" msgstr "사용 가능" msgctxt "Current status of snapshot" msgid "Available" msgstr "사용 가능" msgid "Available projects" msgstr "사용 가능한 프로젝트" msgid "Available security services" msgstr "이용가능한 보안 서비스" msgid "Cancel Migration" msgstr "마이그레이션 취소" msgid "Cancel migration" msgstr "마이그레이션 취소" msgid "Cancel migration of a Share" msgstr "공유에 대한 마이그레이션 취소" msgid "Choose a snapshot" msgstr "스냅샷 선택" msgid "Complete Migration" msgstr "마이그레이션 완료" msgid "Complete migration" msgstr "마이그레이션 완료" msgid "Complete migration of a Share" msgstr "공유에 대한 마이그레이션 완료" msgid "Confirm Migration Cancelling of Share" msgstr "공유에 대한 마이그레이션 취소 확인" msgid "Confirm Migration Completion of Share" msgstr "공유에 대한 마이그레이션 완료 확인" msgid "Confirm Obtaining migration progress of Share" msgstr "공유에 대한 마이그레이션 진행사항을 가져오는 것에 대해 확인합니다" msgid "Confirm Password" msgstr "비밀번호 확인" msgid "Confirm Unmanage Share" msgstr "공유 관리 해제 확인" msgid "Create" msgstr "생성" msgid "Create Replica" msgstr "레프리카 생성" msgid "Create Security Service" msgstr "보안 서비스 생성" msgid "Create Share" msgstr "공유 생성" msgid "Create Share Group Type" msgstr "공유 그룹 타입 생성" msgid "Create Share Network" msgstr "공유 네트워크 생성" msgid "Create Share Snapshot" msgstr "공유 스냅샷 생성" msgid "Create Share Type" msgstr "공유 유형 생성" msgid "Create a Share" msgstr "공유 생성" msgid "Created At" msgstr "생성 시점" msgid "Created at" msgstr "생성 시점" msgctxt "Current status of replica" msgid "Creating" msgstr "생성 중" msgctxt "Current status of share" msgid "Creating" msgstr "생성 중" msgctxt "Current status of share server" msgid "Creating" msgstr "생성 중" msgctxt "Current status of snapshot" msgid "Creating" msgstr "생성 중" #, python-format msgid "Creating replica for share \"%s\"." msgstr "공유 \"%s\"를 위한 레프리카를 생성하는 중. " #, python-format msgid "Creating rule for \"%s\"" msgstr "\"%s\"를 위한 생성 규칙" #, python-format msgid "Creating share \"%s\"" msgstr "공유 \"%s\"를 생성하는중" #, python-format msgid "Creating share snapshot \"%s\"." msgstr "공유 스냅샷 \"%s\" 생성" msgid "Current Size (GiB)" msgstr "현재 크기 (GiB)" msgid "DNS IP" msgstr "DNS IP" msgid "Delete Rule" msgid_plural "Delete Rules" msgstr[0] "규칙 삭제" msgid "Delete Security Service" msgid_plural "Delete Security Services" msgstr[0] "보안 서비스 삭제" msgid "Delete Share Group" msgid_plural "Delete Share Groups" msgstr[0] "공유 그룹 삭제" msgid "Delete Share Group Snapshot" msgid_plural "Delete Share Group Snapshots" msgstr[0] "공유 그룹 스냅샷 삭제" msgid "Deleted Rule" msgid_plural "Deleted Rules" msgstr[0] "규칙 삭제됨" msgid "Deleted Security Service" msgid_plural "Deleted Security Services" msgstr[0] "보안 서비스 삭제됨" msgid "Deleted Share Group" msgid_plural "Deleted Share Groups" msgstr[0] "공유 그룹 삭제됨" msgid "Deleted Share Group Snapshot" msgid_plural "Deleted Share Group Snapshots" msgstr[0] "공유 그룹 스냅샷 삭제됨" msgctxt "Current status of replica" msgid "Deleting" msgstr "Deleting" msgctxt "Current status of share" msgid "Deleting" msgstr "삭제 중" msgid "Description" msgstr "설명" msgid "Domain" msgstr "도메인" msgid "Driver handles share servers" msgstr "드라이버는 공유 서버를 다룹니다" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "드라이버 옵션 (Generic 드라이브에 대한 'volume_id' 등)" #, python-format msgid "Duplicated keys '%s'." msgstr "중복된 키 '%s'." msgid "Edit" msgstr "편집" msgid "Edit Security Service" msgstr "보안 서비스 편집" msgid "Edit Share" msgstr "공유편집" msgid "Edit Share Metadata" msgstr "공유 메타데이터 편집" msgid "Edit Share Network" msgstr "공유 네트워크 편집" msgctxt "Current status of replica" msgid "Error" msgstr "에러" msgctxt "Current status of share" msgid "Error" msgstr "에러" msgctxt "Current status of share network" msgid "Error" msgstr "에러" msgctxt "Current status of share server" msgid "Error" msgstr "오류" msgctxt "Current status of snapshot" msgid "Error" msgstr "오류" msgid "Expected only pairs of key=value." msgstr "key=value 쌍만을 기대합니다." msgid "Export location" msgstr "위치 내보내기" msgid "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgstr "공유에 대한 내보내기 위치. NFS 예시: 1.2.3.4:/path/to/share" msgid "Extend" msgstr "확장" msgid "Extend Share" msgstr "공유 확장" #, python-format msgid "Extend share \"%s\"" msgstr "공유 \"%s\" 확장" msgctxt "Current status of share" msgid "Extending Error" msgstr "확장중 에러" msgid "Extra specs" msgstr "부가 스펙" msgid "Force Host Assisted Migration" msgstr "호스트 지원 마이그레이션 강제" msgid "From here you can update share network info. " msgstr "여기서 공유 네트워크 정보를 업데이트 할 수 있습니다." msgid "From here you can update the default quotas (max limits)." msgstr "여기서 기본 할당량를 업데이트 할 수 있습니다 (최대 한계)." msgid "Get migration progress" msgstr "마이그레이션 진행사항 가져오기" msgid "" "Got improper value for field 'driver_options'. Expected only pairs of " "key=value." msgstr "" "'driver_options' 필드에 대해 적절하지 않은 값을 얻었습니다. key=value 쌍만을 " "기대합니다." msgid "Group specs" msgstr "그룹 사양" msgid "Host" msgstr "호스트" msgid "Host of share" msgstr "공유 호스트" msgid "Host to migrate share" msgstr "공유를 마이그레이션할 호스트" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "공유가 위치할 호스트, 예시: some.host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "IP 버전" msgid "Id" msgstr "Id" #, python-format msgid "" "Improper value set to required extra spec " "'spec_driver_handles_share_servers'. Allowed values are %s. Case insensitive." msgstr "" "필요한 부가 스펙 'spec_driver_handles_share_servers' 을 설정하는 데 적절하지 " "않은 값입니다. 허용 값은 %s 로 대소문자를 구별하지 않습니다." msgctxt "Current status of share server" msgid "In-use" msgstr "사용 중" msgctxt "Current status of snapshot" msgid "In-use" msgstr "사용 중" msgctxt "Current status of share network" msgid "Inactive" msgstr "비활성화 됨" #, python-format msgid "Key '%s' has improper length." msgstr "키 '%s' 길이가 적절하지 않습니다." #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "키는 공백을 포함할 수 없습니다. 문자열 '%s' 를 살펴 봅니다." #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "키는 공백을 포함하지 않아야 합니다. '%s' 에 오류가 있습니다." msgid "Make visible for all" msgstr "모든 것을 보이게 합니다." msgid "Manage" msgstr "관리" msgctxt "Current status of share" msgid "Manage Error" msgstr "관리 오류" msgid "Manage Replicas" msgstr "복제본 관리" msgid "Manage Rules" msgstr "관리 규칙" msgid "Manage Share" msgstr "공유 관리" msgid "Manage Share Type Access" msgstr "공유 유형 액세스 관리" msgid "Metadata" msgstr "메타데이터" msgid "Migrate Share" msgstr "공유 마이그레이션" msgid "Migrate a Share" msgstr "공유 마이그레이션" msgctxt "Current status of share" msgid "Migrating" msgstr "이전 중" msgctxt "Current status of share" msgid "Migrating to" msgstr "로 이전 중" #, python-format msgid "Migration of share %(name)s is at %(progress)s percent." msgstr "공유 %(name)s 에 대한 마이그레이션이 현재 %(progress)s 퍼센트입니다." msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "프로젝트 정보와 멤버들은 수정하였으나, 프로젝트 quota는 수정하지 못 했습니다." msgid "Name" msgstr "이름" msgid "Network Type" msgstr "네트워크 유형" msgid "Networks" msgstr "네트워크" msgid "Neutron Net" msgstr "Neutron Net" msgid "Neutron Subnet" msgstr "Neutron 서브넷" msgid "New Size (GiB)" msgstr "새 크기 (GiB)" msgid "New share network to be set in migrated share" msgstr "마이그레이션된 공유에서 설정될 새로운 공유 네트워크" msgid "New share type to be set in migrating share" msgstr "마이그레이션된 공유에서 설정될 새로운 공유 네트워크 타입" msgid "New size must be greater than current size." msgstr "새로 정하는 크기는 현재 크기보다 커야합니다." msgid "No projects found." msgstr "프로젝트를 찾을 수 없습니다." msgid "No projects selected." msgstr "선택한 프로젝트가 없습니다." msgid "No security services found." msgstr "보안 서비스를 찾을 수 없습니다." msgid "No security services selected." msgstr "보안 서비스가 선택되지 않았습니다." msgid "No source, empty share" msgstr "소스가 없음, 빈 공유" msgid "Nova Net" msgstr "Nova Net" msgid "Obtain Progress" msgstr "진행사항 가져오기" msgid "Obtain migration progress of a Share" msgstr "공유에 대한 마이그레이션 진행사항 가져오기" msgid "Overview" msgstr "개요" msgid "Password" msgstr "암호" msgid "Passwords do not match." msgstr "비밀번호가 일치하지 않습니다." msgid "Preserve Metadata" msgstr "메타데이터 보존" msgid "Project" msgstr "프로젝트" msgid "Projects with access to share type" msgstr "공유 유형에 대한 엑세스를 포함하는 프로젝트" msgid "Protocol" msgstr "프로토콜" msgid "Public" msgstr "공용" msgid "Quota" msgstr "Quota" #, python-format msgid "Replica Details: %(replica_display_name)s" msgstr "레프리카 상세정보: %(replica_display_name)s" msgid "Replica State" msgstr "Replica 상태" msgid "Replicas" msgstr "Replicas" msgid "Reset Replica State" msgstr "Replica State 리셋" msgid "Reset Replica Status" msgstr "Replica Status 리셋" msgid "Reset Share Group Snapshot Status" msgstr "공유 그룹 스냅샷 상태 재설정" msgid "Reset Status" msgstr "상태 재설정" msgid "Reset replica state" msgstr "replica state 리셋" msgid "Reset replica status" msgstr "replica status 리셋" msgid "Reset state" msgstr "state 리셋" msgid "Reset status" msgstr "리셋 status" #, python-format msgid "Reseting replica ('%(id)s') state from '%(from)s' to '%(to)s'." msgstr "replica ('%(id)s') state를 '%(from)s' 에서 '%(to)s' 로 리셋." #, python-format msgid "Reseting replica ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "replica ('%(id)s') status를 '%(from)s' 에서 '%(to)s' 로 리셋." msgid "Resync" msgstr "재동기화" msgid "Resync Replica" msgstr "Replica 재동기화" msgid "Resync replica" msgstr "replica 재동기화" #, python-format msgid "Resync'ing replica '%s'" msgstr "replica '%s' 재동기화 중" msgid "Rules" msgstr "규칙" msgid "Save Changes" msgstr "변경사항 저장" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "보안 서비스 상세정보: %(service_display_name)s" msgid "Security Service Overview" msgstr "보안 서비스 개요" msgid "Security Services" msgstr "보안 서비스" msgid "Security services within share network" msgstr "공유 네트워크 내 보안 서비스 " msgid "Segmentation Id" msgstr "구분 Id" msgid "Selected projects" msgstr "선택한 프로젝트" msgid "Selected security services" msgstr "선택된 보안 서비스" msgid "Server" msgstr "서버" msgid "Set Replica as Active" msgstr "레프리카를 활성화 상태로 설정" msgid "Set as Active" msgstr "활성화 상태로 설정" msgid "Set maximum quotas for the project." msgstr "프로젝트에대한 최대 quota를 설정합니다." #, python-format msgid "Setting replica \"%s\" as active..." msgstr "레프리카 \"%s\"를 활성화 상태로 설정" #, python-format msgid "Share Details: %(share_display_name)s" msgstr "공유 상세정보: %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "공유 세부 사항: %(share_name)s" msgid "Share Group Overview" msgstr "공유 그룹 개요" msgid "Share Group Snapshot Overview" msgstr "공유 그룹 스냅샷 개요" msgid "Share Group Snapshots" msgstr "공유 그룹 스냅샷" msgid "Share Group Types" msgstr "공유 그룹 타입" msgid "Share Groups" msgstr "공유 그룹" msgid "Share ID" msgstr "공유 ID" #, python-format msgid "Share Instance Details: %s" msgstr "공유 인스턴스 세부 사항: %s" msgid "Share Instances" msgstr "공유 인스턴스" msgid "Share Name" msgstr "공유 이름" msgid "Share Network" msgstr "공유 네트워크" #, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "공유 네트워크 상세 정보: %(network_display_name)s" msgid "Share Network Info" msgstr "공유 네트워크 정보" msgid "Share Networks" msgstr "공유 네트워크" msgid "Share Protocol" msgstr "공유 프로토콜" #, python-format msgid "Share Replicas: %(share_display_name)s" msgstr "공유 레프리카들 : %(share_display_name)s" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "공유 규칙들: %(share_display_name)s" msgid "Share Server" msgstr "공유 서버" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "공유 서버 세부 사항: %(server_name)s" msgid "Share Server Id" msgstr "공유 서버 Id" msgid "Share Servers" msgstr "공유 서버" msgid "Share Snapshots" msgstr "공유 스냅샷" msgid "Share Snapshots Storage" msgstr "공유 스냅샷 저장소" msgid "Share Source" msgstr "공유 소스" msgid "Share Storage" msgstr "공유 저장소" msgid "Share Type" msgstr "공유 유형" msgid "Share Types" msgstr "공유 유형" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "사용가능한 quota의 %(avail)iGiB에서 %(req)iGiB로 공유를 확장하지 못했습니다." msgid "Share name to be assigned" msgstr "할당될 공유 이름" #, python-format msgid "Share replica %s has been deleted." msgstr "공유 replica %s 를 삭제하였습니다." #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "공유 크기는 스냅샷 크기 (%sGiB)보다 크거나 같아야합니다." msgid "Share types" msgstr "공유 유형" msgid "Shares" msgstr "공유" msgid "Shares Networks" msgstr "네트워크 공유" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "크기" msgid "Size (GiB)" msgstr "크기 (GiB)" msgid "Snapshot" msgstr "스냅샷" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "스냅샷 상세정보: %(snapshot_display_name)s" msgid "Source" msgstr "소스" msgid "Start migration" msgstr "마이그레이션 시작" msgid "Status" msgstr "상태" #, python-format msgid "Successfully created security service: %s" msgstr "보안 서비스: %s 를 성공적으로 생성하였습니다" #, python-format msgid "Successfully created share network: %s" msgstr "공유 네트워크: %s 를 성공적으로 생성하였습니다" #, python-format msgid "Successfully created share type: %s" msgstr "공유 유형: %s 를 성공적으로 생성하였습니다" #, python-format msgid "Successfully sent the request to cancel migration of share: %s." msgstr "공유 %s 에 대한 마이그레이션 취소 요청을 성공적으로 전송하였습니다." #, python-format msgid "Successfully sent the request to complete migration of share: %s." msgstr "" "공유 %s 에 대한 마이그레이션을 완료하기 위해 요청을 성공적으로 전송하였습니" "다." #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "공유를 관리하기 위해 요청을 성공적으로 전송하였습니다: %s" #, python-format msgid "Successfully sent the request to migrate share: %s." msgstr "요청을 마이그레이션 공유에 성공적으로 보냈습니다: %s." #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "공유를 관리 해제하기 위해 요청을 성공적으로 전송하였습니다: %s" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "공유 유형 '%s' 에 대한 부가 스펙 갱신을 성공하였습니다." #, python-format msgid "Successfully updated security service \"%s\"" msgstr "시큐리티 서비스 %s를 성공적으로 업데이트 하였습니다." #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "공유 크기는 스냅샷 크기 (%sGiB)보다 작을 수 없습니다." msgid "Type" msgstr "유형" msgid "Unable to add rule." msgstr "규칙을 추가할 수 없습니다." #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "현재 공유 %s 에 대한 마이그레이션 취소를 가져올 수 없습니다." #, python-format msgid "Unable to complete migration of share %s." msgstr "공유 %s 에 대한 마이그레이션을 완료할 수 없습니다." msgid "Unable to create security service." msgstr "보안 서비스를 생성할 수 없습니다." msgid "Unable to create share network." msgstr "공유 네트워크를 생성할 수 없습니다." msgid "Unable to create share replica." msgstr "공유 레프리카를 생성할 수 없습니다." msgid "Unable to create share snapshot." msgstr "공유스냅샷을 생성할 수 없습니다" msgid "Unable to create share type." msgstr "공유 유형을 생성할 수 없습니다." msgid "Unable to create share." msgstr "공유를 생성할 수 없습니다." #, python-format msgid "Unable to delete replica \"%s\"." msgstr "replica \"%s\" 를 삭제할 수 없습니다." #, python-format msgid "Unable to delete rule \"%s\"." msgstr "규칙 \"%s\" 를 삭제 할 수 없습니다." #, python-format msgid "Unable to delete share \"%s\". " msgstr "공유 %s를 제거할 수 없습니다. " #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "" "\"%s\" 스냅샷을 삭제할 수 없습니다. 하나 이상의 공유에 의존하고 있습니다." msgid "Unable to extend share." msgstr "공유를 확장할수 없습니다." msgid "Unable to get information about share type access." msgstr "공유 유형 액세스에 관련된 정보를 가져올 수 없습니다." msgid "Unable to get list of projects." msgstr "프로젝트 목록을 가져올 수 없습니다." msgid "Unable to get the security services hosts" msgstr "보안 서비스 호스트를 가져올 수 없습니다." msgid "Unable to load the specified snapshot." msgstr "지정한 스냅샷을 불러올 수 없습니다." msgid "Unable to manage share" msgstr "공유를 관리할 수 없습니다" #, python-format msgid "Unable to migrate share %s." msgstr "공유 %s를 마이그레이션할 수 없습니다." #, python-format msgid "Unable to obtain progress of migration of share %s at this moment." msgstr "현재 공유 %s 에 대한 마이그레이션 과정을 가져올 수 없습니다." #, python-format msgid "Unable to reset state of replica '%s'." msgstr "replica '%s' state를 리셋할 수 없습니다" #, python-format msgid "Unable to reset status of replica '%s'." msgstr "replica '%s' status를 리셋할 수 없습니다." #, python-format msgid "Unable to resync replica '%s'." msgstr "replica '%s' 를 재동기화할 수 없습니다." msgid "Unable to retrieve list of projects." msgstr "프로젝트 목록을 가져올 수 없습니다." msgid "Unable to retrieve quotas." msgstr "쿼터(quota)를 찾을 수 없습니다." #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "레프리카 %s의 상세정보를 찾을 수 없습니다." #, python-format msgid "Unable to retrieve replica '%s'." msgstr "replica '%s' 를 가져올 수 없습니다." #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "보안 서비스 '%s'의 상세정보를 가져올 수 없습니다." msgid "Unable to retrieve security services" msgstr "보안 서비스를 가져올 수 없습니다" msgid "Unable to retrieve security_service." msgstr "security_service를 찾지 못했습니다." msgid "Unable to retrieve share details." msgstr "공유 세부 사항을 가져올 수 없습니다." msgid "Unable to retrieve share instance details." msgstr "공유 인스턴스 세부 사항을 가져올 수 없습니다." msgid "Unable to retrieve share instances." msgstr "공유 인스턴스를 가져올 수 없습니다." msgid "Unable to retrieve share limit information." msgstr "공유 최대 사용량 정보를 찾지 못 했습니다." msgid "Unable to retrieve share list." msgstr "공유 목록을 가져올 수 없습니다." msgid "Unable to retrieve share network details." msgstr "공유 네트워크 상세정보를 가져올 수 없습니다." msgid "Unable to retrieve share network." msgstr "공유네트워크를 가져올 수 없습니다." msgid "Unable to retrieve share networks" msgstr "공유 네트워크를 가져올 수 없습니다" msgid "Unable to retrieve share replicas." msgstr "공유 레프리카를 가져올 수 없습니다." msgid "Unable to retrieve share rules." msgstr "공유 규칙을 찾을 수 없습니다." msgid "Unable to retrieve share server details." msgstr "공유 서버 세부 사항을 가져올 수 없습니다." msgid "Unable to retrieve share servers" msgstr "공유 서버를 가져올 수 없습니다" msgid "Unable to retrieve share snapshots list." msgstr "공유 스냅샷 목록을 찾을 수 없습니다." msgid "Unable to retrieve share snapshots." msgstr "공유 스냅샷을 찾지 못했습니다." msgid "Unable to retrieve share." msgstr "공유를 찾을 수 없습니다." #, python-format msgid "Unable to retrieve share. %s" msgstr "공유 %s를 가져올 수 없습니다. " msgid "Unable to retrieve share_type." msgstr "share_type 을 가져올 수 없습니다." msgid "Unable to retrieve snapshot details." msgstr "스냅샷 상세정보를 찾을 수 없습니다." msgid "Unable to retrieve snapshot." msgstr "스냅샷을 찾을 수 없습니다." msgid "Unable to retrieve volume details." msgstr "볼륨 세부 사항을 가져올 수 없습니다." msgid "Unable to set project quotas." msgstr "프로젝트 quota를 설정하지 못하였습니다." #, python-format msgid "Unable to set replica '%s' as active." msgstr "레프리카 \"%s\"를 활성화 상태로 설정 할 수 없습니다. " msgid "Unable to unmanage share." msgstr "공유를 관리 해제할 수 없습니다." #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "공유 유형 \"%s\" 에 대한 액세스를 업데이트할 수 없습니다." msgid "Unable to update default quotas." msgstr "기본 할당량을 업데이트할 수 없습니다." msgid "Unable to update extra_specs for share type." msgstr "공유 유형에 대한 extra_specs 을 업데이트할 수 없습니다." msgid "Unable to update security service." msgstr "보안 서비스를 업데이트 할 수 없습니다." msgid "Unable to update share metadata." msgstr "공유 메타데이터를 업데이트할 수 없습니다." #, python-format msgid "Unable to update share network \"%s\"." msgstr "공유 네트워크 \"%s\"를 업데이트 할 수 없습니다." msgid "Unable to update share network." msgstr "공유 네트워크를 업데이트 할 수 없습니다." msgid "Unable to update share type." msgstr "공유 유형을 업데이트할 수 없습니다." msgid "Unable to update share." msgstr "공유를 업데이트할 수 없습니다." msgid "Unknown" msgstr "알 수 없음" msgid "Unmanage" msgstr "관리 해제" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "관리되지 않은 에러" msgid "Unmanage Share" msgstr "공유 관리 해제" msgid "Update" msgstr "업데이트" msgid "Update Share Network" msgstr "공유 네트워크 업데이트" msgid "Update Share Type" msgstr "공유 유형 업데이트" msgid "Update Share group Type" msgstr "공유 그룹 유형 업데이트" msgid "Updated At" msgstr "업데이트" #, python-format msgid "Updated access for share type \"%s\"." msgstr "공유 유형 \"%s\" 에 대한 엑세스를 업데이트하였습니다." #, python-format msgid "Updated share network \"%s\"." msgstr "공유 네트워크 \"%s\" 업데이트됨." #, python-format msgid "Updating share \"%s\"" msgstr "공유 \"%s\" 업데이트 중" #, python-format msgid "Updating share metadata \"%s\"" msgstr "공유 메타데이터 \"%s\" 업데이트중" #, python-format msgid "Updating share network \"%s\"" msgstr "공유 네트워크 \"%s\" 업데이트 중." msgid "Use snapshot as a source" msgstr "소스로 스냅샷 사용" msgid "User" msgstr "사용자" msgid "Visibility" msgstr "가시성" msgid "Writable" msgstr "쓰기가능" msgid "key=value pairs per line can be set" msgstr "한 행 당 key=value 쌍을 설정 가능합니다" manila-ui-2.13.0/manila_ui/locale/pt_BR/000077500000000000000000000000001323215354300176555ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/pt_BR/LC_MESSAGES/000077500000000000000000000000001323215354300214425ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/pt_BR/LC_MESSAGES/django.po000066400000000000000000000430731323215354300232530ustar00rootroot00000000000000# José Mello , 2016. #zanata # Rodrigo Loures , 2018. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2018-01-18 10:21+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2018-01-23 09:52+0000\n" "Last-Translator: José Mello \n" "Language-Team: Portuguese (Brazil)\n" "Language: pt-BR\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #, python-format msgid "%sGiB" msgstr "%sGiB" msgid "(Quota exceeded)" msgstr "(Cota excedida)" msgid "Access Level" msgstr "Nível de Acesso" msgid "Access To" msgstr "Accesso Para" msgid "Access Type" msgstr "Tipo de Acesso" msgid "Access to" msgstr "Accesso para" msgctxt "Current status of share network" msgid "Active" msgstr "Ativo" msgctxt "Current status of share server" msgid "Active" msgstr "Ativo" msgid "Add" msgstr "Adicionar" msgid "Add Rule" msgstr "Adicionar Regra" msgid "Add Security Service" msgstr "Adicionar Serviço de segurança" msgid "Add rule" msgstr "Adicionar regra" msgid "All keys and values must be in range from 1 to 255." msgstr "Todas as chaves e valores devem estar no intervalo de 1 a 255" msgid "Availability Zone" msgstr "Zona de Disponibilidade" msgid "Availability zone" msgstr "Zona de disponibilidade" msgctxt "Current status of replica" msgid "Available" msgstr "Disponível" msgctxt "Current status of share" msgid "Available" msgstr "Disponível" msgctxt "Current status of snapshot" msgid "Available" msgstr "Disponível" msgid "Available projects" msgstr "Projetos disponíveis" msgid "Cancel Migration" msgstr "Cancelar Migração" msgid "Cancel migration" msgstr "Cancelar Migração" msgid "Cancel migration of a Share" msgstr "Cancelar migração de um Compartilhamento" msgid "Complete Migration" msgstr "Completar Migração" msgid "Complete migration" msgstr "Completar Migração" msgid "Complete migration of a Share" msgstr "Completar migração de um Compartilhamento" msgid "Confirm Password" msgstr "Confirmar Senha" msgid "Confirm Unmanage Share" msgstr "Confirmar Remoção de Gerenciamento de Compartilhamento" msgid "Create" msgstr "Criar" msgid "Create Replica" msgstr "Criar Réplica" msgid "Create Security Service" msgstr "Criar Serviço de segurança" msgid "Create Share" msgstr "Criar Compartilhamento" msgid "Create Share Network" msgstr "Criar Rede de Compartilhamento" msgid "Create Share Snapshot" msgstr "Criar Snapshot do Compartilhamento" msgid "Create Share Type" msgstr "Criar Tipo de Compartilhamento" msgid "Create a Share" msgstr "Criar um Compartilhamento" msgid "Created At" msgstr "Criado Em" msgctxt "Current status of replica" msgid "Creating" msgstr "Criando" msgctxt "Current status of share" msgid "Creating" msgstr "Criando" msgctxt "Current status of share server" msgid "Creating" msgstr "Criando" msgctxt "Current status of snapshot" msgid "Creating" msgstr "Criando" #, python-format msgid "Creating replica for share \"%s\"." msgstr "Criando réplica para compartilhamento \"%s\"." #, python-format msgid "Creating rule for \"%s\"" msgstr "Criando regra para \"%s\"" #, python-format msgid "Creating share \"%s\"" msgstr "Criando compartilhamento \"%s\"" #, python-format msgid "Creating share snapshot \"%s\"." msgstr "Criando snapshot do compartilhamento \"%s\"." msgid "Current Size (GiB)" msgstr "Tamanho Atual (GiB)" msgctxt "Current status of replica" msgid "Deleting" msgstr "Excluindo" msgctxt "Current status of share" msgid "Deleting" msgstr "Excluindo" msgid "Description" msgstr "Descrição" msgid "Domain" msgstr "Domínio" msgid "Driver handles share servers" msgstr "Driver gerencia servidores de compartilhamento" #, python-format msgid "Duplicated keys '%s'." msgstr "Chaves duplicadas '%s'." msgid "Edit" msgstr "Editar" msgid "Edit Security Service" msgstr "Editar Serviço de segurança" msgid "Edit Share" msgstr "Editar Compartilhamento" msgid "Edit Share Metadata" msgstr "Editar Metadados do Compartilhamento" msgid "Edit Share Network" msgstr "Editar Rede de Compartilhamento" msgctxt "Current status of replica" msgid "Error" msgstr "Erro" msgctxt "Current status of share" msgid "Error" msgstr "Erro" msgctxt "Current status of share network" msgid "Error" msgstr "Erro" msgctxt "Current status of share server" msgid "Error" msgstr "Erro" msgctxt "Current status of snapshot" msgid "Error" msgstr "Erro" msgid "Export location" msgstr "Localização do Export" msgid "Extend" msgstr "Estender" msgid "Extend Share" msgstr "Estender Compartilhamento" #, python-format msgid "Extend share \"%s\"" msgstr "Estender o compartilhamento \"%s\"" msgctxt "Current status of share" msgid "Extending Error" msgstr "Erro estendendo" msgid "Extra specs" msgstr "Especificações extras" msgid "Force Host Assisted Migration" msgstr "Forçar Migração Assistida do Host" msgid "From here you can update the default quotas (max limits)." msgstr "A partir daqui é possível atualizar as cotas padrão (limites máximos)." msgid "Get migration progress" msgstr "Obter progresso da migração" msgid "Host" msgstr "Host" msgid "Host of share" msgstr "Host do compartilhamento" msgid "Host to migrate share" msgstr "Host para migrar o compartilhamento" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "" "Host onde o compartilhamento está localizado, exemplo: algum." "host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "Versão do IP" msgid "Id" msgstr "Id" msgctxt "Current status of share server" msgid "In-use" msgstr "Em uso" msgctxt "Current status of snapshot" msgid "In-use" msgstr "Em uso" msgctxt "Current status of share network" msgid "Inactive" msgstr "Inativo" #, python-format msgid "Key '%s' has improper length." msgstr "Chave '%s' possui tamanho impróprio." #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "Chave não pode conter espaços. Veja string '%s'." #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "Chaves não devem conter espaços. Erro em '%s'." msgid "Manage" msgstr "Gerenciar" msgctxt "Current status of share" msgid "Manage Error" msgstr "Erro no Gerenciamento" msgid "Manage Replicas" msgstr "Gerenciar Réplicas" msgid "Manage Rules" msgstr "Gerenciar regras" msgid "Manage Share" msgstr "Gerenciar Compartilhamento" msgid "Migrate Share" msgstr "Migrar Compartilhamento" msgid "Migrate a Share" msgstr "Migrar um Compartilhamento" msgctxt "Current status of share" msgid "Migrating" msgstr "Migrando" msgctxt "Current status of share" msgid "Migrating to" msgstr "Migrando para" msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "Informações e membros do projeto modificados, mas não é possível modificar " "cotas do projeto." msgid "Name" msgstr "Nome" msgid "Network Type" msgstr "Tipo de Rede" msgid "Networks" msgstr "Redes" msgid "Neutron Net" msgstr "Rede Neutron" msgid "Neutron Subnet" msgstr "Sub-rede Neutron." msgid "New Size (GiB)" msgstr "Novo Tamanho (GiB)" msgid "New size must be greater than current size." msgstr "O novo tamanho deve ser maior do que o tamanho atual." msgid "No projects found." msgstr "Nenhum projeto encontrado." msgid "No projects selected." msgstr "Nenhum projeto selecionado." msgid "No source, empty share" msgstr "Sem origem, compartilhamento vazio" msgid "Nova Net" msgstr "Rede Nova" msgid "Obtain Progress" msgstr "Obter Progresso" msgid "Obtain migration progress of a Share" msgstr "Obter progresso da migração de um Compartilhamento" msgid "Overview" msgstr "Visão Geral" msgid "Password" msgstr "Senha" msgid "Passwords do not match." msgstr "As senhas não correspondem." msgid "Preserve Metadata" msgstr "Preservar Metadados" msgid "Project" msgstr "Projeto" msgid "Protocol" msgstr "Protocolo" msgid "Public" msgstr "Público" msgid "Quota" msgstr "Cota" msgid "Replica State" msgstr "Estado da Réplica" msgid "Reset replica state" msgstr "Resincronizar estado da réplica" msgid "Reset state" msgstr "Redefinir estado" msgid "Resync" msgstr "Resincronizar" msgid "Resync replica" msgstr "Resincronizar réplica" msgid "Rules" msgstr "Regras" msgid "Save Changes" msgstr "Salvar Alterações" msgid "Security Services" msgstr "Serviços de segurança" msgid "Segmentation Id" msgstr "ID de Segmentação" msgid "Selected projects" msgstr "Projetos selecionados" msgid "Server" msgstr "Servidor" msgid "Set Replica as Active" msgstr "Definir Réplica como Ativa" msgid "Set as Active" msgstr "Definir como Ativo" msgid "Set maximum quotas for the project." msgstr "Defina o valor máximo para as cotas do projeto." #, python-format msgid "Setting replica \"%s\" as active..." msgstr "Definindo réplica \"%s\" como ativa..." #, python-format msgid "Share Details: %(share_display_name)s" msgstr "Detalhes do Compartilhamento: %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "Detalhes do Compartilhamento: %(share_name)s" msgid "Share ID" msgstr "ID do Compartilhamento" #, python-format msgid "Share Instance Details: %s" msgstr "Detalhes da Instância de Compartilhamento: %s" msgid "Share Instances" msgstr "Instâncias de Compartilhamento" msgid "Share Name" msgstr "Nome do Compartilhamento" msgid "Share Network" msgstr "Rede de Compartilhamento" msgid "Share Network Info" msgstr "Informação da Rede de Compartilhamento" msgid "Share Networks" msgstr "Redes de Compartilhamento" msgid "Share Protocol" msgstr "Protocolo de Compartilhamento" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "Regras do Compartilhamento: %(share_display_name)s" msgid "Share Server" msgstr "Servidor de Compartilhamento" msgid "Share Server Id" msgstr "ID do Servidor de Compartilhamento" msgid "Share Servers" msgstr "Servidores de Compartilhamento" msgid "Share Snapshots" msgstr "Snapshots do Compartilhamento" msgid "Share Snapshots Storage" msgstr "Armazenamento de Snapshots do Compartilhamento" msgid "Share Storage" msgstr "Armazenamento do Compartilhamento" msgid "Share Type" msgstr "Tipo de Compartilhamento" msgid "Share Types" msgstr "Tipos de Compartilhamento" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "O compartilhamento não pode ser estendido a %(req)iGiB porque você tem " "apenas %(avail)iGiB da sua cota disponível." msgid "Share name to be assigned" msgstr "Nome do compartilhamento a ser atribuído" msgid "Shares" msgstr "Compartilhamentos" msgid "Shares Networks" msgstr "Redes de Compartilhamentos" msgid "Size" msgstr "Tamanho" msgid "Snapshot" msgstr "Snapshot" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "Detalhes do Snapshot: %(snapshot_display_name)s" msgid "Source" msgstr "Origem" msgid "Start migration" msgstr "Iniciar migração" msgid "Status" msgstr "Status" #, python-format msgid "Successfully created security service: %s" msgstr "Serviço de segurança criado com sucesso: %s" #, python-format msgid "Successfully created share network: %s" msgstr "Rede de compartilhamento criada com sucesso: %s" #, python-format msgid "Successfully created share type: %s" msgstr "Tipo de compartilhamento criado com sucesso: %s" #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "" "Solicitação enviada com sucesso para tornar o compartilhamento não " "gerenciado: %s" #, python-format msgid "Successfully updated security service \"%s\"" msgstr "Serviço de segurança \"%s\" atualizado com sucesso " #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "" "O tamanho do compartilhamento não pode ser menor que o tamanho do snapshot " "(%sGiB)" msgid "Type" msgstr "Tipo" msgid "Unable to add rule." msgstr "Não foi possível adicionar a regra." #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "" "Não foi possível cancelar migração do compartilhamento %s neste momento." msgid "Unable to create security service." msgstr "Não foi possível criar o serviço de segurança: %s" msgid "Unable to create share network." msgstr "Não é possível criar a rede de compartilhamento." msgid "Unable to create share replica." msgstr "Não é possível criar réplica de compartilhamento." msgid "Unable to create share snapshot." msgstr "Não foi possível criar um snapshot do compartilhamento." msgid "Unable to create share type." msgstr "Não é possível criar tipo de compartilhamento." msgid "Unable to create share." msgstr "Não foi possível criar o compartilhamento." #, python-format msgid "Unable to delete rule \"%s\"." msgstr "Não foi possível excluir regra \"%s\"." #, python-format msgid "Unable to delete share \"%s\". " msgstr "Não é possível excluir o compartilhamento \"%s\"." msgid "Unable to extend share." msgstr "Não foi possível estender o compartilhamento." msgid "Unable to get list of projects." msgstr "Não é possível recuperar lista de projetos." msgid "Unable to manage share" msgstr "Não foi possível gerenciar o compartilhamento" #, python-format msgid "Unable to migrate share %s." msgstr "Não foi possível migrar compartilhamento %s." msgid "Unable to retrieve list of projects." msgstr "Não é possível recuperar lista de projetos." msgid "Unable to retrieve quotas." msgstr "Não foi possível recuperar cotas." #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "Não foi possível recuperar detalhes da réplica '%s'." #, python-format msgid "Unable to retrieve replica '%s'." msgstr "Não foi possível recuperar a réplica '%s'." msgid "Unable to retrieve security services" msgstr "Não é possível recuperar serviços de segurança" msgid "Unable to retrieve security_service." msgstr "Não é possível recuperar o security_service." msgid "Unable to retrieve share details." msgstr "Não é possível obter os detalhes do compartilhamento." msgid "Unable to retrieve share instance details." msgstr "Não foi possível obter os detalhes da instância de compartilhamento." msgid "Unable to retrieve share instances." msgstr "Não foi possível recuperar instâncias de compartilhamento." msgid "Unable to retrieve share limit information." msgstr "Não foi possível recuperar informações de limite de compartilhamento." msgid "Unable to retrieve share list." msgstr "Não é possível recuperar a lista de compartilhamento." msgid "Unable to retrieve share network details." msgstr "Não foi possível obter os detalhes da rede de compartilhamento." msgid "Unable to retrieve share network." msgstr "Não foi possível recuperar rede de compartilhamento." msgid "Unable to retrieve share networks" msgstr "Não foi possível recuperar redes de compartilhamento" msgid "Unable to retrieve share replicas." msgstr "Não foi possível recuperar réplicas de compartilhamento." msgid "Unable to retrieve share rules." msgstr "Não foi possível recuperar regras do compartilhamento." msgid "Unable to retrieve share server details." msgstr "Não foi possível obter os detalhes do servidor de compartilhamento." msgid "Unable to retrieve share servers" msgstr "Não foi possível recuperar servidores de compartilhamento" msgid "Unable to retrieve share snapshots list." msgstr "Não foi possível recuperar a lista de snapshots." msgid "Unable to retrieve share." msgstr "Não foi possível recuperar compartilhamento." #, python-format msgid "Unable to retrieve share. %s" msgstr "Não foi possível recuperar compartilhamento. %s" msgid "Unable to retrieve share_type." msgstr "Não foi possível recuperar o share_type." msgid "Unable to retrieve snapshot details." msgstr "Não é possível recuperar detalhes do snapshot." msgid "Unable to retrieve snapshot." msgstr "Não foi possível recuperar o snapshot." msgid "Unable to retrieve volume details." msgstr "Não foi possível recuperar detalhes do volume." msgid "Unable to set project quotas." msgstr "Não foi possível configurar cotas do projeto." #, python-format msgid "Unable to set replica '%s' as active." msgstr "Não foi possível definir a réplica '%s' como ativa." msgid "Unable to unmanage share." msgstr "Não foi possível tornar o compartilhamento não gerenciado." msgid "Unable to update default quotas." msgstr "Não é possível atualizar cotas padrão." msgid "Unable to update security service." msgstr "Não foi possível atualizar o serviço de segurança." msgid "Unable to update share metadata." msgstr "Não foi possível atualizar metadados de compartilhamento." msgid "Unable to update share network." msgstr "Não foi possível atualizar rede de compartilhamento." msgid "Unable to update share." msgstr "Não foi possível atualizar o compartilhamento." msgid "Unknown" msgstr "Desconhecido" msgid "Unmanage" msgstr "Remoção de Gerenciamento" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "Erro na Remoção de Gerenciamento" msgid "Unmanage Share" msgstr "Remover Gerenciamento de Compartilhamento" msgid "Update" msgstr "Atualizar" msgid "Update Share Network" msgstr "Atualizar Rede de Compartilhamento" msgid "Update Share Type" msgstr "Atualizar Tipo de Compartilhamento" msgid "Updated At" msgstr "Atualizado em" #, python-format msgid "Updating share \"%s\"" msgstr "Atualizando o compartilhamento \"%s\"" #, python-format msgid "Updating share metadata \"%s\"" msgstr "Atualizando os metadados do compartilhamento \"%s\"" msgid "User" msgstr "Usuário" msgid "Visibility" msgstr "Visibilidade" msgid "Writable" msgstr "Gravável" manila-ui-2.13.0/manila_ui/locale/ru/000077500000000000000000000000001323215354300172755ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/ru/LC_MESSAGES/000077500000000000000000000000001323215354300210625ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/ru/LC_MESSAGES/django.po000066400000000000000000001002531323215354300226650ustar00rootroot00000000000000# Aleksey Alekseenko <9118250541@mail.ru>, 2016. #zanata # Alexander , 2016. #zanata # Artem , 2016. #zanata # Ilya Alekseyev , 2016. #zanata # Ivan Startsev , 2016. #zanata # Valentin Chikunov , 2016. #zanata # Valeriy Ponomaryov , 2016. #zanata # Artem , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.9.1.dev1\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-06-08 22:16+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-02-06 02:19+0000\n" "Last-Translator: Artem \n" "Language-Team: Russian\n" "Language: ru\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" #, python-format msgid "%sGiB" msgstr "%s ГиБ" msgid "(Quota exceeded)" msgstr "(Превышена квота)" msgid "Access Key" msgstr "Ключ доступа" msgid "Access Level" msgstr "Уровень доступа" msgid "Access To" msgstr "Доступ к" msgid "Access Type" msgstr "Тип доступа" msgid "Access to" msgstr "Доступ к" msgctxt "Current status of share network" msgid "Active" msgstr "Активный" msgctxt "Current status of share server" msgid "Active" msgstr "Активный" msgid "Add" msgstr "Добавить" msgid "Add Rule" msgstr "Добавить правило" msgid "Add Security Service" msgstr "Добавить службу безопасности" msgid "Add rule" msgstr "Добавить правило" msgid "Add security services to share network." msgstr "Добавить службы безопасности в сеть общего ресурса." msgid "All keys and values must be in range from 1 to 255." msgstr "Все ключи и значения должны быть в диапазоне от 1 до 255" msgid "Allow project access to share type." msgstr "Разрешить проектам доступ к типу общего ресурса." msgid "At least one security service must be specified." msgstr "По крайней мере одна служба безопасности должна быть определена." msgid "Availability Zone" msgstr "Зона доступности" msgid "Availability zone" msgstr "Зона доступности" msgctxt "Current status of replica" msgid "Available" msgstr "Доступна" msgctxt "Current status of share" msgid "Available" msgstr "Доступен" msgctxt "Current status of snapshot" msgid "Available" msgstr "Доступно" msgid "Available projects" msgstr "Доступные проекты" msgid "Available security services" msgstr "Доступные службы безопасности." msgid "Cancel Migration" msgstr "Отменить миграцию" msgid "Cancel migration" msgstr "Отменить миграцию" msgid "Cancel migration of a Share" msgstr "Отменить миграцию общего ресурса" msgid "Choose a snapshot" msgstr "Выберете снимок" msgid "Complete Migration" msgstr "Завершите миграцию" msgid "Complete migration" msgstr "Завершить миграцию" msgid "Complete migration of a Share" msgstr "Завершите миграцию общего ресурса" msgid "Confirm Migration Cancelling of Share" msgstr "Подтвердите отмену миграции общего ресурса" msgid "Confirm Migration Completion of Share" msgstr "Подтвердите завершение миграции общего ресурса" msgid "Confirm Obtaining migration progress of Share" msgstr "Подтвердите получение информации о прогрессе миграции общего ресурса" msgid "Confirm Password" msgstr "Подтвердите пароль" msgid "Confirm Unmanage Share" msgstr "Подтвердить разрегистрацию общего ресурса" msgid "Create" msgstr "Создать" msgid "Create Replica" msgstr "Создать реплику" msgid "Create Security Service" msgstr "Создать службу безопасности" msgid "Create Share" msgstr "Создать общий ресурс" msgid "Create Share Network" msgstr "Создать сеть общего ресурса" msgid "Create Share Snapshot" msgstr "Создать снимок общего ресурса" msgid "Create Share Type" msgstr "Создать тип общего ресурса" msgid "Create a Share" msgstr "Создать общий ресурс" msgid "Created At" msgstr "Создано" msgctxt "Current status of replica" msgid "Creating" msgstr "Создание" msgctxt "Current status of share" msgid "Creating" msgstr "Создание" msgctxt "Current status of share server" msgid "Creating" msgstr "Создание" msgctxt "Current status of snapshot" msgid "Creating" msgstr "Создание" #, python-format msgid "Creating replica for share \"%s\"." msgstr "Создание реплики общего ресурса \"%s\"." #, python-format msgid "Creating rule for \"%s\"" msgstr "Создние правила для \"%s\"" #, python-format msgid "Creating share \"%s\"" msgstr "Создание общего ресурса \"%s\"" #, python-format msgid "Creating share snapshot \"%s\"." msgstr "Создается снимок общего ресурса \"%s\"." msgid "Current Size (GiB)" msgstr "Текущий размер (ГиБ)" msgid "DNS IP" msgstr "DNS IP" msgctxt "Current status of replica" msgid "Deleting" msgstr "Удаление" msgctxt "Current status of share" msgid "Deleting" msgstr "Удаление" msgid "Description" msgstr "Описание" msgid "Domain" msgstr "Домен" msgid "Driver handles share servers" msgstr "Драйвер обрабатывает сервера общих ресурсов" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "Параметры драйвера ('volume_id' для 'generic' драйвера и т.д.)" #, python-format msgid "Duplicated keys '%s'." msgstr "Повторяющийся ключ '%s'" msgid "Edit" msgstr "Изменить" msgid "Edit Security Service" msgstr "Редактировать службу безопасности" msgid "Edit Share" msgstr "Редактировать общий ресурс" msgid "Edit Share Metadata" msgstr "Редактировать метаданные общего ресурса" msgid "Edit Share Network" msgstr "Редактировать сеть общего ресурса" msgctxt "Current status of replica" msgid "Error" msgstr "Ошибка" msgctxt "Current status of share" msgid "Error" msgstr "Ошибка" msgctxt "Current status of share network" msgid "Error" msgstr "Ошибка" msgctxt "Current status of share server" msgid "Error" msgstr "Ошибка" msgctxt "Current status of snapshot" msgid "Error" msgstr "Ошибка" msgid "Expected only pairs of key=value." msgstr "Ожидаются только пары ключ = значение" msgid "Export location" msgstr "Место экспорта" msgid "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgstr "Место экспорта общего ресурса. Пример для NFS: 1.2.3.4:/path/to/share" msgid "Extend" msgstr "Расширить" msgid "Extend Share" msgstr "Расширить общий ресурс" #, python-format msgid "Extend share \"%s\"" msgstr "Расширить общий ресурс \"%s\"" msgctxt "Current status of share" msgid "Extending Error" msgstr "Ошибка расширения общего ресурса" msgid "Extra specs" msgstr "Доп. параметры" msgid "Force Host Assisted Migration" msgstr "Принудительно использовать хост для миграции" msgid "From here you can update share network info. " msgstr "Здесь вы можете обновить информацию о сети общего ресурса." msgid "From here you can update the default quotas (max limits)." msgstr "" "Здесь вы можете обновить значения квот по умолчанию (максимальные значения " "лимитов)." msgid "Get migration progress" msgstr "Получить статус миграции" msgid "" "Got improper value for field 'driver_options'. Expected only pairs of " "key=value." msgstr "" "Получено неверное значение для поля 'driver_options'. Ожидаются только пары " "ключ = значение" msgid "Host" msgstr "Хост" msgid "Host of share" msgstr "Хост общего ресурса" msgid "Host to migrate share" msgstr "Хост для миграции общего ресурса" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "" "Хост на котором расположен общий ресурс, например: some.host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "Версия IP" msgid "Id" msgstr "ID" #, python-format msgid "" "Improper value set to required extra spec " "'spec_driver_handles_share_servers'. Allowed values are %s. Case insensitive." msgstr "" "В требуемый дополнительный параметр 'spec_driver_handles_share_servers' " "выставлено недопустимое значение. Допустимые значения %s. " "Регистронезависимое." msgctxt "Current status of share server" msgid "In-use" msgstr "Используется" msgctxt "Current status of snapshot" msgid "In-use" msgstr "Используется" msgctxt "Current status of share network" msgid "Inactive" msgstr "Неактивный" #, python-format msgid "Key '%s' has improper length." msgstr "Ключ '%s' имеет неподходящую длину" #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "Ключ не может содержать пробелы. Смотри строку '%s'" #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "Ключ не может содержать пробелы. Ошибка: '%s'" msgid "Make visible for all" msgstr "Сделать видимым для всех" msgid "Manage" msgstr "Управление" msgctxt "Current status of share" msgid "Manage Error" msgstr "Ошибка регистрации" msgid "Manage Replicas" msgstr "Управление репликами общих ресурсов" msgid "Manage Rules" msgstr "Управление правилами" msgid "Manage Share" msgstr "Зарегистрировать общий ресурс" msgid "Manage Share Type Access" msgstr "Управление доступом к типам общих ресурсов" msgid "Metadata" msgstr "Метаданные" msgid "Migrate Share" msgstr "Миграция общего ресурса" msgid "Migrate a Share" msgstr "Мигрировать общий ресурс" msgctxt "Current status of share" msgid "Migrating" msgstr "Миграция" msgctxt "Current status of share" msgid "Migrating to" msgstr "Миграция в" #, python-format msgid "Migration of share %(name)s is at %(progress)s percent." msgstr "Миграция общего ресурса %(name)s выполнена на %(progress)s процентов." msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "Изменена информация о проекте и участниках, но не удалось обновить квоты." msgid "Name" msgstr "Имя" msgid "Network Type" msgstr "Тип сети" msgid "Networks" msgstr "Сети" msgid "Neutron Net" msgstr "Сеть Neutron" msgid "Neutron Subnet" msgstr "Подсеть Neutron " msgid "New Size (GiB)" msgstr "Новый размер (ГиБ)" msgid "New share network to be set in migrated share" msgstr "" "Новая сеть общего ресурса, которая будет назначена мигрируемому общему " "ресурсу" msgid "New share type to be set in migrating share" msgstr "" "Новый тип общего ресурса, который будет назначен мигрируемому общему ресурсу" msgid "New size must be greater than current size." msgstr "Новый размер должен быть больше чем текущий размер" msgid "No projects found." msgstr "Проекты не найдены." msgid "No projects selected." msgstr "Проекты не выбраны." msgid "No security services found." msgstr "Службы безопасности не найдены." msgid "No security services selected." msgstr "Службы безопасности не выбраны." msgid "No source, empty share" msgstr "Нет источника, пустой общий ресурс" msgid "Nova Net" msgstr "Сеть Nova" msgid "Obtain Progress" msgstr "Получить информацию о прогрессе" msgid "Obtain migration progress of a Share" msgstr "Получить информацию о прогрессе миграции общего ресурса" msgid "Overview" msgstr "Обзор" msgid "Password" msgstr "Пароль" msgid "Passwords do not match." msgstr "Пароли не совпадают" msgid "Preserve Metadata" msgstr "Сохранить метаданные" msgid "Project" msgstr "Проект" msgid "Projects with access to share type" msgstr "Проекты с доступом к типу общего ресурса" msgid "Protocol" msgstr "Протокол" msgid "Public" msgstr "Публичный" msgid "Quota" msgstr "Квота" #, python-format msgid "Replica Details: %(replica_display_name)s" msgstr "Информация о реплике: %(replica_display_name)s" msgid "Replica State" msgstr "Состояние реплики" msgid "Replicas" msgstr "Реплики" msgid "Reset Replica State" msgstr "Сбросить состояние реплики" msgid "Reset Replica Status" msgstr "Сбросить статус реплики" msgid "Reset replica state" msgstr "Сбросить состояние реплики" msgid "Reset replica status" msgstr "Сбросить статус реплики" msgid "Reset state" msgstr "Сбросить состояние" msgid "Reset status" msgstr "Сбросить статус" #, python-format msgid "Reseting replica ('%(id)s') state from '%(from)s' to '%(to)s'." msgstr "Сброс состояния реплики ('%(id)s') с '%(from)s' к '%(to)s'." #, python-format msgid "Reseting replica ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "Сброс статуса реплики ('%(id)s') с '%(from)s' до '%(to)s'." msgid "Resync" msgstr "Синхронизировать" msgid "Resync Replica" msgstr "Повторная синхронизация реплики" msgid "Resync replica" msgstr "Повторная синхронизация реплики" #, python-format msgid "Resync'ing replica '%s'" msgstr "Синхронизация реплики '%s'" msgid "Rules" msgstr "Правила" msgid "Save Changes" msgstr "Сохранить изменения" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "Информация о службе безопасности: %(service_display_name)s" msgid "Security Services" msgstr "Службы безопасности" msgid "Security services within share network" msgstr "Службы безопасности сети общего ресурса" msgid "Segmentation Id" msgstr "ID сегмента" msgid "Selected projects" msgstr "Выбранные проекты" msgid "Selected security services" msgstr "Выбранные службы безопасности." msgid "Server" msgstr "Сервер" msgid "Set Replica as Active" msgstr "Назначить реплику активной" msgid "Set as Active" msgstr "Назначить активной" msgid "Set maximum quotas for the project." msgstr "Выставите максимальные квоты для этого проекта" #, python-format msgid "Setting replica \"%s\" as active..." msgstr "Назначение реплики \"%s\" активной..." #, python-format msgid "Share Details: %(share_display_name)s" msgstr "Информация об общем ресурсе: %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "Информация об общем ресурсе: %(share_name)s" msgid "Share ID" msgstr "ID общего ресурса" #, python-format msgid "Share Instance Details: %s" msgstr "Информация об инстансе общего ресурса: %s" msgid "Share Instances" msgstr "Инстансы общего ресурса" msgid "Share Name" msgstr "Имя общего ресурса" msgid "Share Network" msgstr "Сеть общего ресурса" #, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "Информация о сети общего ресурса: %(network_display_name)s" msgid "Share Network Info" msgstr "Информация о сети общего ресурса" msgid "Share Networks" msgstr "Сети общих ресурсов" msgid "Share Protocol" msgstr "Протокол общего ресурса" #, python-format msgid "Share Replicas: %(share_display_name)s" msgstr "Реплики общего ресурса: %(share_display_name)s" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "Правила общего ресурса: %(share_display_name)s" msgid "Share Server" msgstr "Сервер общего ресурса" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "Информация о Сервере общего ресурса: %(server_name)s" msgid "Share Server Id" msgstr "ID сервера общего ресурса" msgid "Share Servers" msgstr "Сервера общих ресурсов" msgid "Share Snapshots" msgstr "Снимки общего ресурса" msgid "Share Snapshots Storage" msgstr "Размер хранилица снимков общих ресурсов" msgid "Share Source" msgstr "Источник общего ресурса" msgid "Share Storage" msgstr "Размер хранилища общих ресурсов" msgid "Share Type" msgstr "Тип общего ресурса" msgid "Share Types" msgstr "Типы общих ресурсов" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "Невозможно расширить общий ресурс до %(req)i ГиБ, так как ограничение квоты " "составляет %(avail)i ГиБ." msgid "Share name to be assigned" msgstr "Имя общего ресурса, которое будет назначено." #, python-format msgid "Share replica %s has been deleted." msgstr "Реплика общего ресурса %s была удалена." #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "" "Размер общего ресурса должен быть равным или больше размера снимка (%sГиБ)" msgid "Shares" msgstr "Общие ресурсы" msgid "Shares Networks" msgstr "Сети Общего Ресурса" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "Размер" msgid "Size (GiB)" msgstr "Размер (ГиБ)" msgid "Snapshot" msgstr "Снимок" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "Информация о снимке: %(snapshot_display_name)s" msgid "Source" msgstr "Источник" msgid "Start migration" msgstr "Начать миграцию" msgid "Status" msgstr "Статус" #, python-format msgid "Successfully created security service: %s" msgstr "Служба безопасности: %s успешно создана" #, python-format msgid "Successfully created share network: %s" msgstr "Сеть общего ресурса: %s успешно создана" #, python-format msgid "Successfully created share type: %s" msgstr "Успешно создан тип общего ресурса: %s" #, python-format msgid "Successfully sent the request to cancel migration of share: %s." msgstr "Запрос на отмену миграции общего ресурса:%s успешно отправлен." #, python-format msgid "Successfully sent the request to complete migration of share: %s." msgstr "Успешно отправлен запрос на завершение миграции общего ресурса :%s" #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "Запрос на регистрацию общего ресурса %s успешно отправлен" #, python-format msgid "Successfully sent the request to migrate share: %s." msgstr "Успешно отправлен запрос на миграцию общего ресурса: %s." #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "Успешно отправлен запрос на разрегистрацию общего ресурса: %s" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "Доп.параметры были успешно обновлены для типа общего ресурса '%s'." #, python-format msgid "Successfully updated security service \"%s\"" msgstr "Успешно обновлена служба безопасности \"%s\"" #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "Размер общего ресурса не может быть меньше размера снимка (%s ГиБ)" msgid "Type" msgstr "Тип" msgid "Unable to add rule." msgstr "Невозможно добавить правило" #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "Невозможно отменить миграцию общего ресурса %s в данный момент." #, python-format msgid "Unable to complete migration of share %s." msgstr "Невозможно завершить миграцию общего ресурса %s." msgid "Unable to create security service." msgstr "Невозможно создать службу безопасности." msgid "Unable to create share network." msgstr "Невозможно создать сеть общего ресурса." msgid "Unable to create share replica." msgstr "Невозможно создать реплику общего ресурса" msgid "Unable to create share snapshot." msgstr "Не удалось создать снимок общего ресурса." msgid "Unable to create share type." msgstr "Не удалось создать тип общего ресурса." msgid "Unable to create share." msgstr "Не удалось создать общий ресурс." #, python-format msgid "Unable to delete replica \"%s\"." msgstr "Невозможно удалить реплику \"%s\"." #, python-format msgid "Unable to delete rule \"%s\"." msgstr "Не удалось удалить правило \"%s\"." #, python-format msgid "Unable to delete share \"%s\". " msgstr "Невозможно удалить общий ресурс \"%s\"." #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "" "Невозможно удалить снимок \"%s\". Один или несколько общих ресурсов зависят " "от него." msgid "Unable to extend share." msgstr "Не удалось расширить общий ресурс." msgid "Unable to get information about share type access." msgstr "Невозможно получить информацию о доступе к типу общего ресурса" msgid "Unable to get list of projects." msgstr "Невозможно получить список проектов." msgid "Unable to get the security services hosts" msgstr "Не удается получить хосты служб безопасности" msgid "Unable to load the specified snapshot." msgstr "Не удается загрузить определенный снимок." msgid "Unable to manage share" msgstr "Невозможно зарегистрировать общий ресурс" #, python-format msgid "Unable to migrate share %s." msgstr "Невозможно мигрировать общий ресурс %s." #, python-format msgid "Unable to obtain progress of migration of share %s at this moment." msgstr "" "Сейчас невозможно получить прогресс выполнения миграции общего ресурса: %s " #, python-format msgid "Unable to reset state of replica '%s'." msgstr "Невозможно сбросить состояние реплики '%s'." #, python-format msgid "Unable to reset status of replica '%s'." msgstr "Невозможно сбросить статус реплики '%s'." #, python-format msgid "Unable to resync replica '%s'." msgstr "Невозможно синхронизировать реплику '%s'." msgid "Unable to retrieve list of projects." msgstr "Невозможно получить список проектов." msgid "Unable to retrieve quotas." msgstr "Не удается получить квоты." #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "Невозможно получить информацию о реплике %s." #, python-format msgid "Unable to retrieve replica '%s'." msgstr "Невозможно получить реплику '%s'." #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "Не удалось получить информацию о службе безопасности '%s'." msgid "Unable to retrieve security services" msgstr "Невозможно получить службы безопасности" msgid "Unable to retrieve security_service." msgstr "Невозможно получить службу безопасности." msgid "Unable to retrieve share details." msgstr "Невозможно получить информацию об общем ресурсе." msgid "Unable to retrieve share instance details." msgstr "Не удалось получить информацию об инстансе общего ресурса." msgid "Unable to retrieve share instances." msgstr "Невозможно получить инстансы общего ресурса." msgid "Unable to retrieve share limit information." msgstr "Не удается получить информацию по ограничениям для общего ресурса. " msgid "Unable to retrieve share list." msgstr "Невозможно получить список общих ресурсов." msgid "Unable to retrieve share network details." msgstr "Невозможно получить информацию о сети общего ресурса" msgid "Unable to retrieve share network." msgstr "Невозможно получить сеть общего ресурса." msgid "Unable to retrieve share networks" msgstr "Невозможно получить сети общех ресурсов" msgid "Unable to retrieve share replicas." msgstr "Невозможно получить реплики общего ресурса." msgid "Unable to retrieve share rules." msgstr "Невозможно получить правила общего ресурса." msgid "Unable to retrieve share server details." msgstr "Невозможно получить информацию о сервере общего ресурса" msgid "Unable to retrieve share servers" msgstr "Невозможно получить сервера общих ресурсов" msgid "Unable to retrieve share snapshots list." msgstr "Невозможно получить список снимков." msgid "Unable to retrieve share snapshots." msgstr "Невозможно получить снимки общего ресурса." msgid "Unable to retrieve share." msgstr "Невозможно получить общий ресурс." #, python-format msgid "Unable to retrieve share. %s" msgstr "Невозможно получить общий ресурс. %s" msgid "Unable to retrieve share_type." msgstr "Не удалось получить тип общего ресурса" msgid "Unable to retrieve snapshot details." msgstr "Не удалось получить детали снимка." msgid "Unable to retrieve snapshot." msgstr "Не удалось получить снимок." msgid "Unable to retrieve volume details." msgstr "Не удалось получить информацию о диске." msgid "Unable to set project quotas." msgstr "Невозможно выставить квоты проекта" #, python-format msgid "Unable to set replica '%s' as active." msgstr "Невозможно назначить реплику '%s' активной." msgid "Unable to unmanage share." msgstr "Невозможно разрегистрировать общий ресурс." #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "Невозможно обновить доступ к типу общего ресурса \"%s\"." msgid "Unable to update default quotas." msgstr "Не удалось обновить квоты по умолчанию." msgid "Unable to update extra_specs for share type." msgstr "Не удается обновить доп параметры для типа общего ресурса." msgid "Unable to update security service." msgstr "Невозможно обновить службу безопасности." msgid "Unable to update share metadata." msgstr "Невозможно обновить метаданные общего ресурса." #, python-format msgid "Unable to update share network \"%s\"." msgstr "Невозможно обновить сеть общего ресурса \"%s\"." msgid "Unable to update share network." msgstr "Невозможно обновить сеть общего ресурса." msgid "Unable to update share type." msgstr "Невозможно обновить тип общего ресурса." msgid "Unable to update share." msgstr "Не удалось обновить общий ресурс." msgid "Unknown" msgstr "Неизвестно" msgid "Unmanage" msgstr "Разрегистрировать" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "Ошибка регистрации общего ресурса" msgid "Unmanage Share" msgstr "Разрегистрировать общий ресурс" msgid "Update" msgstr "Обновить" msgid "Update Share Network" msgstr "Обновить сеть общего ресурса" msgid "Update Share Type" msgstr "Обновить тип общего ресурса" msgid "Updated At" msgstr "Обновлено" #, python-format msgid "Updated access for share type \"%s\"." msgstr "Доступ для типа общего ресурса \"%s\" обновлен." #, python-format msgid "Updated share network \"%s\"." msgstr "Сеть общего ресурса \"%s\" обновлена" #, python-format msgid "Updating share \"%s\"" msgstr "Обновление общего ресурса \"%s\"" #, python-format msgid "Updating share metadata \"%s\"" msgstr "Обновление метаданных общего ресурса \"%s\"" #, python-format msgid "Updating share network \"%s\"" msgstr "Обновление сети общего ресурса \"%s\"" msgid "Use snapshot as a source" msgstr "Использовать снимок как источник" msgid "User" msgstr "Пользователь" msgid "Visibility" msgstr "Видимость" msgid "Writable" msgstr "Записываемый" msgid "key=value pairs per line can be set" msgstr "Пара значений key=value может быть задана для каждой строки" manila-ui-2.13.0/manila_ui/locale/tr_TR/000077500000000000000000000000001323215354300177015ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/tr_TR/LC_MESSAGES/000077500000000000000000000000001323215354300214665ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/tr_TR/LC_MESSAGES/django.po000066400000000000000000001176271323215354300233060ustar00rootroot00000000000000# işbaran akçayır , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.10.2.dev3\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-08-22 12:36+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-08-25 07:29+0000\n" "Last-Translator: Copied by Zanata \n" "Language-Team: Turkish (Turkey)\n" "Language: tr-TR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Zanata 3.9.6\n" "X-POOTLE-MTIME: 1495463317.000000\n" #, python-format msgid "%sGiB" msgstr "%sGiB" msgid "(Quota exceeded)" msgstr "(Kota aşıldı)" msgid "Access Key" msgstr "Erişim Anahtarı" msgid "Access Level" msgstr "Erişim Seviyesi" msgid "Access To" msgstr "Erişim" msgid "Access Type" msgstr "Erişim Türü" msgid "Access to" msgstr "Erişim" msgctxt "Current status of share network" msgid "Active" msgstr "Etkin" msgctxt "Current status of share server" msgid "Active" msgstr "Etkin" msgid "Add" msgstr "Ekle" msgid "Add Rule" msgstr "Kural Ekle" msgid "Add Security Service" msgstr "Güvenlik Servisi Ekle" msgid "Add Share Snapshot Rule" msgstr "Paylaşım Anlık Görüntü Kuralı Ekle" msgid "Add rule" msgstr "Kural ekle" msgid "Add security services to share network." msgstr "Paylaşım ağına güvenlik servisleri ekle." msgid "All keys and values must be in range from 1 to 255." msgstr "Tüm anahtarlar ve değerler 1 ve 255 aralığında olmalı." msgid "Allow project access to share group type." msgstr "Paylaşım grubu türüne proje erişimine izin ver." msgid "Allow project access to share type." msgstr "Paylaşım türüne proje erişimi ver." msgid "At least one security service must be specified." msgstr "En az bir güvenlik servisi belirtilmeli." msgid "At least one share type must be specified." msgstr "En az bir paylaşım türü belirtilmelidir." msgid "Availability Zone" msgstr "Kullanılırlık Bölgesi" msgid "Availability zone" msgstr "Kullanılırlık bölgesi" msgctxt "Current status of replica" msgid "Available" msgstr "Kullanılabilir" msgctxt "Current status of share" msgid "Available" msgstr "Kullanılabilir" msgctxt "Current status of snapshot" msgid "Available" msgstr "Uygun" msgid "Available projects" msgstr "Kullanılabilir projeler" msgid "Available security services" msgstr "Kullanılabilir güvenlik servisleri" msgid "Cancel Migration" msgstr "Göçü İptal Et" msgid "Cancel migration" msgstr "Göçü iptal et" msgid "Cancel migration of a Share" msgstr "Bir Paylaşımın göçünü iptal et" msgid "Choose a snapshot" msgstr "Bir anlık görüntü seçin" msgid "Complete Migration" msgstr "Göçü Tamamla" msgid "Complete migration" msgstr "Göçü tamamla" msgid "Complete migration of a Share" msgstr "Bir paylaşımın göçünü tamamla" msgid "Confirm Migration Cancelling of Share" msgstr "Paylaşım Göç İptalini Onayla" msgid "Confirm Migration Completion of Share" msgstr "Paylaşımın Göç Tamamlanmasını Onayla" msgid "Confirm Obtaining migration progress of Share" msgstr "Paylaşım göç sürecini Almayı onayla" msgid "Confirm Password" msgstr "Parolayı Onayla" msgid "Confirm Unmanage Share" msgstr "Paylaşım Yönetim İptalini Onayla" msgid "Create" msgstr "Oluştur" msgid "Create Replica" msgstr "Kopya Oluştur" msgid "Create Security Service" msgstr "Güvenlik Servisi Oluştur" msgid "Create Share" msgstr "Paylaşım Oluştur" msgid "Create Share Group" msgstr "Paylaşım Grubu Oluştur" msgid "Create Share Group Snapshot" msgstr "Paylaşım Grubu Anlık Görüntüsü Oluştur" msgid "Create Share Group Type" msgstr "Paylaşım Grubu Türü Oluştur" msgid "Create Share Network" msgstr "Paylaşım Ağı Oluştur" msgid "Create Share Snapshot" msgstr "Paylaşım Anlık Görüntüsü Oluştur" msgid "Create Share Type" msgstr "Paylaşım Türü Oluştur" msgid "Create a Share" msgstr "Bir Paylaşım Oluştur" msgid "Created At" msgstr "Oluşturulma Tarihi" msgid "Created at" msgstr "Oluşturulma" msgctxt "Current status of replica" msgid "Creating" msgstr "Oluşturuluyor" msgctxt "Current status of share" msgid "Creating" msgstr "Oluşturuluyor" msgctxt "Current status of share server" msgid "Creating" msgstr "Oluşturuluyor" msgctxt "Current status of snapshot" msgid "Creating" msgstr "Oluşturuluyor" #, python-format msgid "Creating replica for share \"%s\"." msgstr "\"%s\" paylaşımı için kopya oluşturuluyor." #, python-format msgid "Creating rule for \"%s\"" msgstr "\"%s\" için kural oluşturuluyor" #, python-format msgid "Creating share \"%s\"" msgstr "\"%s\" paylaşımı oluşturuluyor" #, python-format msgid "Creating share group \"%s\"" msgstr "\"%s\" paylaşım grubu oluşturuluyor" #, python-format msgid "Creating share group snapshot \"%s\"." msgstr "Paylaşım grubu anlık görüntüsü \"%s\" oluşturuluyor." #, python-format msgid "Creating share snapshot \"%s\"." msgstr "Paylaşım anlık görüntüsü \"%s\"." #, python-format msgid "Creating snapshot rule for \"%s\"" msgstr "\"%s\" için anlık görüntü kuralı oluşturuluyor" msgid "Current Size (GiB)" msgstr "Mevcut Boyut (GiB)" msgid "DNS IP" msgstr "DNS IP" msgid "Default Quotas" msgstr "Öntanımlı Kotalar" msgid "Delete Replica" msgid_plural "Delete Replicas" msgstr[0] "Kopyayı Sil" msgstr[1] "Kopyaları Sil" msgid "Delete Rule" msgid_plural "Delete Rules" msgstr[0] "Kuralı Sil" msgstr[1] "Kuralları Sil" msgid "Delete Security Service" msgid_plural "Delete Security Services" msgstr[0] "Güvenlik Servisini Sil" msgstr[1] "Güvenlik Servislerini Sil" msgid "Delete Share" msgid_plural "Delete Shares" msgstr[0] "Paylaşımı Sil" msgstr[1] "Paylaşımları Sil" msgid "Delete Share Group" msgid_plural "Delete Share Groups" msgstr[0] "Paylaşım Grubunu Sil" msgstr[1] "Paylaşım Gruplarını Sil" msgid "Delete Share Group Snapshot" msgid_plural "Delete Share Group Snapshots" msgstr[0] "Paylaşım Grubu Anlık Görüntüsünü Sil" msgstr[1] "Paylaşım Grubu Anlık Görüntülerini Sil" msgid "Delete Share Group Type" msgid_plural "Delete Share Group Types" msgstr[0] "Paylaşım Grubu Türünü Sil" msgstr[1] "Paylaşım Grubu Türlerini Sil" msgid "Delete Share Network" msgid_plural "Delete Share Networks" msgstr[0] "Paylaşım Ağını Sil" msgstr[1] "Paylaşım Ağlarını Sil" msgid "Delete Share Server" msgid_plural "Delete Share Server" msgstr[0] "Paylaşım Sunucusu Sil" msgstr[1] "Paylaşım Sunucularını Sil" msgid "Delete Share Snapshot" msgid_plural "Delete Share Snapshots" msgstr[0] "Paylaşım Anlık Görüntüsünü Sİl" msgstr[1] "Paylaşım Anlık Görüntülerini Sİl" msgid "Delete Share Snapshot Rule" msgid_plural "Delete Share Snapshot Rules" msgstr[0] "Paylaşım Anlık Görüntü Kuralı Sil" msgstr[1] "Paylaşım Anlık Görüntü Kurallarını Sil" msgid "Delete Share Type" msgid_plural "Delete Share Types" msgstr[0] "Paylaşım Türünü Sil" msgstr[1] "Paylaşım Türlerini Sil" msgid "Delete Snapshot" msgid_plural "Delete Snapshots" msgstr[0] "Anlık Görüntü Sil" msgstr[1] "Anlık Görüntüleri Sil" msgid "Deleted Replica" msgid_plural "Deleted Replicas" msgstr[0] "Kopya Silindi" msgstr[1] "Kopyalar Silindi" msgid "Deleted Rule" msgid_plural "Deleted Rules" msgstr[0] "Kural Silindi" msgstr[1] "Kurallar Silindi" msgid "Deleted Security Service" msgid_plural "Deleted Security Services" msgstr[0] "Güvenlik Servisi Silindi" msgstr[1] "Güvenlik Servisleri Silindi" msgid "Deleted Share" msgid_plural "Deleted Shares" msgstr[0] "Paylaşım Silindi" msgstr[1] "Paylaşımlar Silindi" msgid "Deleted Share Group" msgid_plural "Deleted Share Groups" msgstr[0] "Paylaşım Grubunu Sil" msgstr[1] "Paylaşım Gruplarını Sil" msgid "Deleted Share Group Snapshot" msgid_plural "Deleted Share Group Snapshots" msgstr[0] "Paylaşım Grubu Anlık Görüntüsünü Sil" msgstr[1] "Paylaşım Grubu Anlık Görüntülerini Sil" msgid "Deleted Share Group Type" msgid_plural "Deleted Share Group Types" msgstr[0] "Paylaşım Grubu Türünü Sil" msgstr[1] "Paylaşım Grubu Türlerini Sil" msgid "Deleted Share Network" msgid_plural "Deleted Share Networks" msgstr[0] "Paylaşım Ağı Silindi" msgstr[1] "Paylaşım Ağları Silindi" msgid "Deleted Share Server" msgid_plural "Deleted Share Server" msgstr[0] "Paylaşım Sunucusu Silindi" msgstr[1] "Paylaşım Sunucuları Silindi" msgid "Deleted Share Snapshot" msgid_plural "Deleted Share Snapshots" msgstr[0] "Paylaşım Anlık Görüntüsünü Sil" msgstr[1] "Paylaşım Anlık Görüntülerini Sil" msgid "Deleted Share Snapshot Rule" msgid_plural "Deleted Share Snapshot Rules" msgstr[0] "Paylaşım Anlık Görüntü Kuralı Sil" msgstr[1] "Paylaşım Anlık Görüntü Kurallarını Sil" msgid "Deleted Share Type" msgid_plural "Deleted Share Types" msgstr[0] "Paylaşım Türü Silindi" msgstr[1] "Paylaşım Türleri Silindi" msgid "Deleted Snapshot" msgid_plural "Deleted Snapshots" msgstr[0] "Anlık Görüntü Silindi" msgstr[1] "Anlık Görüntüler Silindi" msgctxt "Current status of replica" msgid "Deleting" msgstr "Siliniyor" msgctxt "Current status of share" msgid "Deleting" msgstr "Siliniyor" msgid "Description" msgstr "Açıklama" msgid "Destination host and pool where share will be migrated to." msgstr "Paylaşımın geçirileceği hedef istemci ve havuz." msgid "Domain" msgstr "Alan" msgid "Driver handles share servers" msgstr "Sürücü paylaşım sunucuları ele alır" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "Sürücü seçenekleri (Genel sürücü için 'birim_kimliği', vs...)" #, python-format msgid "Duplicated keys '%s'." msgstr "Kopya anahtarlar '%s'." msgid "Edit" msgstr "Düzenle" msgid "Edit Security Service" msgstr "Güvenlik Servisini Düzenle" msgid "Edit Share" msgstr "Paylaşımı Düzenle" msgid "Edit Share Metadata" msgstr "Paylaşım Metaverisini Düzenle" msgid "Edit Share Network" msgstr "Paylaşım Ağını Düzenle" msgid "Edit Share Snapshot" msgstr "Paylaşım Anlık Görüntüsü Düzenle" msgid "" "Enforces migration of the share snapshots to the destination. If set to " "True, host-assisted migration will not be attempted." msgstr "" "Paylaşım anlık görüntülerinin hedefe göçünü zorlar. Doğru olarak " "işaretlenirse, istemci-destekli göç denenmez." msgid "" "Enforces migration to be nondisruptive. If set to True, host-assisted " "migration will not be attempted." msgstr "" "Göçün aksatmadan yapılmasına zorlar. Doğru olarak ayarlanırsa, istemci-" "destekli göç denenmez." msgid "" "Enforces migration to keep the share writable while contents are being " "moved. If set to True, host-assisted migration will not be attempted." msgstr "" "Göç sırasında içerik taşınırken paylaşımın yazılabilir kalmasını zorlar. " "Doğru olarak ayarlanırsa, istemci-destekli göç denenmez." msgid "" "Enforces migration to preserve all file metadata when moving its contents. " "If set to True, host-assisted migration will not be attempted." msgstr "" "Göç sırasında içeriği taşırken tüm metaveri dosyasının korunmasını zorlar. " "Doğru olarak işaretlenirse, istemci-destekli göç denenmez." msgid "" "Enforces the use of the host-assisted migration approach, which bypasses " "driver optimizations." msgstr "" "İstemci-destekli göç yaklaşımını kullanmaya zorlar, sürücü iyileştirmeleri " "atlanır." msgctxt "Current status of replica" msgid "Error" msgstr "Hata" msgctxt "Current status of share" msgid "Error" msgstr "Hata" msgctxt "Current status of share network" msgid "Error" msgstr "Hata" msgctxt "Current status of share server" msgid "Error" msgstr "Hata" msgctxt "Current status of snapshot" msgid "Error" msgstr "Hata" msgid "Expected only pairs of key=value." msgstr "Yalnızca anahtar=değer çiftleri bekleniyor." msgid "Export location" msgstr "Dışa aktarım konumu" msgid "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgstr "" "Paylaşımın dışa aktarım konumu. Örneğin NFS için 1.2.3.4:/paylaşım/yolu" msgid "Extend" msgstr "Genişlet" msgid "Extend Share" msgstr "Paylaşımı Büyüt" #, python-format msgid "Extend share \"%s\"" msgstr "\"%s\" paylaşımını büyüt" msgctxt "Current status of share" msgid "Extending Error" msgstr "Genişletme Hatası" msgid "Extra specs" msgstr "Ek özellikler" msgid "Force Host Assisted Migration" msgstr "İstemci Destekli Göçe Zorla" msgid "From here you can update share network info. " msgstr "Burdan paylaşım ağı bilgisini güncelleyebilirsiniz. " msgid "From here you can update the default quotas (max limits)." msgstr "Buradan öntanımlı kotaları güncelleyebilirsiniz (azami sınırlar)." msgid "Get migration progress" msgstr "Göç ilerlemesini al" msgid "" "Got improper value for field 'driver_options'. Expected only pairs of " "key=value." msgstr "" "'driver_options' alanı için geçersiz değer alındı. Yalnızca anahtar=değer " "çiftleri bekleniyor." msgid "Group specs" msgstr "Grup özellikleri" msgid "Host" msgstr "Sunucu" msgid "Host of share" msgstr "Paylaşım sunucusu" msgid "Host to migrate share" msgstr "Paylaşımın geçirileceği istemci" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "Paylaşımın konumlandığı sunucu, örneğin: bir.sunucu@sürücü[#havuz]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "IP Sürümü" msgid "Id" msgstr "Id" #, python-format msgid "" "Improper value set to required extra spec " "'spec_driver_handles_share_servers'. Allowed values are %s. Case insensitive." msgstr "" "'spec_driver_handles_share_servers' ek özelliği için uygun olmayan değer " "ayarlanmış. İzin verilen değerler %s. Büyük küçük harfe duyarsız." msgctxt "Current status of share server" msgid "In-use" msgstr "Kullanımda" msgctxt "Current status of snapshot" msgid "In-use" msgstr "Kullanımda" msgctxt "Current status of share network" msgid "Inactive" msgstr "Pasif" #, python-format msgid "Key '%s' has improper length." msgstr "Anahtar '%s' uygunsuz uzunluğa sahip." #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "Anahtar boşluk içeremez. '%s' karakter dizisine göz atın." #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "Anahtarlar boşluk içermemeli. '%s'de hata." msgid "Make visible for all" msgstr "Herkes için görünür yap" msgid "Manage" msgstr "Yönet" msgctxt "Current status of share" msgid "Manage Error" msgstr "Yönetme Hatası" msgid "Manage Replicas" msgstr "Kopyaları Yönet" msgid "Manage Rules" msgstr "Kuralları Yönet" msgid "Manage Share" msgstr "Paylaşımı Yönet" msgid "Manage Share Group Type Access" msgstr "Paylaşım Grubu Türü Erişimini Yönet" msgid "Manage Share Snapshot Rules" msgstr "Paylaşım Anlık Görüntü Kurallarını Yönet" msgid "Manage Share Type Access" msgstr "Paylaşım Türü Erişimini Yönet" msgid "Metadata" msgstr "Metaveri" msgid "Migrate Share" msgstr "Paylaşımı Göç Ettir" msgid "Migrate a Share" msgstr "Bir paylaşımı göç ettir" msgctxt "Current status of share" msgid "Migrating" msgstr "Göç Ediyor" msgctxt "Current status of share" msgid "Migrating to" msgstr "Göç konumu" #, python-format msgid "Migration of share %(name)s is at %(progress)s percent." msgstr "%(name)s paylaşımının göçü yüzde %(progress)s." msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "" "Proje bilgisi ve üyeleri değiştirildi, ama proje kotaları değiştirilemiyor." msgid "Name" msgstr "İsim" msgid "Network Type" msgstr "Ağ Türü" msgid "Networks" msgstr "Ağlar" msgid "Neutron Net" msgstr "Neutron Ağı" msgid "Neutron Subnet" msgstr "Neutron Alt Ağı" msgid "New Size (GiB)" msgstr "Yeni Boyut (GiB)" msgid "New share network to be set in migrated share" msgstr "Göç etmiş paylaşımda yeni paylaşım ağı ayarlanacak" msgid "New share type to be set in migrating share" msgstr "Göç eden paylaşımda ayarlanacak yeni paylaşım türü" msgid "New size must be greater than current size." msgstr "Yeni boyut mevcut boyuttan büyük olmalı." msgid "No projects found." msgstr "Proje bulunamadı." msgid "No projects selected." msgstr "Hiçbir proje seçili değil." msgid "No security services found." msgstr "Hiçbir güvenlik servisi bulunamadı." msgid "No security services selected." msgstr "Hiçbir güvenlik servisi seçilmemiş." msgid "No source, empty share" msgstr "Kaynak yok, boş paylaşım" msgid "No source, empty share group" msgstr "Kaynak yok, boş paylaşım grubu" msgid "Nondisruptive" msgstr "Aksatmadan" msgid "Nova Net" msgstr "Nova Ağı" msgid "Obtain Progress" msgstr "Süreci Al" msgid "Obtain migration progress of a Share" msgstr "Bir Paylaşımın göç sürecini al" msgid "Overview" msgstr "Genel Görünüm" msgid "Password" msgstr "Parola" msgid "Passwords do not match." msgstr "Parolalar eşleşmiyor." msgid "Preserve Metadata" msgstr "Metaveriyi Koru" msgid "Preserve Snapshots" msgstr "Anlık Görüntüleri Koru" msgid "Project" msgstr "Proje" msgid "Projects with access to share group type" msgstr "Paylaşım grubu türüne erişimi olan projeler" msgid "Projects with access to share type" msgstr "Paylaşım türüne erişimi olan projeler" msgid "Protocol" msgstr "İletişim Kuralı" msgid "Public" msgstr "Açık" msgid "Quota" msgstr "Kota" #, python-format msgid "Replica Details: %(replica_display_name)s" msgstr "Kopya Ayrıntıları: %(replica_display_name)s" msgid "Replica State" msgstr "Kopya Durumu" msgid "Replicas" msgstr "Kopyalar" msgid "Reset Replica State" msgstr "Kopya Durumunu Sıfırla" msgid "Reset Replica Status" msgstr "Kopya Durumunu Sıfırla" msgid "Reset Share Group Snapshot Status" msgstr "Paylaşım Grubu Anlık Görüntü Durumu" msgid "Reset Share Group Status" msgstr "Paylaşım Grubu Durumunu Sıfırla" msgid "Reset Status" msgstr "Durumu Sıfırla" msgid "Reset replica state" msgstr "Kopya durumunu sıfırla" msgid "Reset replica status" msgstr "Kopya durumunu sıfırla" msgid "Reset state" msgstr "Durumu sıfırla" msgid "Reset status" msgstr "Durumu sıfırla" #, python-format msgid "Reseting replica ('%(id)s') state from '%(from)s' to '%(to)s'." msgstr "Kopya ('%(id)s') durumu '%(from)s' den '%(to)s' e sıfırlanıyor." #, python-format msgid "Reseting replica ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "Kopya ('%(id)s') durumu '%(from)s' den '%(to)s' e yeniden ayarlanıyor." #, python-format msgid "Reseting share group ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "('%(id)s') paylaşım grubu durumu '%(from)s' den '%(to)s' e sıfırlanıyor." #, python-format msgid "" "Reseting share group snapshot ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "" "Paylaşım grubu anlık görüntüsü ('%(id)s') durumu '%(from)s' den '%(to)s' e " "yeniden ayarlanıyor." msgid "Resync" msgstr "Yeniden eşzamanla" msgid "Resync Replica" msgstr "Kopyayı Yeniden Eşzamanla" msgid "Resync replica" msgstr "Kopyayı yeniden eş zamanla" #, python-format msgid "Resync'ing replica '%s'" msgstr "Kopya '%s' yeniden eş zamanlanıyor" msgid "Revert Share" msgstr "Paylaşımı Geri Döndür" msgid "Revert Share to a Snapshot" msgstr "Paylaşımı Anlık Görüntüye Geri Al" msgid "Revert share to a snapshot" msgstr "Paylaşımı bir anlık görüntüye geri al" msgctxt "Current status of share" msgid "Reverting Error" msgstr "Geri Alma Hatası" msgid "Rules" msgstr "Kurallar" msgid "Save Changes" msgstr "Değişiklikleri Kaydet" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "Güvenlik Servisi Ayrıntıları: %(service_display_name)s" msgid "Security Service Overview" msgstr "Güvenlik Servisi Genel Görünümü" msgid "Security Services" msgstr "Güvenlik Servisleri" msgid "Security services within share network" msgstr "Paylaşım ağındaki güvenlik servisleri" msgid "Segmentation Id" msgstr "Dilimlendirme Kimliği" msgid "Selected projects" msgstr "Seçili projeler" msgid "Selected security services" msgstr "Seçili güvenlik servisleri" msgid "Server" msgstr "Sunucu" msgid "Set Replica as Active" msgstr "Kopyayı Etkin olarak Ayarla" msgid "Set as Active" msgstr "Etkin olarak Ayarla" msgid "Set maximum quotas for the project." msgstr "Proje için azami kotaları ayarla." #, python-format msgid "Setting replica \"%s\" as active..." msgstr "\"%s\" kopyası etkin olarak ayarlanıyor..." #, python-format msgid "Share \"%(s)s\" has been reverted to \"%(ss)s\" snapshot successfully" msgstr "Paylaşım \"%(s)s\" \"%(ss)s\" anlık görüntüsüne başarıyla geri alındı" #, python-format msgid "Share Details: %(share_display_name)s" msgstr "Paylaşım Ayrıntıları: %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "Paylaşım Ayrıntıları: %(share_name)s" msgid "Share Group" msgstr "Paylaşım Grubu" #, python-format msgid "Share Group Details: %s" msgstr "Paylaşım Grubu Ayrıntıları: %s" msgid "Share Group Name" msgstr "Paylaşım Grubu İsmi" msgid "Share Group Overview" msgstr "Paylaşım Grubu Genel Görünümü" msgid "Share Group Snapshot" msgstr "Paylaşım Grubu Anlık Görüntüsü" #, python-format msgid "Share Group Snapshot Details: %(sgs_display_name)s" msgstr "Paylaşım Grubu Anlık Görüntü Ayrıntıları: %(sgs_display_name)s" msgid "Share Group Snapshot Overview" msgstr "Paylaşım Grubu Anlık Görüntüsü Genel Görünümü" msgid "Share Group Snapshots" msgstr "Paylaşım Grubu Anlık Görüntüleri" msgid "Share Group Type" msgstr "Paylaşım Grubu Türü" msgid "Share Group Types" msgstr "Paylaşım Grubu Türleri" msgid "Share Groups" msgstr "Paylaşım Grupları" msgid "Share ID" msgstr "Paylaşım Kimliği" #, python-format msgid "Share Instance Details: %s" msgstr "Paylaşım Sunucusu Ayrıntıları: %s" msgid "Share Instance Overview" msgstr "Paylaşım Sunucusu Genel Görünümü" msgid "Share Instances" msgstr "Paylaşım Sunucuları" msgid "Share Name" msgstr "Paylaşım İsmi" msgid "Share Network" msgstr "Paylaşım Ağı" #, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "Paylaşım Ağı Ayrıntıları: %(network_display_name)s" msgid "Share Network Info" msgstr "Paylaşım Ağı Bilgisi" msgid "Share Network Overview" msgstr "Paylaşım Ağı Genel Görünümü" msgid "Share Networks" msgstr "Paylaşım Ağları" msgid "Share Overview" msgstr "Paylaşım Genel Görünümü" msgid "Share Protocol" msgstr "Paylaşım Protokolü" #, python-format msgid "Share Replicas: %(share_display_name)s" msgstr "Paylaşım Kopyaları: %(share_display_name)s" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "Paylaşım Kuralları: %(share_display_name)s" msgid "Share Server" msgstr "Paylaşım Sunucu" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "Paylaşım Sunucusu Ayrıntıları: %(server_name)s" msgid "Share Server Id" msgstr "Paylaşım Sunucu Kimliği" msgid "Share Server Overview" msgstr "Paylaşım Sunucusu Genel Görünümü" msgid "Share Servers" msgstr "Paylaşım Sunucuları" msgid "Share Snapshot Name" msgstr "Paylaşım Anlık Görüntü İsmi" msgid "Share Snapshot Overview" msgstr "Paylaşım Anlık Görüntüsü Genel Görünümü" msgid "Share Snapshot Rules" msgstr "Paylaşım Anlık Görüntü Kuralları" msgid "Share Snapshots" msgstr "Paylaşım Anlık Görüntüleri" msgid "Share Snapshots Storage" msgstr "Paylaşım Anlık Görüntüleri Depolama" msgid "Share Source" msgstr "Paylaşım Kaynağı" msgid "Share Storage" msgstr "Paylaşım Depolama" msgid "Share Type" msgstr "Paylaşım Türü" msgid "Share Types" msgstr "Paylaşım Türleri" msgid "Share Types (multiple available)" msgstr "Paylaşım Türleri (birden çok kullanılabilir)" msgid "Share Types (one available)" msgstr "Paylaşım Türleri (biri kullanılabilir)" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "" "Kotanızda yalnız %(avail)iGiB olduğundan paylaşım %(req)iGiB olarak " "büyütülemedi." msgid "Share gigabytes" msgstr "Paylaşım gigabayt" msgid "Share name to be assigned" msgstr "Atanacak paylaşım adı" #, python-format msgid "Share replica %s has been deleted." msgstr "Paylaşım kopyası %s silindi." #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "" "Paylaşım boyutu anlık görüntü boyutuna eşit ya da boyutundan fazla olmalı " "(%sGiB)" msgid "Share snapshot gigabytes" msgstr "Paylaşım anlık görüntü gigabaytları" msgid "Share snapshots" msgstr "Paylaşım anlık görüntüleri" msgid "Share types" msgstr "Paylaşım türleri" msgid "Shares" msgstr "Paylaşımlar" msgid "Shares Networks" msgstr "Paylaşım Ağları" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "Boyut" msgid "Size (GiB)" msgstr "Boyut (GiB)" msgid "Snapshot" msgstr "Anlık görüntü" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "Anlık Görüntü Ayrıntıları: %(snapshot_display_name)s" #, python-format msgid "Snapshot Rules: %(snapshot_display_name)s" msgstr "Anlık Görüntü Kuralları: %(snapshot_display_name)s" msgid "Source" msgstr "Kaynak" msgid "Source Share Group Snapshot" msgstr "Paylaşım Grubu Anlık Görüntüsünü Kaynak Et" msgid "Source Type" msgstr "Kaynak Türü" msgid "" "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." msgstr "" "Paylaşım için yeni paylaşım ağını belirtin. Göç eden paylaşımın mevcut " "paylaşım ağını koruması gerekiyorsa bu parametreyi belirtmeyin." msgid "" "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." msgstr "" "Paylaşım için yeni paylaşım türünü belirtin. Göç eden paylaşımın mevcut " "paylaşım türünü koruması gerekiyorsa bu parametreyi belirtmeyin." msgid "Start migration" msgstr "Göçü başlat" msgid "Status" msgstr "Durum" #, python-format msgid "Successfully created security service: %s" msgstr "Güvenlik servisi başarıyla oluşturuldu: %s" #, python-format msgid "Successfully created share group type: %s" msgstr "Başarıyla paylaşım grubu türü oluşturuldu: %s" #, python-format msgid "Successfully created share network: %s" msgstr "Paylaşım ağı başarıyla oluşturuldu: %s" #, python-format msgid "Successfully created share type: %s" msgstr "Paylaşım türü başarıyla oluşturuldu: %s" #, python-format msgid "Successfully sent the request to cancel migration of share: %s." msgstr "Paylaşımın göç iptali için istek başarıyla gönderildi: %s." #, python-format msgid "Successfully sent the request to complete migration of share: %s." msgstr "Paylaşım göçünün tamamlanması isteği başarıyla gönderildi: %s." #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "Paylaşımı yönetme isteği başarıyla gönderildi: %s" #, python-format msgid "Successfully sent the request to migrate share: %s." msgstr "İstek göç paylaşımına başarıyla gönderildi: %s." #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "Paylaşımın yönetim iptali isteği başarıyla gönderildi: %s" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "'%s' paylaşım türü için ek özellikler başarıyla güncellendi." #, python-format msgid "Successfully updated group specs for share group type '%s'." msgstr "'%s' paylaşım grubu türü için grup özellikleri başarıyla güncellendi." #, python-format msgid "Successfully updated security service \"%s\"" msgstr "Güvenlik servisi \"%s\" başarıyla güncellendi" #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "Paylaşım boyutu anlık görüntü boyutundan az olamaz (%sGiB)" msgid "Type" msgstr "Tür" msgid "Unable to add rule." msgstr "Kural eklenemedi." msgid "Unable to add snapshot rule." msgstr "Anlık görüntü kuralı eklenemedi." #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "%s paylaşımının göçü şu an iptal edilemiyor." #, python-format msgid "Unable to complete migration of share %s." msgstr "%s paylaşımının göçü tamamlanamadı." msgid "Unable to create security service." msgstr "Güvenlik servisi oluşturulamıyor." msgid "Unable to create share group snapshot." msgstr "Paylaşım grubu anlık görüntüsü oluşturulamadı." msgid "Unable to create share group type." msgstr "Paylaşım grubu türü oluşturulamadı." msgid "Unable to create share group." msgstr "Paylaşım grubu oluşturulamıyor." msgid "Unable to create share network." msgstr "Paylaşım ağı oluşturulamadı." msgid "Unable to create share replica." msgstr "Paylaşım kopyası oluşturulamadı." msgid "Unable to create share snapshot." msgstr "Paylaşım anlık görüntüsü oluşturulamıyor." msgid "Unable to create share type." msgstr "Paylaşım türü oluşturulamıyor." msgid "Unable to create share." msgstr "Paylaşım oluşturulamadı." #, python-format msgid "Unable to create share. %s" msgstr "Paylaşım oluşturulamadı. %s" #, python-format msgid "Unable to delete replica \"%s\"." msgstr "Kopya \"%s\" silinemedi." #, python-format msgid "Unable to delete rule \"%s\"." msgstr "\"%s\" kuralı silinemedi." #, python-format msgid "Unable to delete share \"%s\". " msgstr "\"%s\" paylaşımı silinemedi. " #, python-format msgid "" "Unable to delete share group snapshot \"%s\". One or more share groups " "depend on it." msgstr "" "\"%s\" paylaşım grubu anlık görüntüsü silinemiyor. Bir ya da daha fazla " "paylaşım grubu ona bağımlı." #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "" "\"%s\" anlık görüntüsü silinemedi. Bir ya da fazla paylaşım ona bağımlı." #, python-format msgid "Unable to delete snapshot rule \"%s\"." msgstr "Anlık görüntü kuralı \"%s\" silinemiyor." msgid "Unable to extend share." msgstr "Paylaşım genişletilemedi." msgid "Unable to get information about share group type access." msgstr "Paylaşım grubu tür erişimiyle ilgili bilgi alınamadı." msgid "Unable to get information about share type access." msgstr "Paylaşım türü erişimi hakkında bilgi alınamadı." msgid "Unable to get list of projects." msgstr "Proje listesi alınamadı." msgid "Unable to get the security services hosts" msgstr "Güvenlik servisi sunucuları alınamadı" #, python-format msgid "Unable to get the specified share group '%s' for snapshot creation." msgstr "" "Anlık görüntü oluşturmak için belirtilen paylaşım grubu '%s' alınamadı." msgid "Unable to load the specified share group snapshot." msgstr "Belirtilen paylaşım grubu anlık görüntüsü yüklenemedi." msgid "Unable to load the specified snapshot." msgstr "Belirtilen anlık görüntü yüklenemedi." msgid "Unable to manage share" msgstr "Paylaşım yönetilemiyor" #, python-format msgid "Unable to migrate share %s." msgstr "%s paylaşımı göç ettirilemedi." #, python-format msgid "Unable to obtain progress of migration of share %s at this moment." msgstr "%s paylaşımının göç yüzdesi şu an alınamıyor." #, python-format msgid "Unable to reset state of replica '%s'." msgstr "'%s' kopyasının durumu sıfırlanamadı." #, python-format msgid "Unable to reset status of replica '%s'." msgstr "'%s' kopyasının durumu sıfırlanamadı." #, python-format msgid "Unable to reset status of share group '%s'." msgstr "'%s' paylaşım grubu durumu sıfırlanamadı." #, python-format msgid "Unable to reset status of share group snapshot '%s'." msgstr "'%s' paylaşım grubu anlık görüntüsü durumu sıfırlanamıyor." #, python-format msgid "Unable to resync replica '%s'." msgstr "Kopya '%s' yeniden eş zamanlanamadı." msgid "Unable to retrieve list of projects." msgstr "Projelerin listesi alınamadı." msgid "Unable to retrieve quotas." msgstr "Kotalar alınamıyor." #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "Kopya %s ayrıntıları alınamadı." #, python-format msgid "Unable to retrieve replica '%s'." msgstr "Kopya '%s' alınamadı." #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "Güvenlik servisi '%s' ayrıntıları alınamıyor." msgid "Unable to retrieve security services" msgstr "Güvenlik servisleri alınamadı" msgid "Unable to retrieve security_service." msgstr "security_service alınamadı." msgid "Unable to retrieve share details." msgstr "Paylaşım ayrıntıları alınamadı." #, python-format msgid "Unable to retrieve share group '%s'." msgstr "Paylaşım grubu '%s' alınamıyor." msgid "Unable to retrieve share group details." msgstr "Paylaşım grubu ayrıntıları alınamıyor." #, python-format msgid "Unable to retrieve share group snapshot '%s'." msgstr "Paylaşım grubu anlık görüntüsü '%s' alınamıyor." msgid "Unable to retrieve share group snapshot details." msgstr "Paylaşım grubu anlık görüntü ayrıntıları alınamıyor." msgid "Unable to retrieve share group snapshot list." msgstr "Paylaşım grubu anlık görüntü listesi alınamıyor." msgid "Unable to retrieve share group snapshot." msgstr "Paylaşım grubu anlık görüntüsü alınamıyor." msgid "Unable to retrieve share group snapshots." msgstr "Paylaşım grubu anlık görüntüleri alınamadı." msgid "Unable to retrieve share group types." msgstr "Paylaşım grubu türleri alınamadı." msgid "Unable to retrieve share group." msgstr "Paylaşım grubu alınamıyor." msgid "Unable to retrieve share groups." msgstr "Paylaşım grupları alınamadı." msgid "Unable to retrieve share instance details." msgstr "Paylaşım sunucusu ayrıntıları alınamadı." msgid "Unable to retrieve share instances." msgstr "Paylaşım sunucuları alınamadı." msgid "Unable to retrieve share limit information." msgstr "Paylaşım sınır bilgisi alınamadı." msgid "Unable to retrieve share list." msgstr "Paylaşım listesi alınamadı." msgid "Unable to retrieve share network details." msgstr "Paylaşım ağı ayrıntıları alınamıyor." msgid "Unable to retrieve share network." msgstr "Paylaşım ağı alınamadı." msgid "Unable to retrieve share networks" msgstr "Paylaşım ağları alınamadı" msgid "Unable to retrieve share replicas." msgstr "Paylaşım kopyaları alınamadı." msgid "Unable to retrieve share rules." msgstr "Paylaşım kuralları alınamadı." msgid "Unable to retrieve share server details." msgstr "Paylaşım sunucusu ayrıntıları alınamıyor." msgid "Unable to retrieve share servers" msgstr "Paylaşım sunucuları alınamadı" msgid "Unable to retrieve share snapshot list." msgstr "Paylaşım anlık görüntü listesi alınamadı." msgid "Unable to retrieve share snapshot rules." msgstr "Paylaşım anlık görüntü kuralları alınamadı." msgid "Unable to retrieve share snapshot." msgstr "Paylaşım anlık görüntüsü alınamıyor." msgid "Unable to retrieve share snapshots list." msgstr "Paylaşım anlık görüntü listesi alınamıyor." msgid "Unable to retrieve share snapshots." msgstr "Paylaşım anlık görüntüleri alınamadı." msgid "Unable to retrieve share types." msgstr "Paylaşım türleri alınamadı." msgid "Unable to retrieve share." msgstr "Paylaşım alınamıyor." #, python-format msgid "Unable to retrieve share. %s" msgstr "Paylaşım alınamıyor. %s" msgid "Unable to retrieve share_gruop_type." msgstr "Paylaşım grup bütür alınamadı." msgid "Unable to retrieve share_type." msgstr "share_type alınamadı." msgid "Unable to retrieve snapshot details." msgstr "Anlık görüntü ayrıntıları alınamıyor." msgid "Unable to retrieve snapshot." msgstr "Anlık görüntü alınamıyor." msgid "Unable to retrieve volume details." msgstr "Birim ayrıntıları alınamıyor." msgid "Unable to revert share to the snapshot." msgstr "Paylaşım anlık görüntüye geri alınamadı." msgid "Unable to set project quotas." msgstr "Proje kotaları ayarlanamıyor." #, python-format msgid "Unable to set replica '%s' as active." msgstr "'%s' kopyası etkin olarak ayarlanamadı." msgid "Unable to unmanage share." msgstr "Paylaşım yönetim iptali başarısız." #, python-format msgid "Unable to update access for share group type \"%s\"." msgstr "\"%s\" paylaşım grubu türü için erişim güncellenemedi." #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "Paylaşım türü \"%s\" için erişim güncellenemiyor." msgid "Unable to update default quotas." msgstr "Öntanımlı kotalar güncellenemedi." msgid "Unable to update extra_specs for share type." msgstr "Paylaşım türü için ek_özellikler başarıyla güncellendi." msgid "Unable to update group_specs for share group type." msgstr "Paylaşım grubu türü için grup özellikleri güncellenemedi." msgid "Unable to update security service." msgstr "Güvenlik servisi güncellenemedi." msgid "Unable to update share group snapshot." msgstr "Paylaşım grubu anlık görüntüsü güncellenemedi." msgid "Unable to update share group type." msgstr "Paylaşım grubu türü güncellenemedi." msgid "Unable to update share group." msgstr "Paylaşım grubu güncellenemiyor." msgid "Unable to update share metadata." msgstr "Paylaşım metaverisi güncellenemedi." #, python-format msgid "Unable to update share network \"%s\"." msgstr "Paylaşım ağı \"%s\" güncellenemedi." msgid "Unable to update share network." msgstr "Paylaşım ağı güncellenemedi." msgid "Unable to update share snapshot." msgstr "Paylaşım anlık görüntüsü güncellenemedi." msgid "Unable to update share type." msgstr "Paylaşım türü güncellenemiyor." msgid "Unable to update share." msgstr "Paylaşım güncellenemedi." msgid "Unknown" msgstr "Bilinmiyor" msgid "Unmanage" msgstr "Yönetimi Bırak" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "Yönetimi Bırakma Hatası" msgid "Unmanage Share" msgstr "Paylaşım Yönetimini Bırak" msgid "Update" msgstr "Güncelle" msgid "Update Share Group" msgstr "Paylaşım Grubunu Güncelle" msgid "Update Share Group Snapshot" msgstr "Paylaşım Grubu Anlık Görüntüsünü Güncelle" msgid "Update Share Group Type" msgstr "Paylaşım Grubu Türünü Güncelle" msgid "Update Share Network" msgstr "Paylaşım Ağını Güncelle" msgid "Update Share Snapshot" msgstr "Paylaşım Anlık Görüntüsünü Güncelle" msgid "Update Share Type" msgstr "Paylaşım Türünü Güncelle" msgid "Update Share group Type" msgstr "Paylaşım grubu Türünü Güncelle" msgid "Updated At" msgstr "Güncelleme Zamanı" #, python-format msgid "Updated access for share group type \"%s\"." msgstr "\"%s\" paylaşım grubu türü için erişimi güncelle." #, python-format msgid "Updated access for share type \"%s\"." msgstr "\"%s\" paylaşım türü için erişim güncellendi." #, python-format msgid "Updated share network \"%s\"." msgstr "\"%s\" paylaşım ağı güncellendi." #, python-format msgid "Updating share \"%s\"" msgstr "\"%s\" paylaşımı güncelleniyor" #, python-format msgid "Updating share group \"%s\"" msgstr "\"%s\" paylaşım grubu güncelleniyor" #, python-format msgid "Updating share group snapshot \"%s\"" msgstr "Paylaşım grubu anlık görüntüsü \"%s\" güncelleniyor" #, python-format msgid "Updating share metadata \"%s\"" msgstr "Paylaşım metaverisi \"%s\" güncelleniyor" #, python-format msgid "Updating share network \"%s\"" msgstr "Paylaşım ağı \"%s\" güncelleniyor" #, python-format msgid "Updating share snapshot \"%s\"" msgstr "Paylaşım anlık görüntüsü \"%s\" güncelleniyor" msgid "Use share group snapshot as a source" msgstr "Paylaşım grubu anlık görüntüsünü kaynak olarak kullan" msgid "Use snapshot as a source" msgstr "Anlık görüntüyü kaynak olarak kullan" msgid "User" msgstr "Kullanıcı" msgid "Visibility" msgstr "Görünürlük" msgid "Writable" msgstr "Yazılabilir" msgid "key=value pairs per line can be set" msgstr "satır başına anahtar=değer çiftleri ayarlanabilir" manila-ui-2.13.0/manila_ui/locale/zh_CN/000077500000000000000000000000001323215354300176505ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/zh_CN/LC_MESSAGES/000077500000000000000000000000001323215354300214355ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/locale/zh_CN/LC_MESSAGES/django.po000066400000000000000000000622061323215354300232450ustar00rootroot00000000000000# sunanchen , 2016. #zanata # zhongjun , 2016. #zanata # zzxwill , 2016. #zanata # Bin , 2017. #zanata # WenChao Xiang , 2017. #zanata # liujunpeng , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui 2.10.2.dev14\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-13 12:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-09-16 07:16+0000\n" "Last-Translator: WenChao Xiang \n" "Language-Team: Chinese (China)\n" "Language: zh-CN\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=1; plural=0\n" #, python-format msgid "%sGiB" msgstr "%sGiB" msgid "(Quota exceeded)" msgstr "(超过配额)" msgid "Access Key" msgstr "访问密钥" msgid "Access Level" msgstr "访问级别" msgid "Access To" msgstr "访问" msgid "Access Type" msgstr "访问类型" msgid "Access to" msgstr "访问" msgctxt "Current status of share network" msgid "Active" msgstr "活动" msgctxt "Current status of share server" msgid "Active" msgstr "活动" msgid "Add" msgstr "增加" msgid "Add Rule" msgstr "增加规则" msgid "Add Security Service" msgstr "增加安全服务" msgid "Add rule" msgstr "增加规则" msgid "Add security services to share network." msgstr "给共享网络增加安全服务" msgid "All keys and values must be in range from 1 to 255." msgstr "所有的键和值都必须在1到255之间" msgid "Allow project access to share type." msgstr "允许项目连接到共享类型" msgid "At least one security service must be specified." msgstr "至少指定一项安全服务" msgid "Availability Zone" msgstr "可用域" msgid "Availability zone" msgstr "可用域" msgctxt "Current status of replica" msgid "Available" msgstr "可用" msgctxt "Current status of share" msgid "Available" msgstr "可用" msgctxt "Current status of snapshot" msgid "Available" msgstr "可用" msgid "Available projects" msgstr "可用项目" msgid "Available security services" msgstr "可用安全服务" msgid "Cancel Migration" msgstr "取消迁移" msgid "Cancel migration" msgstr "取消迁移" msgid "Cancel migration of a Share" msgstr "取消迁移共享" msgid "Choose a snapshot" msgstr "选择一个快照" msgid "Complete Migration" msgstr "完成迁移" msgid "Complete migration" msgstr "完成迁移" msgid "Complete migration of a Share" msgstr "完成共享迁移" msgid "Confirm Migration Cancelling of Share" msgstr "确认共享迁移的取消" msgid "Confirm Migration Completion of Share" msgstr "确认共享迁移的完成" msgid "Confirm Obtaining migration progress of Share" msgstr "确认获取共享迁移的进度" msgid "Confirm Password" msgstr "确认密码" msgid "Confirm Unmanage Share" msgstr "确认取消管理共享" msgid "Create" msgstr "创建" msgid "Create Replica" msgstr "创建副本" msgid "Create Security Service" msgstr "创建安全服务" msgid "Create Share" msgstr "创建共享" msgid "Create Share Network" msgstr "创建共享网络" msgid "Create Share Snapshot" msgstr "创建共享快照" msgid "Create Share Type" msgstr "创建共享类型" msgid "Create a Share" msgstr "创建共享" msgid "Created At" msgstr "创建于" msgctxt "Current status of replica" msgid "Creating" msgstr "创建中" msgctxt "Current status of share" msgid "Creating" msgstr "创建中" msgctxt "Current status of share server" msgid "Creating" msgstr "正在创建" msgctxt "Current status of snapshot" msgid "Creating" msgstr "正在创建" #, python-format msgid "Creating replica for share \"%s\"." msgstr "为共享\"%s\".创建副本。" #, python-format msgid "Creating rule for \"%s\"" msgstr "为 \"%s\"创建规则" #, python-format msgid "Creating share \"%s\"" msgstr "创建共享\"%s\"" #, python-format msgid "Creating share snapshot \"%s\"." msgstr "创建共享快照\"%s\"中" #, python-format msgid "Creating snapshot rule for \"%s\"" msgstr "创建快照规则\"%s\"" msgid "Current Size (GiB)" msgstr "当前大小(GiB)" msgid "DNS IP" msgstr "DNS IP地址" msgid "Delete Security Service" msgid_plural "Delete Security Services" msgstr[0] "删除安全服务" msgid "Delete Share Group Snapshot" msgid_plural "Delete Share Group Snapshots" msgstr[0] "删除共享组快照" msgid "Deleted Security Service" msgid_plural "Deleted Security Services" msgstr[0] "删除安全服务" msgctxt "Current status of replica" msgid "Deleting" msgstr "删除中" msgctxt "Current status of share" msgid "Deleting" msgstr "删除中" msgid "Description" msgstr "描述" msgid "Destination host and pool where share will be migrated to." msgstr " 共享迁移到的目的主机和池。" msgid "Domain" msgstr "域名" msgid "Driver handles share servers" msgstr "共享服务器" msgid "Driver options ('volume_id' for Generic driver, etc...)" msgstr "Driver选项(例如,设置'volume_id'为Generic driver)" #, python-format msgid "Duplicated keys '%s'." msgstr "复制密钥'%s'" msgid "Edit" msgstr "编辑" msgid "Edit Security Service" msgstr "编辑安全服务" msgid "Edit Share" msgstr "编辑共享" msgid "Edit Share Metadata" msgstr "编辑共享元数据" msgid "Edit Share Network" msgstr "编辑共享网络" msgid "" "Enforces migration of the share snapshots to the destination. If set to " "True, host-assisted migration will not be attempted." msgstr "强制共享快照迁移到目的地。如果为True,主机辅助迁移将不会尝试。" msgid "" "Enforces migration to be nondisruptive. If set to True, host-assisted " "migration will not be attempted." msgstr "强制迁移不干扰。如果设置为True,将不尝试主机辅助迁移。" msgid "" "Enforces migration to keep the share writable while contents are being " "moved. If set to True, host-assisted migration will not be attempted." msgstr "" "当内容被移动时,强制迁移保持共享可写。如果为True,主机辅助迁移将不会尝试。" msgid "" "Enforces migration to preserve all file metadata when moving its contents. " "If set to True, host-assisted migration will not be attempted." msgstr "" "当移动它的内容时,强制迁移保留所有文件元数据。如果为True,主机辅助迁移将不会" "尝试。" msgid "" "Enforces the use of the host-assisted migration approach, which bypasses " "driver optimizations." msgstr "强制使用主机辅助迁移方法,绕过驱动最优参数。" msgctxt "Current status of replica" msgid "Error" msgstr "错误" msgctxt "Current status of share" msgid "Error" msgstr "错误" msgctxt "Current status of share network" msgid "Error" msgstr "错误" msgctxt "Current status of share server" msgid "Error" msgstr "错误" msgctxt "Current status of snapshot" msgid "Error" msgstr "错误" msgid "Expected only pairs of key=value." msgstr "只支持键值对的方式key=value" msgid "Export location" msgstr "导入位置" msgid "Export location of share. Example for NFS: 1.2.3.4:/path/to/share" msgstr "导入共享的位置。例如,NFS: 1.2.3.4:/path/to/share" msgid "Extend" msgstr "扩展" msgid "Extend Share" msgstr "扩展共享" #, python-format msgid "Extend share \"%s\"" msgstr "扩展共享 \"%s\"" msgctxt "Current status of share" msgid "Extending Error" msgstr "扩展错误" msgid "Extra specs" msgstr "额外规范" msgid "Force Host Assisted Migration" msgstr "强制主机协助迁移" msgid "From here you can update share network info. " msgstr "您可在此处更新共享网络信息。" msgid "From here you can update the default quotas (max limits)." msgstr "您可在此处更新默认配额(上限)。" msgid "Get migration progress" msgstr "获取迁移进度" msgid "" "Got improper value for field 'driver_options'. Expected only pairs of " "key=value." msgstr "'driver_options'设置了不正确的值。只支持键值对的方式key=value" msgid "Host" msgstr "主机" msgid "Host of share" msgstr "共享主机" msgid "Host to migrate share" msgstr "选择要迁移的主机。" msgid "Host where share is located, example: some.host@driver[#pool]" msgstr "共享服务所处的主机,比如some.host@driver[#pool]" msgid "ID" msgstr "ID" msgid "IP Version" msgstr "IP版本" msgid "Id" msgstr "Id" #, python-format msgid "" "Improper value set to required extra spec " "'spec_driver_handles_share_servers'. Allowed values are %s. Case insensitive." msgstr "" "额外规范中'spec_driver_handles_share_servers'的值设置的不正确。允许的值为%s。" "不区分大小写" msgctxt "Current status of share server" msgid "In-use" msgstr "正在使用" msgctxt "Current status of snapshot" msgid "In-use" msgstr "正在使用" msgctxt "Current status of share network" msgid "Inactive" msgstr "失效" #, python-format msgid "Key '%s' has improper length." msgstr "密钥'%s'长度不符合要求" #, python-format msgid "Key can not contain spaces. See string '%s'." msgstr "密钥不能包含空格。参看字符串'%s'。" #, python-format msgid "Keys should not contain spaces. Error in '%s'." msgstr "密钥不能包含空格。'%s'中存在错误" msgid "Make visible for all" msgstr "对所有人可见" msgid "Manage" msgstr "管理" msgctxt "Current status of share" msgid "Manage Error" msgstr "管理错误" msgid "Manage Replicas" msgstr "管理副本" msgid "Manage Rules" msgstr "管理规则" msgid "Manage Share" msgstr "管理共享" msgid "Manage Share Type Access" msgstr "管理共享类型的访问权限" msgid "Metadata" msgstr "元数据" msgid "Migrate Share" msgstr "共享迁移" msgid "Migrate a Share" msgstr "迁移共享" msgctxt "Current status of share" msgid "Migrating" msgstr "迁移中" msgctxt "Current status of share" msgid "Migrating to" msgstr "正在迁移至" #, python-format msgid "Migration of share %(name)s is at %(progress)s percent." msgstr "共享%(name)s已迁移百分之%(progress)s。" msgid "" "Modified project information and members, but unable to modify project " "quotas." msgstr "已修改项目信息和成员,但是无法修改项目配额。" msgid "Name" msgstr "名称" msgid "Network Type" msgstr "网络类型" msgid "Networks" msgstr "网络" msgid "Neutron Net" msgstr "Neutron网络" msgid "Neutron Subnet" msgstr "Neutron子网" msgid "New Size (GiB)" msgstr "新大小(GiB)" msgid "New share network to be set in migrated share" msgstr " 在迁移共享中,设置新的共享网络" msgid "New share type to be set in migrating share" msgstr "在迁移共享中设置共享类型" msgid "New size must be greater than current size." msgstr "新大小必须大于当前大小" msgid "No projects found." msgstr "没有找到任何项目" msgid "No projects selected." msgstr "为选择任何项目" msgid "No security services found." msgstr "未发现安全服务" msgid "No security services selected." msgstr "未选择安全服务" msgid "No source, empty share" msgstr "没有源,空的共享" msgid "Nondisruptive" msgstr "不干扰" msgid "Nova Net" msgstr "Nova网络" msgid "Obtain Progress" msgstr "获取进度" msgid "Obtain migration progress of a Share" msgstr "获取共享迁移的进度" msgid "Overview" msgstr "概览" msgid "Password" msgstr "密码" msgid "Passwords do not match." msgstr "密码不匹配" msgid "Preserve Metadata" msgstr "保护元数据" msgid "Preserve Snapshots" msgstr "保留快照" msgid "Project" msgstr "项目" msgid "Projects with access to share type" msgstr "项目访问分享类型" msgid "Protocol" msgstr "协议" msgid "Public" msgstr "公有" msgid "Quota" msgstr "配额" #, python-format msgid "Replica Details: %(replica_display_name)s" msgstr "副本详情:%(replica_display_name)s" msgid "Replica State" msgstr "副本状态" msgid "Replicas" msgstr "副本" msgid "Reset Replica State" msgstr "重置副本状态" msgid "Reset Replica Status" msgstr "重置副本状态" msgid "Reset replica state" msgstr "重置副本状态" msgid "Reset replica status" msgstr "重置副本状态" msgid "Reset state" msgstr "重置状态" msgid "Reset status" msgstr "重置状态" #, python-format msgid "Reseting replica ('%(id)s') state from '%(from)s' to '%(to)s'." msgstr "正在重置副本 ('%(id)s') 状态从'%(from)s'到 '%(to)s'。" #, python-format msgid "Reseting replica ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "重置副本 ('%(id)s') 状态从'%(from)s'到 '%(to)s'。" #, python-format msgid "" "Reseting share group snapshot ('%(id)s') status from '%(from)s' to '%(to)s'." msgstr "重置共享组快照('%(id)s') 状态从'%(from)s'至'%(to)s'" msgid "Resync" msgstr "重新同步" msgid "Resync Replica" msgstr "重新同步副本" msgid "Resync replica" msgstr "重新同步副本" #, python-format msgid "Resync'ing replica '%s'" msgstr "重新同步副本'%s'" msgid "Rules" msgstr "规则" msgid "Save Changes" msgstr "保存变更" #, python-format msgid "Security Service Details: %(service_display_name)s" msgstr "安全服务详情: %(service_display_name)s" msgid "Security Service Overview" msgstr "安全服务概览" msgid "Security Services" msgstr "安全服务" msgid "Security services within share network" msgstr "共享网络内的安全服务" msgid "Segmentation Id" msgstr "分段ID" msgid "Selected projects" msgstr "选择项目" msgid "Selected security services" msgstr "选择安全服务" msgid "Server" msgstr "主机" msgid "Set Replica as Active" msgstr "设置副本状态为Active" msgid "Set as Active" msgstr "设置为Active" msgid "Set maximum quotas for the project." msgstr "为项目设置最大配额" #, python-format msgid "Setting replica \"%s\" as active..." msgstr "设置副本\"%s\"状态为active。。。" #, python-format msgid "Share Details: %(share_display_name)s" msgstr "共享详情: %(share_display_name)s" #, python-format msgid "Share Details: %(share_name)s" msgstr "共享详情: %(share_name)s" msgid "Share Group Snapshots" msgstr "共享组快照" msgid "Share ID" msgstr "共享ID" #, python-format msgid "Share Instance Details: %s" msgstr "共享实例详情: %s" msgid "Share Instances" msgstr "共享实例" msgid "Share Name" msgstr "共享名称" msgid "Share Network" msgstr "共享网络" #, python-format msgid "Share Network Details: %(network_display_name)s" msgstr "共享网络详情: %(network_display_name)s" msgid "Share Network Info" msgstr "共享网络信息" msgid "Share Networks" msgstr "共享网络" msgid "Share Protocol" msgstr "共享协议" #, python-format msgid "Share Replicas: %(share_display_name)s" msgstr "共享副本: %(share_display_name)s" #, python-format msgid "Share Rules: %(share_display_name)s" msgstr "共享规则: %(share_display_name)s" msgid "Share Server" msgstr "共享服务器" #, python-format msgid "Share Server Details: %(server_name)s" msgstr "共享服务器详情: %(server_name)s" msgid "Share Server Id" msgstr "共享服务器Id" msgid "Share Servers" msgstr "共享服务器" msgid "Share Snapshots" msgstr "共享快照" msgid "Share Snapshots Storage" msgstr "共享快照存储" msgid "Share Source" msgstr "共享源" msgid "Share Storage" msgstr "共享存储" msgid "Share Type" msgstr "共享类型" msgid "Share Types" msgstr "共享类型" #, python-format msgid "" "Share cannot be extended to %(req)iGiB as you only have %(avail)iGiB of your " "quota available." msgstr "共享不能扩展到 %(req)iGiB,因为您的可用配额只有 %(avail)iGiB。" msgid "Share name to be assigned" msgstr "指定分享名称" #, python-format msgid "Share replica %s has been deleted." msgstr "共享副本'%s'已经被删除。" #, python-format msgid "Share size must be equal to or greater than the snapshot size (%sGiB)" msgstr "分享大小必须等于或者大于快照大小(%sGiB)" msgid "Shares" msgstr "共享" msgid "Shares Networks" msgstr "共享网络" msgid "Sid" msgstr "Sid" msgid "Size" msgstr "大小" msgid "Size (GiB)" msgstr "大小(GiB)" msgid "Snapshot" msgstr "快照" #, python-format msgid "Snapshot Details: %(snapshot_display_name)s" msgstr "快照详情: %(snapshot_display_name)s" #, python-format msgid "Snapshot Rules: %(snapshot_display_name)s" msgstr "快照规则:%(snapshot_display_name)s" msgid "Source" msgstr "源" msgid "" "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." msgstr "" "为共享指定新的共享网络。如果迁移共享被保留在它的当前共享网络时,不要指定这参" "数。" msgid "" "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." msgstr "" "为共享指定新的共享类型。如果迁移共享被保留在它的当前共享类型时,不要指定这个" "参数。" msgid "Start migration" msgstr "开始迁移" msgid "Status" msgstr "状态" #, python-format msgid "Successfully created security service: %s" msgstr "成功创建安全服务%s" #, python-format msgid "Successfully created share network: %s" msgstr "成功创建共享网络%s" #, python-format msgid "Successfully created share type: %s" msgstr "创建共享类型%s成功" #, python-format msgid "Successfully sent the request to cancel migration of share: %s." msgstr "成功发送取消共享: %s迁移的请求。" #, python-format msgid "Successfully sent the request to complete migration of share: %s." msgstr "成功发送完成共享迁移: %s的请求。" #, python-format msgid "Successfully sent the request to manage share: %s" msgstr "已成功发送管理卷 %s 的请求" #, python-format msgid "Successfully sent the request to migrate share: %s." msgstr "已成功发送迁移共享: %s的请求。" #, python-format msgid "Successfully sent the request to unmanage share: %s" msgstr "已成功发送取消管理卷 %s 的请求" #, python-format msgid "Successfully updated extra specs for share type '%s'." msgstr "成功更新共享类型的额外规范'%s'" #, python-format msgid "Successfully updated security service \"%s\"" msgstr "成功更新安全服务\"%s\"" #, python-format msgid "The share size cannot be less than the snapshot size (%sGiB)" msgstr "共享大小不能小于快照大小(%sGiB)" msgid "Type" msgstr "类型" msgid "Unable to add rule." msgstr "无法增加规则" msgid "Unable to add snapshot rule." msgstr "不能添加快照规则。" #, python-format msgid "Unable to cancel migration of share %s at this moment." msgstr "当前无法取消共享%s的迁移。" #, python-format msgid "Unable to complete migration of share %s." msgstr "无法完成共享: %s的迁移。" msgid "Unable to create security service." msgstr "无法创建安全服务" msgid "Unable to create share network." msgstr "无法创建共享网络" msgid "Unable to create share replica." msgstr "无法创建共享副本。" msgid "Unable to create share snapshot." msgstr "无法创建共享快照" msgid "Unable to create share type." msgstr "无法创建共享类型" msgid "Unable to create share." msgstr "无法创建共享" #, python-format msgid "Unable to delete replica \"%s\"." msgstr "无法删除副本'%s'。" #, python-format msgid "Unable to delete rule \"%s\"." msgstr "无法删除规则 \"%s\"" #, python-format msgid "Unable to delete share \"%s\". " msgstr "无法删除共享 \"%s\"" #, python-format msgid "" "Unable to delete share group snapshot \"%s\". One or more share groups " "depend on it." msgstr "无法删除共享组快照\"%s\",至少一个共享组与其存在依赖关系" #, python-format msgid "Unable to delete snapshot \"%s\". One or more shares depend on it." msgstr "无法删除快照\"%s\"。一个或多个共享正在使用" #, python-format msgid "Unable to delete snapshot rule \"%s\"." msgstr "不能删除快照规则\"%s\"。" msgid "Unable to extend share." msgstr "无法扩展共享" msgid "Unable to get information about share type access." msgstr "无法获得共享类型访问信息" msgid "Unable to get list of projects." msgstr "无法获得项目列表" msgid "Unable to get the security services hosts" msgstr "无法获得安全服务主机" msgid "Unable to load the specified snapshot." msgstr "无法加载指定快照" msgid "Unable to manage share" msgstr "无法管理共享" #, python-format msgid "Unable to migrate share %s." msgstr "无法迁移共享%s。" #, python-format msgid "Unable to obtain progress of migration of share %s at this moment." msgstr "当前无法获得共享%s的迁移进度。" #, python-format msgid "Unable to reset state of replica '%s'." msgstr "无法重置副本'%s'的状态。" #, python-format msgid "Unable to reset status of replica '%s'." msgstr "无法重置副本'%s'的状态。" #, python-format msgid "Unable to reset status of share group snapshot '%s'." msgstr "无法重置共享组快照'%s'的状态" #, python-format msgid "Unable to resync replica '%s'." msgstr "无法重新同步副本 '%s'。" msgid "Unable to retrieve list of projects." msgstr "无法检索项目列表" msgid "Unable to retrieve quotas." msgstr "无法检索配额" #, python-format msgid "Unable to retrieve replica %sdetails." msgstr "无法检索副本%s详情。" #, python-format msgid "Unable to retrieve replica '%s'." msgstr "无法检索副本'%s'。" #, python-format msgid "Unable to retrieve security service '%s' details." msgstr "无法检索安全服务详情'%s'" msgid "Unable to retrieve security services" msgstr "无法检索安全服务" msgid "Unable to retrieve security_service." msgstr "无法检索安全服务" msgid "Unable to retrieve share details." msgstr "无法检索共享详情" msgid "Unable to retrieve share instance details." msgstr "无法检索共享实例详情" msgid "Unable to retrieve share instances." msgstr "无法检索共享实例" msgid "Unable to retrieve share limit information." msgstr "无法检索共享限制信息" msgid "Unable to retrieve share list." msgstr "无法检索共享列表" msgid "Unable to retrieve share network details." msgstr "无法检索共享网络详情" msgid "Unable to retrieve share network." msgstr "无法检索共享网络" msgid "Unable to retrieve share networks" msgstr "无法检索共享网络" msgid "Unable to retrieve share replicas." msgstr "无法检索共享副本" msgid "Unable to retrieve share rules." msgstr "无法检索共享规则" msgid "Unable to retrieve share server details." msgstr "无法检索共享服务器详情" msgid "Unable to retrieve share servers" msgstr "无法检索共享服务器" msgid "Unable to retrieve share snapshots list." msgstr "无法检索共享快照列表" msgid "Unable to retrieve share snapshots." msgstr "无法检索共享快照" msgid "Unable to retrieve share." msgstr "无法检索共享" #, python-format msgid "Unable to retrieve share. %s" msgstr "无法检索共享。%s" msgid "Unable to retrieve share_type." msgstr "无法检索共享类型" msgid "Unable to retrieve snapshot details." msgstr "无法检索快照详情" msgid "Unable to retrieve snapshot." msgstr "无法检索快照" msgid "Unable to retrieve volume details." msgstr "无法检索卷详情" msgid "Unable to set project quotas." msgstr "无法设置项目配额" #, python-format msgid "Unable to set replica '%s' as active." msgstr "无法设置副本'%s'状态为active。" msgid "Unable to unmanage share." msgstr "无法取消管理共享" #, python-format msgid "Unable to update access for share type \"%s\"." msgstr "无法更新共享类型\"%s\"的访问权限" msgid "Unable to update default quotas." msgstr "无法更新默认配额" msgid "Unable to update extra_specs for share type." msgstr "无法更新共享类型的额外规范" msgid "Unable to update security service." msgstr "无法更新安全服务" msgid "Unable to update share metadata." msgstr "无法更新共享元数据" #, python-format msgid "Unable to update share network \"%s\"." msgstr "无法更新共享网络 \"%s\"" msgid "Unable to update share network." msgstr "无法更新共享网络" msgid "Unable to update share type." msgstr "无法更新共享类型" msgid "Unable to update share." msgstr "无法更新共享" msgid "Unknown" msgstr "未知" msgid "Unmanage" msgstr "取消管理" msgctxt "Current status of share" msgid "Unmanage Error" msgstr "取消管理错误" msgid "Unmanage Share" msgstr "取消管理共享" msgid "Update" msgstr "更新" msgid "Update Share Network" msgstr "更新共享网络" msgid "Update Share Type" msgstr "更新共享类型" msgid "Updated At" msgstr "更新于" #, python-format msgid "Updated access for share type \"%s\"." msgstr "更新共享类型\"%s\"的访问权限" #, python-format msgid "Updated share network \"%s\"." msgstr "更新共享网络\"%s\"" #, python-format msgid "Updating share \"%s\"" msgstr "正在更新共享 \"%s\"" #, python-format msgid "Updating share metadata \"%s\"" msgstr "正在更新共享元数据 \"%s\"" #, python-format msgid "Updating share network \"%s\"" msgstr "更新共享网络\"%s\"" msgid "Use snapshot as a source" msgstr "使用快照作为源" msgid "User" msgstr "用户" msgid "Visibility" msgstr "可见性" msgid "Writable" msgstr "可写入的" msgid "key=value pairs per line can be set" msgstr "每一行设置键值对" manila-ui-2.13.0/manila_ui/tests/000077500000000000000000000000001323215354300165525ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/__init__.py000066400000000000000000000000001323215354300206510ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/api/000077500000000000000000000000001323215354300173235ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/api/__init__.py000066400000000000000000000000001323215354300214220ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/api/test_manila.py000066400000000000000000000565111323215354300222050ustar00rootroot00000000000000# Copyright (c) 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 manila_ui.api import manila as api from manila_ui.tests import helpers as base @ddt.ddt class ManilaApiTests(base.APITestCase): def setUp(self): super(self.__class__, self).setUp() self.id = "fake_id" @ddt.data((None, True), ("some_fake_sg_id", False)) @ddt.unpack def test_share_create(self, sg_id, is_public): kwargs = { "share_network": "fake_sn", "snapshot_id": "fake_snapshot_id", "metadata": {"k1": "v1", "k2": "v2"}, "share_type": "fake_st", "is_public": is_public, "availability_zone": "fake_az", "share_group_id": sg_id, } size = 5 name = "fake_name" desc = "fake_description" proto = "fake_share_protocol" api.share_create(self.request, size, name, desc, proto, **kwargs) self.manilaclient.shares.create.assert_called_once_with( proto, size, name=name, description=desc, **kwargs) @ddt.data(None, "some_fake_sg_id") def test_share_delete(self, sg_id): s_id = "fake_share_id" api.share_delete(self.request, s_id, sg_id) self.manilaclient.shares.delete.assert_called_once_with( s_id, share_group_id=sg_id) def test_list_share_export_locations(self): api.share_export_location_list(self.request, self.id) self.manilaclient.share_export_locations.list.assert_called_once_with( self.id) def test_list_share_instance_export_locations(self): api.share_instance_export_location_list(self.request, self.id) client = self.manilaclient client.share_instance_export_locations.list.assert_called_once_with( self.id) def test_share_manage(self): api.share_manage( self.request, service_host="fake_service_host", protocol="fake_protocol", export_path="fake_export_path", driver_options={"fake_key": "fake_value"}, share_type="fake_share_type", name="fake_name", description="fake_description", is_public="fake_is_public", ) self.manilaclient.shares.manage.assert_called_once_with( service_host="fake_service_host", protocol="fake_protocol", export_path="fake_export_path", driver_options={"fake_key": "fake_value"}, share_type="fake_share_type", name="fake_name", description="fake_description", is_public="fake_is_public", ) def test_share_extend(self): new_size = "123" api.share_extend(self.request, self.id, new_size) self.manilaclient.shares.extend.assert_called_once_with( self.id, new_size ) def test_share_revert(self): share = 'fake_share' snapshot = 'fake_snapshot' api.share_revert(self.request, share, snapshot) self.manilaclient.shares.revert_to_snapshot.assert_called_once_with( share, snapshot) @ddt.data(True, False) def test_share_type_create_with_default_values(self, dhss): name = 'fake_share_type_name' api.share_type_create(self.request, name, dhss) self.manilaclient.share_types.create.assert_called_once_with( name=name, spec_driver_handles_share_servers=dhss, spec_snapshot_support=True, is_public=True) @ddt.data( (True, True, True), (True, True, False), (True, False, True), (False, True, True), (True, False, False), (False, False, True), (False, True, False), (True, True, True), ) @ddt.unpack def test_share_type_create_with_custom_values( self, dhss, snapshot_support, is_public): name = 'fake_share_type_name' api.share_type_create( self.request, name, dhss, snapshot_support, is_public) self.manilaclient.share_types.create.assert_called_once_with( name=name, spec_driver_handles_share_servers=dhss, spec_snapshot_support=snapshot_support, is_public=is_public) def test_share_type_set_extra_specs(self): data = {"foo": "bar"} api.share_type_set_extra_specs(self.request, self.id, data) share_types_get = self.manilaclient.share_types.get share_types_get.assert_called_once_with(self.id) share_types_get.return_value.set_keys.assert_called_once_with(data) def test_share_type_unset_extra_specs(self): keys = ["foo", "bar"] api.share_type_unset_extra_specs(self.request, self.id, keys) share_types_get = self.manilaclient.share_types.get share_types_get.assert_called_once_with(self.id) share_types_get.return_value.unset_keys.assert_called_once_with(keys) def test_share_instance_list(self): api.share_instance_list(self.request) self.manilaclient.share_instances.list.assert_called_once_with() def test_share_instance_get(self): api.share_instance_get(self.request, self.id) self.manilaclient.share_instances.get.assert_called_once_with(self.id) def test_share_replica_list(self): api.share_replica_list(self.request) self.manilaclient.share_replicas.list.assert_called_once_with(None) def test_share_replica_list_with_filter_by_share(self): api.share_replica_list(self.request, share="FOO") self.manilaclient.share_replicas.list.assert_called_once_with("FOO") @ddt.data(None, "foo_share_network") def test_share_replica_create(self, share_network): share = "FOO_share" availability_zone = "BAR_availability_zone" api.share_replica_create( self.request, share, availability_zone, share_network) self.manilaclient.share_replicas.create.assert_called_once_with( share, availability_zone=availability_zone, share_network=share_network, ) def test_share_replica_get(self): api.share_replica_get(self.request, "fake") self.manilaclient.share_replicas.get.assert_called_once_with("fake") def test_share_replica_delete(self): api.share_replica_delete(self.request, "fake") self.manilaclient.share_replicas.delete.assert_called_once_with("fake") def test_share_replica_promote(self): api.share_replica_promote(self.request, "fake") self.manilaclient.share_replicas.promote.assert_called_once_with( "fake") def test_share_replica_resync(self): api.share_replica_resync(self.request, "fake") self.manilaclient.share_replicas.resync.assert_called_once_with("fake") def test_share_replica_reset_status(self): replica = "fake_replica" status = "fake_status" api.share_replica_reset_status(self.request, replica, status) self.manilaclient.share_replicas.reset_state.assert_called_once_with( replica, status) def test_share_replica_reset_state(self): replica = "fake_replica" state = "fake_state" api.share_replica_reset_state(self.request, replica, state) mock_reset_state = self.manilaclient.share_replicas.reset_replica_state mock_reset_state.assert_called_once_with(replica, state) def test_allow_snapshot(self): access_type = "fake_type" access_to = "fake_value" api.share_snapshot_allow(self.request, self.id, access_type, access_to) client = self.manilaclient client.share_snapshots.allow.assert_called_once_with( self.id, access_type, access_to) def test_deny_snapshot(self): api.share_snapshot_deny(self.request, self.id, self.id) client = self.manilaclient client.share_snapshots.deny.assert_called_once_with(self.id, self.id) def test_list_snapshot_rules(self): api.share_snapshot_rules_list(self.request, self.id) client = self.manilaclient client.share_snapshots.access_list.assert_called_once_with(self.id) def test_list_snapshot_export_locations(self): api.share_snap_export_location_list(self.request, self.id) client = self.manilaclient client.share_snapshot_export_locations.list.assert_called_once_with( snapshot=self.id) def test_list_snapshot_instance_export_locations(self): api.share_snap_instance_export_location_list(self.request, self.id) client = self.manilaclient client.share_snapshot_export_locations.list.assert_called_once_with( snapshot_instance=self.id) def test_migration_start(self): api.migration_start(self.request, 'fake_share', 'fake_host', False, True, True, True, True, 'fake_net_id', 'fake_type_id') self.manilaclient.shares.migration_start.assert_called_once_with( 'fake_share', host='fake_host', force_host_assisted_migration=False, nondisruptive=True, writable=True, preserve_metadata=True, preserve_snapshots=True, new_share_network_id='fake_net_id', new_share_type_id='fake_type_id' ) def test_migration_complete(self): api.migration_complete(self.request, 'fake_share') self.manilaclient.shares.migration_complete.assert_called_once_with( 'fake_share') def test_migration_cancel(self): api.migration_cancel(self.request, 'fake_share') self.manilaclient.shares.migration_cancel.assert_called_once_with( 'fake_share') def test_migration_get_progress(self): api.migration_get_progress(self.request, 'fake_share') (self.manilaclient.shares.migration_get_progress. assert_called_once_with('fake_share')) def test_availability_zone_list(self): api.availability_zone_list(self.request) self.manilaclient.availability_zones.list.assert_called_once_with() @ddt.data( ({'share_gigabytes': 333}, {'gigabytes': 333}), ({'share_snapshot_gigabytes': 444}, {'snapshot_gigabytes': 444}), ({'share_snapshots': 14}, {'snapshots': 14}), ({'snapshots': 14}, {'snapshots': 14}), ({'gigabytes': 14}, {'gigabytes': 14}), ({'snapshot_gigabytes': 314}, {'snapshot_gigabytes': 314}), ({'shares': 24}, {'shares': 24}), ({'share_networks': 14}, {'share_networks': 14}), ) @ddt.unpack def test_tenant_quota_update(self, provided_kwargs, expected_kwargs): tenant_id = 'fake_tenant_id' api.tenant_quota_update(self.request, tenant_id, **provided_kwargs) self.manilaclient.quotas.update.assert_called_once_with( tenant_id, **expected_kwargs) self.manilaclient.quota_classes.update.assert_not_called() @ddt.data( ({'share_gigabytes': 333}, {'gigabytes': 333}), ({'share_snapshot_gigabytes': 444}, {'snapshot_gigabytes': 444}), ({'share_snapshots': 14}, {'snapshots': 14}), ({'snapshots': 14}, {'snapshots': 14}), ({'gigabytes': 14}, {'gigabytes': 14}), ({'snapshot_gigabytes': 314}, {'snapshot_gigabytes': 314}), ({'shares': 24}, {'shares': 24}), ({'share_networks': 14}, {'share_networks': 14}), ) @ddt.unpack def test_default_quota_update(self, provided_kwargs, expected_kwargs): api.default_quota_update(self.request, **provided_kwargs) self.manilaclient.quota_classes.update.assert_called_once_with( api.DEFAULT_QUOTA_NAME, **expected_kwargs) @ddt.data( {}, {"name": "foo_name"}, {"description": "foo_desc"}, {"neutron_net_id": "foo_neutron_net_id"}, {"neutron_subnet_id": "foo_neutron_subnet_id"}, {"name": "foo_name", "description": "foo_desc", "neutron_net_id": "foo_neutron_net_id", "neutron_subnet_id": "foo_neutron_subnet_id"}, ) @ddt.unpack def test_share_network_create(self, **kwargs): expected_kwargs = { "name": None, "description": None, "neutron_net_id": None, "neutron_subnet_id": None, } expected_kwargs.update(kwargs) api.share_network_create(self.request, **kwargs) mock_sn_create = self.manilaclient.share_networks.create mock_sn_create.assert_called_once_with(**expected_kwargs) # Share groups tests def test_share_group_create(self): name = "fake_sg_name" kwargs = { "description": "fake_desc", "share_group_type": "fake_sg_type", "share_types": ["fake", "list", "of", "fake", "share", "types"], "share_network": "fake_sn", "source_share_group_snapshot": "fake_source_share_group_snapshot", "availability_zone": "fake_az", } result = api.share_group_create(self.request, name, **kwargs) self.assertEqual( self.manilaclient.share_groups.create.return_value, result) self.manilaclient.share_groups.create.assert_called_once_with( name=name, **kwargs) def test_share_group_get(self): sg = "fake_share_group" result = api.share_group_get(self.request, sg) self.assertEqual( self.manilaclient.share_groups.get.return_value, result) self.manilaclient.share_groups.get.assert_called_once_with(sg) def test_share_group_update(self): sg = "fake_share_group" name = "fake_name" desc = "fake_desc" result = api.share_group_update(self.request, sg, name, desc) self.assertEqual( self.manilaclient.share_groups.update.return_value, result) self.manilaclient.share_groups.update.assert_called_once_with( sg, name=name, description=desc) @ddt.data({}, {"force": True}, {"force": False}) def test_share_group_delete(self, kwargs): sg = 'fake_share_group' api.share_group_delete(self.request, sg, **kwargs) self.manilaclient.share_groups.delete.assert_called_once_with( sg, force=kwargs.get("force", False)) def test_share_group_reset_state(self): sg = 'fake_share_group' state = 'fake_state' result = api.share_group_reset_state(self.request, sg, state) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_groups.reset_state.return_value, result) self.manilaclient.share_groups.reset_state.assert_called_once_with( sg, state) @ddt.data( {}, {"detailed": True}, {"detailed": False}, {"search_opts": {"foo": "bar"}}, {"sort_key": "id", "sort_dir": "asc"}, ) def test_share_group_list(self, kwargs): result = api.share_group_list(self.request, **kwargs) self.assertEqual( self.manilaclient.share_groups.list.return_value, result) self.manilaclient.share_groups.list.assert_called_once_with( detailed=kwargs.get("detailed", True), search_opts=kwargs.get("search_opts"), sort_key=kwargs.get("sort_key"), sort_dir=kwargs.get("sort_dir"), ) # Share Group Snapshots tests def test_share_group_snapshot_create(self): sg = 'fake_share_group' name = 'fake_name' desc = 'fake_description' result = api.share_group_snapshot_create(self.request, sg, name, desc) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_snapshots.create.return_value, result) self.manilaclient.share_group_snapshots.create.assert_called_once_with( share_group=sg, name=name, description=desc) def test_share_group_snapshot_get(self): sgs = 'fake_share_group_snapshot' result = api.share_group_snapshot_get(self.request, sgs) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_snapshots.get.return_value, result) self.manilaclient.share_group_snapshots.get.assert_called_once_with( sgs) def test_share_group_snapshot_update(self): sgs = 'fake_share_group_snapshot' name = 'fake_name' desc = 'fake_description' result = api.share_group_snapshot_update(self.request, sgs, name, desc) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_snapshots.update.return_value, result) self.manilaclient.share_group_snapshots.update.assert_called_once_with( sgs, name=name, description=desc) @ddt.data(True, False) def test_share_group_snapshot_delete(self, force): sgs = 'fake_share_group_snapshot' result = api.share_group_snapshot_delete(self.request, sgs, force) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_snapshots.delete.return_value, result) self.manilaclient.share_group_snapshots.delete.assert_called_once_with( sgs, force=force) def test_share_group_snapshot_reset_state(self): sgs = 'fake_share_group_snapshot' state = 'fake_state' result = api.share_group_snapshot_reset_state(self.request, sgs, state) rs_method = self.manilaclient.share_group_snapshots.reset_state self.assertIsNotNone(result) self.assertEqual(rs_method.return_value, result) rs_method.assert_called_once_with(sgs, state) @ddt.data( {}, {'detailed': False}, {'detailed': True, 'search_opts': 'foo', 'sort_key': 'k', 'sort_dir': 'v'}, ) def test_share_group_snapshot_list(self, kwargs): result = api.share_group_snapshot_list(self.request, **kwargs) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_snapshots.list.return_value, result) self.manilaclient.share_group_snapshots.list.assert_called_once_with( detailed=kwargs.get('detailed', True), search_opts=kwargs.get('search_opts'), sort_key=kwargs.get('sort_key'), sort_dir=kwargs.get('sort_dir')) # Share Group Types tests @ddt.data( {'is_public': True}, {'is_public': False, 'group_specs': {'foo': 'bar'}}, {'group_specs': {}}, ) def test_share_group_type_create(self, kwargs): name = 'fake_sgt_name' sts = ['fake', 'list', 'of', 'share', 'types'] result = api.share_group_type_create(self.request, name, sts, **kwargs) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_types.create.return_value, result) self.manilaclient.share_group_types.create.assert_called_once_with( name=name, share_types=sts, is_public=kwargs.get('is_public', False), group_specs=kwargs.get('group_specs')) def test_share_group_type_get(self): sgt = "fake_sgt" result = api.share_group_type_get(self.request, sgt) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_types.get.return_value, result) self.manilaclient.share_group_types.get.assert_called_once_with(sgt) @ddt.data(True, False) def test_share_group_type_list(self, show_all): result = api.share_group_type_list(self.request, show_all) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_types.list.return_value, result) self.manilaclient.share_group_types.list.assert_called_once_with( show_all=show_all) def test_share_group_type_delete(self): sgt = 'fake_share_group_type' result = api.share_group_type_delete(self.request, sgt) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_types.delete.return_value, result) self.manilaclient.share_group_types.delete.assert_called_once_with(sgt) def test_share_group_type_access_list(self): sgt = 'fake_share_group_type' result = api.share_group_type_access_list(self.request, sgt) self.assertIsNotNone(result) self.assertEqual( self.manilaclient.share_group_type_access.list.return_value, result) self.manilaclient.share_group_type_access.list.assert_called_once_with( sgt) def test_share_group_type_access_add(self): sgt = 'fake_share_group_type' project = 'fake_project' result = api.share_group_type_access_add(self.request, sgt, project) sgt_access = self.manilaclient.share_group_type_access self.assertIsNotNone(result) self.assertEqual( sgt_access.add_project_access.return_value, result) sgt_access.add_project_access.assert_called_once_with(sgt, project) def test_share_group_type_access_remove(self): sgt = 'fake_share_group_type' project = 'fake_project' result = api.share_group_type_access_remove(self.request, sgt, project) sgt_access = self.manilaclient.share_group_type_access self.assertIsNotNone(result) self.assertEqual( sgt_access.remove_project_access.return_value, result) sgt_access.remove_project_access.assert_called_once_with(sgt, project) def test_share_group_type_set_specs(self): sgt = 'fake_share_group_type' group_specs = 'fake_specs' result = api.share_group_type_set_specs(self.request, sgt, group_specs) get_method = self.manilaclient.share_group_types.get self.assertIsNotNone(result) self.assertEqual(get_method.return_value.set_keys.return_value, result) get_method.assert_called_once_with(sgt) get_method.return_value.set_keys.assert_called_once_with(group_specs) def test_share_group_type_unset_specs(self): sgt = 'fake_share_group_type' keys = ['fake', 'list', 'of', 'keys', 'for', 'deletion'] result = api.share_group_type_unset_specs(self.request, sgt, keys) get_method = self.manilaclient.share_group_types.get self.assertIsNotNone(result) self.assertEqual( get_method.return_value.unset_keys.return_value, result) get_method.assert_called_once_with(sgt) get_method.return_value.unset_keys.assert_called_once_with(keys) def test_share_group_type_get_specs(self): sgt = 'fake_share_group_type' result = api.share_group_type_get_specs(self.request, sgt) get_method = self.manilaclient.share_group_types.get self.assertIsNotNone(result) self.assertEqual( get_method.return_value.get_keys.return_value, result) get_method.assert_called_once_with(sgt) get_method.return_value.get_keys.assert_called_once_with() manila-ui-2.13.0/manila_ui/tests/dashboards/000077500000000000000000000000001323215354300206645ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/__init__.py000066400000000000000000000000001323215354300227630ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/000077500000000000000000000000001323215354300217545ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/__init__.py000066400000000000000000000000001323215354300240530ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/security_services/000077500000000000000000000000001323215354300255265ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/security_services/__init__.py000066400000000000000000000000001323215354300276250ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/security_services/tests.py000066400000000000000000000075441323215354300272540ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # Copyright (c) 2015 Mirantis, Inc. # # 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 django.core.urlresolvers import reverse from horizon import exceptions as horizon_exceptions import mock from openstack_dashboard.api import keystone as api_keystone from manila_ui.api import manila as api_manila from manila_ui.dashboards.admin import utils from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test from manila_ui.tests.test_data import keystone_data INDEX_URL = reverse('horizon:admin:security_services:index') class SecurityServicesTests(test.BaseAdminViewTests): def setUp(self): super(self.__class__, self).setUp() self.mock_object( api_keystone, "tenant_list", mock.Mock(return_value=(keystone_data.projects, None))) # Reset taken list of projects to avoid test interference utils.PROJECTS = {} def test_detail_view(self): sec_service = test_data.sec_service self.mock_object( api_manila, "security_service_get", mock.Mock(return_value=sec_service)) url = reverse( 'horizon:admin:security_services:security_service_detail', args=[sec_service.id]) res = self.client.get(url) self.assertContains(res, "

Security Service Details: %s

" % sec_service.name, 1, 200) self.assertContains(res, "
%s
" % sec_service.name, 1, 200) self.assertContains(res, "
%s
" % sec_service.id, 1, 200) self.assertContains(res, "
%s
" % sec_service.user, 1, 200) self.assertContains(res, "
%s
" % sec_service.server, 1, 200) self.assertContains(res, "
%s
" % sec_service.dns_ip, 1, 200) self.assertContains(res, "
%s
" % sec_service.domain, 1, 200) self.assertNoMessages() api_manila.security_service_get.assert_called_once_with( mock.ANY, sec_service.id) def test_detail_view_with_exception(self): url = reverse( 'horizon:admin:security_services:security_service_detail', args=[test_data.sec_service.id]) self.mock_object( api_manila, "security_service_get", mock.Mock(side_effect=horizon_exceptions.NotFound(404))) res = self.client.get(url) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.security_service_get.assert_called_once_with( mock.ANY, test_data.sec_service.id) def test_delete_security_service(self): security_service = test_data.sec_service formData = { 'action': 'security_services__delete__%s' % security_service.id, } self.mock_object(api_manila, "security_service_delete") self.mock_object( api_manila, "security_service_list", mock.Mock(return_value=[test_data.sec_service])) res = self.client.post(INDEX_URL, formData) api_keystone.tenant_list.assert_called_once_with(mock.ANY) api_manila.security_service_delete.assert_called_once_with( mock.ANY, test_data.sec_service.id) api_manila.security_service_list.assert_called_once_with( mock.ANY, search_opts={'all_tenants': True}) self.assertRedirectsNoFollow(res, INDEX_URL) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_group_snapshots/000077500000000000000000000000001323215354300263745ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_group_snapshots/__init__.py000066400000000000000000000000001323215354300304730ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_group_snapshots/tests.py000066400000000000000000000176171323215354300301240ustar00rootroot00000000000000# Copyright (c) 2017 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 django.core.urlresolvers import reverse import mock from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:admin:share_group_snapshots:index') @ddt.ddt class ShareGroupSnapshotTests(test.BaseAdminViewTests): def setUp(self): super(self.__class__, self).setUp() self.sg = test_data.share_group self.sg_nl = test_data.share_group_nameless self.sg_dhss_true = test_data.share_group_dhss_true self.sgs = test_data.share_group_snapshot self.sgs_nl = test_data.share_group_snapshot_nameless def test_share_group_snapshots_list_get(self): share_groups = [self.sg, self.sg_nl, self.sg_dhss_true] sgss = [self.sgs, self.sgs_nl] self.mock_object( api_manila, 'share_group_snapshot_list', mock.Mock(return_value=sgss)) self.mock_object( api_manila, 'share_group_list', mock.Mock(return_value=share_groups)) res = self.client.get(INDEX_URL) self.assertStatusCode(res, 200) self.assertMessageCount(error=0) self.assertNoMessages() api_manila.share_group_snapshot_list.assert_called_once_with( mock.ANY, search_opts={'all_tenants': True}) api_manila.share_group_list.assert_called_once_with(mock.ANY) self.assertTemplateUsed(res, 'admin/share_group_snapshots/index.html') self.assertContains(res, "

Share Group Snapshots

") self.assertContains( res, 'Delete Share Group Snapshot', len(sgss)) self.assertContains(res, 'Delete Share Group Snapshots', 1) for sgs in sgss: self.assertContains( res, 'href="/admin/share_group_snapshots/%s/reset_status"> ' 'Reset status' % sgs.id, 1) self.assertContains( res, 'value="share_group_snapshots__delete__%s' % sgs.id, 1) self.assertContains( res, '%(name)s' % { 'id': self.sgs.id, 'name': self.sgs.name}, 1) self.assertContains( res, '-' % self.sgs_nl.id, 1) def test_share_group_snapshots_list_error_get(self): self.mock_object( api_manila, 'share_group_snapshot_list', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(INDEX_URL) self.assertStatusCode(res, 200) self.assertTemplateUsed(res, 'admin/share_group_snapshots/index.html') self.assertContains(res, "

Share Group Snapshots

") self.assertContains(res, 'Delete Share Group Snapshot', 0) self.assertContains(res, 'Delete Share Group Snapshots', 0) self.assertNoMessages() @ddt.data( test_data.share_group_snapshot, test_data.share_group_snapshot_nameless, ) def test_share_group_snapshot_detailed_page_get(self, sgs): sg = test_data.share_group_nameless url = reverse( 'horizon:admin:share_group_snapshots:detail', args=[sgs.id]) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(return_value=sgs)) self.mock_object( api_manila, 'share_group_get', mock.Mock(return_value=sg)) res = self.client.get(url) self.assertTemplateUsed(res, 'admin/share_group_snapshots/detail.html') self.assertStatusCode(res, 200) api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, sgs.id) api_manila.share_group_get.assert_called_once_with( mock.ANY, sgs.share_group_id) def test_share_group_snapshot_detailed_page_error_get(self): url = reverse( 'horizon:admin:share_group_snapshots:detail', args=[self.sgs.id]) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(url) self.assertTemplateNotUsed( res, 'admin/share_group_snapshots/detail.html') self.assertStatusCode(res, 302) self.assertMessageCount(error=1) self.assertMessageCount(success=0) def test_share_group_snapshot_reset_status_get(self): url = reverse( 'horizon:admin:share_group_snapshots:reset_status', args=[self.sgs.id]) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(return_value=self.sgs)) res = self.client.get(url) self.assertTemplateUsed( res, 'admin/share_group_snapshots/reset_status.html') self.assertStatusCode(res, 200) self.assertMessageCount(error=0) api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, self.sgs.id) def test_share_group_snapshot_reset_status_error_get(self): url = reverse( 'horizon:admin:share_group_snapshots:reset_status', args=[self.sgs.id]) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(url) self.assertTemplateNotUsed( res, 'admin/share_group_snapshots/reset_status.html') self.assertStatusCode(res, 302) self.assertMessageCount(error=1) api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, self.sgs.id) def test_share_group_snapshot_reset_status_post(self): url = reverse( 'horizon:admin:share_group_snapshots:reset_status', args=[self.sgs.id]) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(return_value=self.sgs)) self.mock_object(api_manila, 'share_group_snapshot_reset_state') form_data = {'status': 'error'} res = self.client.post(url, form_data) self.assertTemplateNotUsed( res, 'admin/share_group_snapshots/reset_status.html') self.assertStatusCode(res, 302) self.assertMessageCount(error=0) api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, self.sgs.id) api_manila.share_group_snapshot_reset_state.assert_called_once_with( mock.ANY, self.sgs.id, form_data['status']) self.assertRedirectsNoFollow(res, INDEX_URL) def test_share_group_snapshot_delete_post(self): data = {'action': 'share_group_snapshots__delete__%s' % self.sgs.id} self.mock_object(api_manila, "share_group_snapshot_delete") self.mock_object( api_manila, "share_group_snapshot_list", mock.Mock(return_value=[self.sgs])) res = self.client.post(INDEX_URL, data) self.assertStatusCode(res, 302) self.assertMessageCount(success=1) api_manila.share_group_snapshot_delete.assert_called_once_with( mock.ANY, self.sgs.id) api_manila.share_group_snapshot_list.assert_called_once_with( mock.ANY, search_opts={'all_tenants': True}) self.assertRedirectsNoFollow(res, INDEX_URL) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_group_types/000077500000000000000000000000001323215354300255165ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_group_types/__init__.py000066400000000000000000000000001323215354300276150ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_group_types/tests.py000066400000000000000000000132421323215354300272340ustar00rootroot00000000000000# Copyright (c) 2017 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 copy from django.core.urlresolvers import reverse import mock from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:admin:share_group_types:index') class ShareGroupTypeTests(test.BaseAdminViewTests): def setUp(self): super(self.__class__, self).setUp() self.sgt = copy.copy(test_data.share_group_type) self.sgt_p = copy.copy(test_data.share_group_type_private) self.url = reverse( 'horizon:admin:share_group_types:update', args=[self.sgt.id]) self.mock_object( api_manila, "share_group_type_get", mock.Mock(return_value=self.sgt)) def test_list_share_group_types_get(self): sgts = [self.sgt, self.sgt_p] self.mock_object( api_manila, "share_group_type_list", mock.Mock(return_value=sgts)) self.mock_object( api_manila, "share_type_list", mock.Mock(return_value=[ test_data.share_type, test_data.share_type_private])) self.mock_object( api_manila, "share_group_type_get", mock.Mock(side_effect=lambda req, sgt_id: ( self.sgt if sgt_id in (self.sgt, self.sgt.id, self.sgt.name) else self.sgt_p))) res = self.client.get(INDEX_URL) api_manila.share_group_type_list.assert_called_once_with(mock.ANY) api_manila.share_type_list.assert_called_once_with(mock.ANY) self.assertEqual(len(sgts), api_manila.share_group_type_get.call_count) self.assertContains(res, "

Share Group Types

") self.assertContains(res, 'href="/admin/share_group_types/create"') self.assertContains(res, 'Delete Share Group Type', len(sgts)) self.assertContains(res, 'Delete Share Group Types', 1) for sgt in (self.sgt, self.sgt_p): for s in ( 'href="/admin/share_group_types/%s/update">' % sgt.id, 'value="share_group_types__delete__%s"' % sgt.id): self.assertContains(res, s, 1, 200) self.assertContains( res, 'href="/admin/share_group_types/%s/manage_access"' % sgt.id, 0 if sgt.is_public else 1) def test_create_share_group_type_post(self): url = reverse('horizon:admin:share_group_types:create') data = { 'method': u'CreateShareGroupTypeForm', 'is_public': True, 'name': 'my_share_group_type', 'share_types': ['foo'], 'group_specs': 'key=value', } self.mock_object( api_manila, "share_group_type_create", mock.Mock(return_value=type( 'SGT', (object, ), {'id': 'sgt_id', 'name': 'sgt_name'}))) self.mock_object(api_manila, "share_group_type_set_specs") self.mock_object( api_manila, "share_type_list", mock.Mock(return_value=[ type('ST', (object, ), {'id': s_id, 'name': s_id + '_name'}) for s_id in ('foo', 'bar') ])) res = self.client.post(url, data) api_manila.share_group_type_create.assert_called_once_with( mock.ANY, data['name'], is_public=data['is_public'], share_types=['foo']) api_manila.share_type_list.assert_called_once_with(mock.ANY) api_manila.share_group_type_set_specs.assert_called_once_with( mock.ANY, 'sgt_id', {'key': 'value'}) self.assertRedirectsNoFollow(res, INDEX_URL) def test_update_share_group_type_get(self): res = self.client.get(self.url) api_manila.share_group_type_get.assert_called_once_with( mock.ANY, self.sgt.id) self.assertNoMessages() self.assertTemplateUsed(res, 'admin/share_group_types/update.html') def test_update_share_group_type_post(self): form_data = {'group_specs': 'foo=bar'} data = {'group_specs': {'foo': 'bar'}} self.mock_object(api_manila, "share_group_type_set_specs") res = self.client.post(self.url, form_data) api_manila.share_group_type_set_specs.assert_called_once_with( mock.ANY, self.sgt.id, data['group_specs']) self.assertRedirectsNoFollow(res, INDEX_URL) def test_delete_share_group_type(self): data = {'action': 'share_group_types__delete__%s' % self.sgt.id} self.mock_object(api_manila, "share_group_type_delete") self.mock_object( api_manila, "share_group_type_list", mock.Mock(return_value=[self.sgt])) self.mock_object( api_manila, "share_type_list", mock.Mock(return_value=[test_data.share_type])) res = self.client.post(INDEX_URL, data) api_manila.share_group_type_delete.assert_called_once_with( mock.ANY, self.sgt.id) api_manila.share_group_type_list.assert_called_once_with( mock.ANY) self.assertRedirectsNoFollow(res, INDEX_URL) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_groups/000077500000000000000000000000001323215354300244555ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_groups/__init__.py000066400000000000000000000000001323215354300265540ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_groups/tests.py000066400000000000000000000166421323215354300262020ustar00rootroot00000000000000# Copyright (c) 2017 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 django.core.urlresolvers import reverse import mock from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:admin:share_groups:index') @ddt.ddt class ShareGroupTests(test.BaseAdminViewTests): def setUp(self): super(self.__class__, self).setUp() self.sg = test_data.share_group self.sg_nl = test_data.share_group_nameless self.sg_dhss_true = test_data.share_group_dhss_true def test_share_groups_list_get(self): sgs = [self.sg, self.sg_nl, self.sg_dhss_true] self.mock_object( api_manila, 'share_group_list', mock.Mock(return_value=sgs)) res = self.client.get(INDEX_URL) self.assertStatusCode(res, 200) api_manila.share_group_list.assert_called_once_with( mock.ANY, detailed=True) self.assertTemplateUsed(res, 'admin/share_groups/index.html') self.assertContains(res, "

Share Groups

") self.assertContains(res, 'Delete Share Group', len(sgs)) self.assertContains(res, 'Delete Share Groups', 1) for sg in sgs: self.assertContains( res, 'href="/admin/share_groups/%s/reset_status"> ' 'Reset status' % sg.id, 1) self.assertContains( res, 'value="share_groups__delete__%s' % sg.id, 1) self.assertContains( res, '%(name)s' % { 'id': sg.id, 'name': sg.name}, 1) self.assertContains( res, '-' % self.sg_nl.id, 1) self.assertNoMessages() def test_share_group_list_error_get(self): self.mock_object( api_manila, 'share_group_list', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(INDEX_URL) self.assertStatusCode(res, 200) self.assertTemplateUsed(res, 'admin/share_groups/index.html') self.assertContains(res, "

Share Groups

") self.assertContains(res, 'Delete Share Group', 0) self.assertContains(res, 'Delete Share Groups', 0) self.assertNoMessages() @ddt.data( test_data.share_group_nameless, test_data.share_group_dhss_true, ) def test_share_group_detailed_page_get(self, sg): url = reverse('horizon:admin:share_groups:detail', args=[sg.id]) shares = [test_data.share, test_data.nameless_share] self.mock_object( api_manila, 'share_group_get', mock.Mock(return_value=sg)) self.mock_object( api_manila, 'share_list', mock.Mock(return_value=shares)) self.mock_object( api_manila, 'share_type_list', mock.Mock(return_value=[ test_data.share_type, test_data.share_type_dhss_true])) res = self.client.get(url) self.assertTemplateUsed(res, 'admin/share_groups/detail.html') self.assertStatusCode(res, 200) for share in shares: data = {'id': share.id, 'name': share.name or share.id} self.assertContains( res, '%(name)s' % data) def test_share_group_detailed_page_error_get(self): sg = test_data.share_group_dhss_true url = reverse('horizon:admin:share_groups:detail', args=[sg.id]) self.mock_object( api_manila, 'share_group_get', mock.Mock(side_effect=type( 'CustomExc', (Exception, ), {}))) res = self.client.get(url) self.assertTemplateNotUsed(res, 'admin/share_groups/detail.html') self.assertStatusCode(res, 302) self.assertMessageCount(error=1) self.assertMessageCount(success=0) def test_share_group_reset_status_get(self): sg = test_data.share_group_dhss_true url = reverse('horizon:admin:share_groups:reset_status', args=[sg.id]) self.mock_object( api_manila, 'share_group_get', mock.Mock(return_value=sg)) res = self.client.get(url) self.assertTemplateUsed(res, 'admin/share_groups/reset_status.html') self.assertStatusCode(res, 200) self.assertMessageCount(error=0) api_manila.share_group_get.assert_called_once_with(mock.ANY, sg.id) def test_share_group_reset_status_error_get(self): sg = test_data.share_group_dhss_true url = reverse('horizon:admin:share_groups:reset_status', args=[sg.id]) self.mock_object( api_manila, 'share_group_get', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(url) self.assertTemplateNotUsed(res, 'admin/share_groups/reset_status.html') self.assertStatusCode(res, 302) self.assertMessageCount(error=1) api_manila.share_group_get.assert_called_once_with(mock.ANY, sg.id) def test_share_group_reset_status_post(self): sg = test_data.share_group_dhss_true url = reverse('horizon:admin:share_groups:reset_status', args=[sg.id]) self.mock_object( api_manila, 'share_group_get', mock.Mock(return_value=sg)) self.mock_object(api_manila, 'share_group_reset_state') form_data = {'status': 'error'} res = self.client.post(url, form_data) self.assertTemplateNotUsed(res, 'admin/share_groups/reset_status.html') self.assertStatusCode(res, 302) self.assertMessageCount(error=0) api_manila.share_group_get.assert_called_once_with(mock.ANY, sg.id) api_manila.share_group_reset_state.assert_called_once_with( mock.ANY, sg.id, form_data['status']) self.assertRedirectsNoFollow(res, INDEX_URL) def test_share_group_delete_post(self): sg = test_data.share_group_dhss_true data = {'action': 'share_groups__delete__%s' % sg.id} self.mock_object(api_manila, "share_group_delete") self.mock_object( api_manila, "share_group_list", mock.Mock(return_value=[sg])) res = self.client.post(INDEX_URL, data) self.assertStatusCode(res, 302) self.assertMessageCount(success=1) api_manila.share_group_delete.assert_called_once_with(mock.ANY, sg.id) api_manila.share_group_list.assert_called_once_with( mock.ANY, detailed=True) self.assertRedirectsNoFollow(res, INDEX_URL) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_instances/000077500000000000000000000000001323215354300251255ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_instances/__init__.py000066400000000000000000000000001323215354300272240ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_instances/tests.py000066400000000000000000000117671323215354300266550ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # Copyright (c) 2015 Mirantis, Inc. # # 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 django.core.urlresolvers import reverse from horizon import exceptions as horizon_exceptions import mock from openstack_dashboard.api import keystone as api_keystone from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:admin:share_instances:index') class ShareInstanceTests(test.BaseAdminViewTests): def test_list_share_instances(self): share_instances = [ test_data.share_instance, test_data.share_instance_no_ss, ] self.mock_object( api_manila, "share_instance_list", mock.Mock(return_value=share_instances)) self.mock_object( api_keystone, "tenant_list", mock.Mock(return_value=([], None))) res = self.client.get(INDEX_URL) self.assertContains(res, "

Share Instances

") self.assertContains( res, '%s' % ( share_instances[0].share_server_id, share_instances[0].share_server_id), 1, 200) self.assertContains( res, '%s' % ( share_instances[0].share_network_id, share_instances[0].share_network_id), 1, 200) for si in share_instances: self.assertContains( res, '%s' % ( si.id, si.id)) self.assertContains(res, si.host) self.assertContains(res, si.availability_zone) self.assertContains( res, '%s' % ( si.share_id, si.share_id), 1, 200) api_manila.share_instance_list.assert_called_once_with(mock.ANY) self.assertEqual(0, api_keystone.tenant_list.call_count) def test_detail_view_share_instance(self): share_instance = test_data.share_instance share_id = share_instance.share_id ss_id = share_instance.share_server_id url = reverse('horizon:admin:share_instances:share_instance_detail', args=[share_instance.id]) self.mock_object( api_manila, "share_instance_get", mock.Mock(return_value=share_instance)) self.mock_object( api_manila, "share_instance_export_location_list", mock.Mock(return_value=test_data.export_locations)) res = self.client.get(url) self.assertContains( res, "

Share Instance Details: %s

" % share_instance.id, 1, 200) self.assertContains(res, "
%s
" % share_instance.id, 1, 200) self.assertContains(res, "
Available
", 1, 200) self.assertContains(res, "
%s
" % share_instance.host, 1, 200) self.assertContains( res, "
%s
" % share_instance.availability_zone, 1, 200) self.assertContains( res, "
%s
" % ( share_id, share_id), 1, 200) self.assertContains( res, "
%s
" % ( share_instance.share_network_id, share_instance.share_network_id), 1, 200) self.assertContains( res, "
%s
" % ( ss_id, ss_id), 1, 200) self.assertNoMessages() api_manila.share_instance_get.assert_called_once_with( mock.ANY, share_instance.id) api_manila.share_instance_export_location_list.assert_called_once_with( mock.ANY, share_instance.id) def test_detail_view_share_instance_with_exception(self): share_instance = test_data.share_instance url = reverse('horizon:admin:share_instances:share_instance_detail', args=[share_instance.id]) self.mock_object( api_manila, "share_instance_get", mock.Mock(side_effect=horizon_exceptions.NotFound(404))) res = self.client.get(url) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_instance_get.assert_called_once_with( mock.ANY, share_instance.id) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_networks/000077500000000000000000000000001323215354300250125ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_networks/__init__.py000066400000000000000000000000001323215354300271110ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_networks/tests.py000066400000000000000000000171461323215354300265370ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # Copyright (c) 2015 Mirantis, Inc. # # 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 django.core.urlresolvers import reverse from horizon import exceptions as horizon_exceptions import mock from neutronclient.client import exceptions from openstack_dashboard.api import keystone as api_keystone from openstack_dashboard.api import neutron as api_neutron from manila_ui.api import manila as api_manila from manila_ui.dashboards.admin import utils from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test from manila_ui.tests.test_data import keystone_data INDEX_URL = reverse('horizon:admin:share_networks:index') class ShareNetworksTests(test.BaseAdminViewTests): def setUp(self): super(self.__class__, self).setUp() self.mock_object( api_keystone, "tenant_list", mock.Mock(return_value=(keystone_data.projects, None))) # Reset taken list of projects to avoid test interference utils.PROJECTS = {} def test_detail_view(self): share_net = test_data.active_share_network sec_service = test_data.sec_service self.mock_object( api_manila, "share_server_list", mock.Mock(return_value=[])) self.mock_object( api_manila, "share_network_get", mock.Mock(return_value=share_net)) self.mock_object( api_manila, "share_network_security_service_list", mock.Mock(return_value=[sec_service])) network = self.networks.first() subnet = self.subnets.first() self.mock_object( api_neutron, "network_get", mock.Mock(return_value=network)) self.mock_object( api_neutron, "subnet_get", mock.Mock(return_value=subnet)) url = reverse('horizon:admin:share_networks:share_network_detail', args=[share_net.id]) res = self.client.get(url) self.assertContains(res, "

Share Network Details: %s

" % share_net.name, 1, 200) self.assertContains(res, "
%s
" % share_net.name, 1, 200) self.assertContains(res, "
%s
" % share_net.id, 1, 200) self.assertContains(res, "
%s
" % network.name_or_id, 1, 200) self.assertContains(res, "
%s
" % subnet.name_or_id, 1, 200) self.assertContains(res, "%s" % (sec_service.id, sec_service.name), 1, 200) self.assertNoMessages() api_manila.share_network_security_service_list.assert_called_once_with( mock.ANY, share_net.id) api_manila.share_server_list.assert_called_once_with( mock.ANY, search_opts={'share_network_id': share_net.id}) api_manila.share_network_get.assert_called_once_with( mock.ANY, share_net.id) api_neutron.network_get.assert_called_once_with( mock.ANY, share_net.neutron_net_id) api_neutron.subnet_get.assert_called_once_with( mock.ANY, share_net.neutron_subnet_id) def test_detail_view_network_not_found(self): share_net = test_data.active_share_network sec_service = test_data.sec_service url = reverse('horizon:admin:share_networks:share_network_detail', args=[share_net.id]) self.mock_object( api_manila, "share_server_list", mock.Mock(return_value=[])) self.mock_object( api_manila, "share_network_get", mock.Mock(return_value=share_net)) self.mock_object( api_manila, "share_network_security_service_list", mock.Mock(return_value=[sec_service])) self.mock_object( api_neutron, "network_get", mock.Mock( side_effect=exceptions.NeutronClientException('fake', 500))) self.mock_object( api_neutron, "subnet_get", mock.Mock( side_effect=exceptions.NeutronClientException('fake', 500))) res = self.client.get(url) self.assertContains(res, "

Share Network Details: %s

" % share_net.name, 1, 200) self.assertContains(res, "
%s
" % share_net.name, 1, 200) self.assertContains(res, "
%s
" % share_net.id, 1, 200) self.assertContains(res, "
Unknown
", 2, 200) self.assertNotContains(res, "
%s
" % share_net.neutron_net_id) self.assertNotContains(res, "
%s
" % share_net.neutron_subnet_id) self.assertContains(res, "%s" % (sec_service.id, sec_service.name), 1, 200) self.assertNoMessages() api_manila.share_network_security_service_list.assert_called_once_with( mock.ANY, share_net.id) api_manila.share_server_list.assert_called_once_with( mock.ANY, search_opts={'share_network_id': share_net.id}) api_manila.share_network_get.assert_called_once_with( mock.ANY, share_net.id) api_neutron.network_get.assert_called_once_with( mock.ANY, share_net.neutron_net_id) api_neutron.subnet_get.assert_called_once_with( mock.ANY, share_net.neutron_subnet_id) def test_detail_view_with_exception(self): url = reverse('horizon:admin:share_networks:share_network_detail', args=[test_data.active_share_network.id]) self.mock_object( api_manila, "share_network_get", mock.Mock(side_effect=horizon_exceptions.NotFound(404))) res = self.client.get(url) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_network_get.assert_called_once_with( mock.ANY, test_data.active_share_network.id) def test_delete_share_network(self): share_network = test_data.inactive_share_network formData = {'action': 'share_networks__delete__%s' % share_network.id} self.mock_object( api_neutron, "network_list", mock.Mock(return_value=[])) self.mock_object( api_neutron, "subnet_list", mock.Mock(return_value=[])) self.mock_object(api_manila, "share_network_delete") self.mock_object( api_manila, "share_network_list", mock.Mock(return_value=[ test_data.active_share_network, test_data.inactive_share_network])) res = self.client.post(INDEX_URL, formData) api_keystone.tenant_list.assert_called_once_with(mock.ANY) api_manila.share_network_delete.assert_called_once_with( mock.ANY, test_data.inactive_share_network.id) api_manila.share_network_list.assert_called_once_with( mock.ANY, detailed=True, search_opts={'all_tenants': True}) api_neutron.network_list.assert_called_once_with(mock.ANY) api_neutron.subnet_list.assert_called_once_with(mock.ANY) self.assertRedirectsNoFollow(res, INDEX_URL) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_servers/000077500000000000000000000000001323215354300246275ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_servers/__init__.py000066400000000000000000000000001323215354300267260ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_servers/tests.py000066400000000000000000000124331323215354300263460ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # Copyright (c) 2015 Mirantis, Inc. # # 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 django.core.urlresolvers import reverse from horizon import exceptions as horizon_exceptions import mock from openstack_dashboard.api import keystone as api_keystone from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:admin:share_servers:index') class ShareServerTests(test.BaseAdminViewTests): def test_list_share_servers(self): share_servers = [ test_data.share_server, test_data.share_server_errored, ] projects = [ type('FakeProject', (object, ), {'id': s.project_id, 'name': '%s_name' % s.project_id}) for s in share_servers ] projects_dict = {p.id: p for p in projects} self.mock_object( api_manila, "share_server_list", mock.Mock(return_value=share_servers)) self.mock_object( api_manila, "share_list", mock.Mock(side_effect=[ [], [test_data.share], [test_data.nameless_share]])) self.mock_object( api_keystone, "tenant_list", mock.Mock(return_value=(projects, None))) res = self.client.get(INDEX_URL) self.assertContains(res, "

Share Servers

") for share_server in share_servers: self.assertContains( res, '%s' % ( share_server.id, share_server.id), 1, 200) self.assertContains(res, share_server.host, 1, 200) self.assertContains( res, projects_dict[share_server.project_id].name, 1, 200) self.assertContains( res, '%s' % ( share_server.share_network_id, share_server.share_network), 1, 200) api_manila.share_list.assert_has_calls([ mock.call( mock.ANY, search_opts={'share_server_id': share_server.id}) for share_server in share_servers ]) api_manila.share_server_list.assert_called_once_with(mock.ANY) self.assertEqual(1, api_keystone.tenant_list.call_count) def test_detail_view_share_server(self): share_server = test_data.share_server shares = [test_data.share, test_data.nameless_share] url = reverse( 'horizon:admin:share_servers:share_server_detail', args=[share_server.id]) self.mock_object( api_manila, "share_server_get", mock.Mock(return_value=share_server)) self.mock_object( api_manila, "share_list", mock.Mock(return_value=shares)) res = self.client.get(url) self.assertContains( res, "

Share Server Details: %s

" % share_server.id, 1, 200) self.assertContains(res, "
%s
" % share_server.id, 1, 200) self.assertContains(res, "
Active
", 1, 200) self.assertContains(res, "
%s
" % share_server.host, 1, 200) self.assertContains( res, "
%s
" % ( share_server.share_network_id, share_server.share_network_name), 1, 200) self.assertContains( res, "
%s
" % ( shares[0].id, shares[0].name), 1, 200) self.assertContains( res, "
%s
" % ( shares[1].id, shares[1].id), 1, 200) for k, v in share_server.backend_details.items(): self.assertContains(res, "
%s
" % k) self.assertContains(res, "
%s
" % v) self.assertNoMessages() api_manila.share_server_get.assert_called_once_with( mock.ANY, share_server.id) api_manila.share_list.assert_called_once_with( mock.ANY, search_opts={"share_server_id": share_server.id}) def test_detail_view_share_server_with_exception(self): share_server = test_data.share_server url = reverse('horizon:admin:share_servers:share_server_detail', args=[share_server.id]) self.mock_object( api_manila, "share_server_get", mock.Mock(side_effect=horizon_exceptions.NotFound(404))) res = self.client.get(url) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_server_get.assert_called_once_with( mock.ANY, share_server.id) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_snapshots/000077500000000000000000000000001323215354300251605ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_snapshots/__init__.py000066400000000000000000000000001323215354300272570ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_snapshots/tests.py000066400000000000000000000151451323215354300267020ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # Copyright (c) 2015 Mirantis, Inc. # # 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 django.core.urlresolvers import reverse from horizon import exceptions as horizon_exceptions import mock from openstack_dashboard.api import keystone as api_keystone from manila_ui.api import manila as api_manila from manila_ui.dashboards.admin import utils from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test from manila_ui.tests.test_data import keystone_data INDEX_URL = reverse('horizon:admin:share_snapshots:index') class SnapshotsTests(test.BaseAdminViewTests): def setUp(self): super(self.__class__, self).setUp() self.mock_object( api_keystone, "tenant_list", mock.Mock(return_value=(keystone_data.projects, None))) # Reset taken list of projects to avoid test interference utils.PROJECTS = {} def test_detail_view(self): snapshot = test_data.snapshot share = test_data.share url = reverse('horizon:admin:share_snapshots:share_snapshot_detail', args=[snapshot.id]) self.mock_object( api_manila, "share_snapshot_get", mock.Mock(return_value=snapshot)) self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) res = self.client.get(url) self.assertContains(res, "

Snapshot Details: %s

" % snapshot.name, 1, 200) self.assertContains(res, "
%s
" % snapshot.name, 1, 200) self.assertContains(res, "
%s
" % snapshot.id, 1, 200) self.assertContains(res, "
%s
" % (snapshot.share_id, share.name), 1, 200) self.assertContains(res, "
%s GiB
" % snapshot.size, 1, 200) self.assertNoMessages() api_manila.share_get.assert_called_once_with(mock.ANY, share.id) api_manila.share_snapshot_get.assert_called_once_with( mock.ANY, snapshot.id) def test_detail_view_with_mount_support(self): snapshot = test_data.snapshot_mount_support rules = [test_data.ip_rule, test_data.user_rule, test_data.cephx_rule] export_locations = test_data.admin_snapshot_export_locations share = test_data.share_mount_snapshot url = reverse('horizon:admin:share_snapshots:share_snapshot_detail', args=[snapshot.id]) self.mock_object( api_manila, "share_snapshot_get", mock.Mock(return_value=snapshot)) self.mock_object( api_manila, "share_snapshot_rules_list", mock.Mock( return_value=rules)) self.mock_object( api_manila, "share_snap_export_location_list", mock.Mock( return_value=export_locations)) self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) res = self.client.get(url) self.assertContains(res, "

Snapshot Details: %s

" % snapshot.name, 1, 200) self.assertContains(res, "
%s
" % snapshot.name, 1, 200) self.assertContains(res, "
%s
" % snapshot.id, 1, 200) self.assertContains(res, "
%s
" % (snapshot.share_id, share.name), 1, 200) self.assertContains(res, "
%s GiB
" % snapshot.size, 1, 200) for el in export_locations: self.assertContains(res, "value=\"%s\"" % el.path, 1, 200) self.assertContains( res, "
Is admin only: %s
" % el.is_admin_only, 1, 200) self.assertContains( res, ("
Snapshot Replica ID: %s
" % el.share_snapshot_instance_id), 1, 200) for rule in rules: self.assertContains(res, "
%s
" % rule.access_type, 1, 200) self.assertContains( res, "
Access to: %s
" % rule.access_to, 1, 200) self.assertContains( res, "
Status: active
", len(rules), 200) self.assertNoMessages() api_manila.share_get.assert_called_once_with(mock.ANY, share.id) api_manila.share_snapshot_get.assert_called_once_with( mock.ANY, snapshot.id) api_manila.share_snapshot_rules_list.assert_called_once_with( mock.ANY, snapshot.id) api_manila.share_snap_export_location_list.assert_called_once_with( mock.ANY, snapshot) def test_detail_view_with_exception(self): url = reverse('horizon:admin:share_snapshots:share_snapshot_detail', args=[test_data.snapshot.id]) self.mock_object( api_manila, "share_snapshot_get", mock.Mock(side_effect=horizon_exceptions.NotFound(404))) res = self.client.get(url) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_snapshot_get.assert_called_once_with( mock.ANY, test_data.snapshot.id) def test_delete_snapshot(self): share = test_data.share snapshot = test_data.snapshot formData = {'action': 'share_snapshots__delete__%s' % snapshot.id} self.mock_object(api_manila, "share_snapshot_delete") self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=[snapshot])) self.mock_object( api_manila, "share_list", mock.Mock(return_value=[share])) res = self.client.post(INDEX_URL, formData) api_keystone.tenant_list.assert_called_once_with(mock.ANY) api_manila.share_snapshot_delete.assert_called_once_with( mock.ANY, test_data.snapshot.id) api_manila.share_snapshot_list.assert_called_once_with( mock.ANY, search_opts={'all_tenants': True}) api_manila.share_list.assert_called_once_with(mock.ANY) self.assertRedirectsNoFollow(res, INDEX_URL) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_types/000077500000000000000000000000001323215354300243025ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_types/__init__.py000066400000000000000000000000001323215354300264010ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_types/test_forms.py000066400000000000000000000227711323215354300270520ustar00rootroot00000000000000# Copyright (c) 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 django.core.handlers import wsgi from django import forms as django_forms from horizon import forms as horizon_forms import mock from manila_ui.dashboards.admin.share_types import forms from manila_ui.tests import helpers as base @ddt.ddt class ManilaDashboardsAdminSharesUpdateShareTypeFormTests(base.APITestCase): def setUp(self): super(self.__class__, self).setUp() FAKE_ENVIRON = {'REQUEST_METHOD': 'GET', 'wsgi.input': 'fake_input'} self.request = wsgi.WSGIRequest(FAKE_ENVIRON) def _get_form(self, initial): kwargs = { 'prefix': None, 'initial': initial, } return forms.UpdateShareType(self.request, **kwargs) @ddt.data( ({}, []), ({'foo': 'bar', 'quuz': 'zaab'}, ["foo=bar\r\n", "quuz=zaab\r\n"]), ) @ddt.unpack def test___init__(self, extra_specs_dict_input, extra_specs_str_output): form = self._get_form({'extra_specs': extra_specs_dict_input}) for expected_extra_spec in extra_specs_str_output: self.assertIn(expected_extra_spec, form.initial['extra_specs']) self.assertIn('extra_specs', list(form.fields.keys())) self.assertTrue( isinstance(form.fields['extra_specs'], horizon_forms.CharField)) @mock.patch('horizon.messages.success') def test_handle_success_no_changes(self, mock_horizon_messages_success): initial = {'id': 'fake_id', 'name': 'fake_name', 'extra_specs': {}} form = self._get_form(initial) data = {'extra_specs': ''} result = form.handle(self.request, data) self.assertTrue(result) mock_horizon_messages_success.assert_called_once_with( mock.ANY, mock.ANY) @mock.patch('horizon.messages.success') def test_handle_success_only_set(self, mock_horizon_messages_success): initial = { 'id': 'fake_id', 'name': 'fake_name', 'extra_specs': {'foo': 'bar'} } form = self._get_form(initial) data = {'extra_specs': 'foo=bar\r\n'} result = form.handle(self.request, data) self.assertTrue(result) mock_horizon_messages_success.assert_called_once_with( mock.ANY, mock.ANY) self.manilaclient.share_types.get.assert_called_once_with( initial['id']) self.manilaclient.share_types.get.return_value.set_keys.\ assert_called_once_with({'foo': 'bar'}) self.assertFalse( self.manilaclient.share_types.get.return_value.unset_keys.called) @mock.patch('horizon.messages.success') def test_handle_success_only_unset(self, mock_horizon_messages_success): initial = { 'id': 'fake_id', 'name': 'fake_name', 'extra_specs': {'foo': 'bar'} } form = self._get_form(initial) data = {'extra_specs': 'foo\r\n'} share_types_get = self.manilaclient.share_types.get share_types_get.return_value.get_keys.return_value = { 'foo': 'bar', 'quuz': 'zaab'} result = form.handle(self.request, data) self.assertTrue(result) mock_horizon_messages_success.assert_called_once_with( mock.ANY, mock.ANY) self.manilaclient.share_types.get.assert_has_calls([ mock.call(initial['id'])]) share_types_get.return_value.get_keys.assert_called_once_with() self.assertFalse(share_types_get.return_value.set_keys.called) share_types_get.return_value.unset_keys.assert_called_once_with( {'foo'}) @mock.patch('horizon.messages.success') def test_handle_success_set_and_unset(self, mock_horizon_messages_success): initial = { 'id': 'fake_id', 'name': 'fake_name', 'extra_specs': {'foo': 'bar'} } form = self._get_form(initial) data = {'extra_specs': 'foo\r\nquuz=zaab'} share_types_get = self.manilaclient.share_types.get share_types_get.return_value.get_keys.return_value = {'foo': 'bar'} result = form.handle(self.request, data) self.assertTrue(result) mock_horizon_messages_success.assert_called_once_with( mock.ANY, mock.ANY) self.manilaclient.share_types.get.assert_has_calls([ mock.call(initial['id'])]) share_types_get.return_value.get_keys.assert_called_once_with() share_types_get.return_value.set_keys.assert_called_once_with( {'quuz': 'zaab'}) share_types_get.return_value.unset_keys.assert_called_once_with( {'foo'}) def test_handle_validation_error(self): initial = {'id': 'fake_id', 'name': 'fake_name', 'extra_specs': {}} form = self._get_form(initial) form.api_error = mock.Mock() data = {'extra_specs': 'a b'} result = form.handle(self.request, data) self.assertFalse(result) form.api_error.assert_called_once_with(mock.ANY) @mock.patch('horizon.exceptions.handle') def test_handle_other_exception(self, mock_horizon_exceptions_handle): django_forms.ValidationError initial = {'id': 'fake_id', 'name': 'fake_name', 'extra_specs': {}} form = self._get_form(initial) data = {'extra_specs': None} result = form.handle(self.request, data) self.assertFalse(result) mock_horizon_exceptions_handle.assert_called_once_with( self.request, mock.ANY) @ddt.ddt class ManilaDashboardsAdminSharesCreateShareTypeFormTests(base.APITestCase): def setUp(self): super(self.__class__, self).setUp() FAKE_ENVIRON = {'REQUEST_METHOD': 'GET', 'wsgi.input': 'fake_input'} self.request = wsgi.WSGIRequest(FAKE_ENVIRON) def _get_form(self, **kwargs): return forms.CreateShareType(self.request, **kwargs) @mock.patch('horizon.messages.success') def test_create_share_type(self, mock_horizon_messages_success): form = self._get_form() data = { 'extra_specs': '', 'is_public': False, 'spec_driver_handles_share_servers': 'True', 'name': 'share', } result = form.handle(self.request, data) self.assertTrue(result) self.manilaclient.share_types.create.assert_called_once_with( name=data['name'], spec_driver_handles_share_servers='true', spec_snapshot_support=True, is_public=data["is_public"]) mock_horizon_messages_success.assert_called_once_with( self.request, mock.ANY) @mock.patch('horizon.messages.success') def test_create_share_type_with_extra_specs(self, mock_horizon_messages_success): form = self._get_form() data = {'extra_specs': 'a=b \n c=d', 'is_public': False, 'spec_driver_handles_share_servers': 'True', 'name': 'share'} result = form.handle(self.request, data) self.assertTrue(result) set_keys = self.manilaclient.share_types.get.return_value.set_keys set_keys.assert_called_once_with( {'a': 'b', 'c': 'd'}) self.manilaclient.share_types.create.assert_called_once_with( name=data['name'], spec_driver_handles_share_servers='true', spec_snapshot_support=True, is_public=data["is_public"]) mock_horizon_messages_success.assert_called_once_with( self.request, mock.ANY) @ddt.data(True, False) @mock.patch('horizon.messages.success') def test_public_share_type_creation(self, enable_public_share_type_creation, mock_horizon_messages_success): with self.settings(OPENSTACK_MANILA_FEATURES={ 'enable_public_share_type_creation': enable_public_share_type_creation}): form = self._get_form() data = { 'extra_specs': '', 'is_public': enable_public_share_type_creation, 'spec_driver_handles_share_servers': 'True', 'name': 'share', } result = form.handle(self.request, data) self.assertTrue(result) self.assertEqual( enable_public_share_type_creation, form.enable_public_share_type_creation) if enable_public_share_type_creation: self.assertIn("is_public", form.fields) self.assertTrue(form.fields["is_public"]) else: self.assertNotIn("is_public", form.fields) self.manilaclient.share_types.create.assert_called_once_with( name=data['name'], spec_driver_handles_share_servers='true', spec_snapshot_support=True, is_public=enable_public_share_type_creation) mock_horizon_messages_success.assert_called_once_with( self.request, mock.ANY) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/share_types/tests.py000066400000000000000000000065201323215354300260210ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # Copyright (c) 2015 Mirantis, Inc. # # 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 django.core.urlresolvers import reverse import mock from openstack_dashboard.api import keystone as api_keystone from openstack_dashboard.api import neutron as api_neutron from manila_ui.api import manila as api_manila from manila_ui.dashboards.admin import utils from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test from manila_ui.tests.test_data import keystone_data INDEX_URL = reverse('horizon:admin:share_types:index') class ShareTypeTests(test.BaseAdminViewTests): def setUp(self): super(self.__class__, self).setUp() self.share_type = test_data.share_type self.url = reverse('horizon:admin:share_types:update_type', args=[self.share_type.id]) self.mock_object( api_manila, "share_type_get", mock.Mock(return_value=self.share_type)) self.mock_object( api_keystone, "tenant_list", mock.Mock(return_value=(keystone_data.projects, None))) self.mock_object( api_neutron, "is_service_enabled", mock.Mock(return_value=[True])) # Reset taken list of projects to avoid test interference utils.PROJECTS = {} def test_create_share_type(self): url = reverse('horizon:admin:share_types:create_type') data = { 'is_public': True, 'name': 'my_share_type', 'spec_driver_handles_share_servers': 'False' } form_data = data.copy() form_data['spec_driver_handles_share_servers'] = 'false' self.mock_object(api_manila, "share_type_create") res = self.client.post(url, data) api_manila.share_type_create.assert_called_once_with( mock.ANY, form_data['name'], form_data['spec_driver_handles_share_servers'], is_public=form_data['is_public']) self.assertRedirectsNoFollow(res, INDEX_URL) def test_update_share_type_get(self): res = self.client.get(self.url) api_manila.share_type_get.assert_called_once_with( mock.ANY, self.share_type.id) self.assertNoMessages() self.assertTemplateUsed(res, 'admin/share_types/update.html') def test_update_share_type_post(self): data = { 'extra_specs': 'driver_handles_share_servers=True' } form_data = { 'extra_specs': {'driver_handles_share_servers': 'True'}, } self.mock_object(api_manila, "share_type_set_extra_specs") res = self.client.post(self.url, data) api_manila.share_type_set_extra_specs.assert_called_once_with( mock.ANY, self.share_type.id, form_data['extra_specs']) self.assertRedirectsNoFollow(res, INDEX_URL) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/shares/000077500000000000000000000000001323215354300232415ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/shares/__init__.py000066400000000000000000000000001323215354300253400ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/shares/replicas/000077500000000000000000000000001323215354300250435ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/shares/replicas/__init__.py000066400000000000000000000000001323215354300271420ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/admin/shares/replicas/tests.py000066400000000000000000000347741323215354300265760ustar00rootroot00000000000000# Copyright (c) 2016 Mirantis, Inc. # # 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 import ddt from django.core.urlresolvers import reverse import mock from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test from openstack_dashboard.api import neutron SHARE_INDEX_URL = reverse('horizon:admin:shares:index') @ddt.ddt class ReplicasTests(test.BaseAdminViewTests): def setUp(self): super(self.__class__, self).setUp() self.share = test_data.share self.share_replica = test_data.share_replica self.share_replica2 = test_data.share_replica2 self.mock_object( api_manila, "share_get", mock.Mock(return_value=self.share)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) def test_detail(self): url = reverse( "horizon:admin:shares:replica_detail", args=[self.share_replica.id]) export_locations = test_data.export_locations self.mock_object( api_manila, "share_replica_get", mock.Mock(return_value=self.share_replica)) self.mock_object( api_manila, "share_instance_export_location_list", mock.Mock(return_value=export_locations)) res = self.client.get(url) self.assertEqual(200, res.status_code) self.assertTemplateUsed(res, "admin/shares/replicas/detail.html") self.assertNoMessages() self.assertContains(res, "

Share Replica Overview", 1, 200) self.assertContains(res, ">%s" % self.share.id, 1, 200) self.assertContains(res, "
%s
" % self.share_replica.id, 1, 200) self.assertContains( res, "
%s
" % self.share.availability_zone, 1, 200) for el in export_locations: self.assertContains(res, "value=\"%s\"" % el.path, 1, 200) self.assertContains( res, "
Preferred: %s
" % el.preferred, 1, 200) self.assertContains( res, "
Is admin only: %s
" % el.is_admin_only, 1, 200) self.assertNoMessages() api_manila.share_replica_get.assert_called_once_with( mock.ANY, self.share_replica.id) api_manila.share_instance_export_location_list.assert_called_once_with( mock.ANY, self.share_replica.id) def test_detail_not_found(self): url = reverse("horizon:admin:shares:replica_detail", args=[self.share_replica.id]) self.mock_object( api_manila, "share_replica_get", mock.Mock( side_effect=Exception("Fake replica NotFound exception"))) self.mock_object(api_manila, "share_instance_export_location_list") res = self.client.get(url) self.assertEqual(302, res.status_code) self.assertRedirectsNoFollow(res, SHARE_INDEX_URL) self.assertTemplateNotUsed(res, "admin/shares/replicas/detail.html") api_manila.share_replica_get.assert_called_once_with( mock.ANY, self.share_replica.id) self.assertFalse(api_manila.share_instance_export_location_list.called) def test_list(self): self.mock_object( api_manila, "share_replica_list", mock.Mock(return_value=[self.share_replica])) url = reverse( "horizon:admin:shares:manage_replicas", args=[self.share.id]) res = self.client.get(url) self.assertEqual(200, res.status_code) self.assertTemplateUsed( res, "admin/shares/replicas/manage_replicas.html") api_manila.share_get.assert_called_with(mock.ANY, self.share.id) api_manila.share_replica_list.assert_called_with( mock.ANY, self.share.id) def test_list_exception(self): self.mock_object( api_manila, "share_replica_list", mock.Mock(side_effect=Exception("Fake exception"))) url = reverse( "horizon:admin:shares:manage_replicas", args=[self.share.id]) res = self.client.get(url) self.assertEqual(302, res.status_code) self.assertRedirectsNoFollow(res, SHARE_INDEX_URL) self.assertTemplateNotUsed( res, "admin/shares/replicas/manage_replicas.html") api_manila.share_replica_list.assert_called_with( mock.ANY, self.share.id) @ddt.data( ([test_data.share_replica], test_data.share_replica.id, None), ([test_data.share_replica], test_data.share_replica.id, 'dr'), ([test_data.share_replica], test_data.share_replica.id, 'readable'), ([test_data.share_replica], test_data.share_replica.id, 'writable'), ([test_data.share_replica, test_data.share_replica2], test_data.share_replica.id, 'dr'), ([test_data.share_replica, test_data.share_replica2], test_data.share_replica.id, 'readable'), ) @ddt.unpack def test_delete_not_allowed(self, replica_list, replica_id, replication_type): share = copy.copy(self.share) share.replication_type = replication_type formData = {"action": "replicas__delete__%s" % replica_id} self.mock_object(api_manila, "share_replica_delete") self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object( api_manila, "share_replica_list", mock.Mock(return_value=replica_list)) url = reverse( "horizon:admin:shares:manage_replicas", args=[share.id]) res = self.client.post(url, formData) self.assertEqual(302, res.status_code) self.assertRedirectsNoFollow(res, url) api_manila.share_replica_list.assert_called_with(mock.ANY, share.id) self.assertFalse(api_manila.share_replica_delete.called) @ddt.data( ([test_data.share_replica, test_data.share_replica2], test_data.share_replica2.id, 'dr'), ([test_data.share_replica, test_data.share_replica2], test_data.share_replica2.id, 'readable'), ([test_data.share_replica, test_data.share_replica3], test_data.share_replica.id, 'writable'), ([test_data.share_replica, test_data.share_replica3], test_data.share_replica3.id, 'writable'), ) @ddt.unpack def test_delete_allowed(self, replica_list, replica_id, replication_type): share = copy.copy(self.share) share.replication_type = replication_type formData = {"action": "replicas__delete__%s" % replica_id} self.mock_object(api_manila, "share_replica_delete") self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object( api_manila, "share_replica_list", mock.Mock(return_value=replica_list)) url = reverse( "horizon:admin:shares:manage_replicas", args=[share.id]) res = self.client.post(url, formData) self.assertEqual(302, res.status_code) self.assertRedirectsNoFollow(res, url) api_manila.share_replica_list.assert_called_with(mock.ANY, share.id) api_manila.share_replica_delete.assert_called_with( mock.ANY, replica_id) def test_resync_replica_get(self): url = reverse( "horizon:admin:shares:resync_replica", args=[self.share_replica.id]) self.mock_object(api_manila, "share_replica_get") self.mock_object(api_manila, "share_replica_resync") res = self.client.get(url) self.assertEqual(200, res.status_code) self.assertTemplateUsed( res, "admin/shares/replicas/resync_replica.html") self.assertFalse(api_manila.share_replica_get.called) self.assertFalse(api_manila.share_replica_resync.called) def _resync_post(self): url = reverse( "horizon:admin:shares:resync_replica", args=[self.share_replica.id]) self.mock_object( api_manila, "share_replica_get", mock.Mock(return_value=self.share_replica)) formData = { "method": "ResyncReplicaForm", "replica_id": self.share_replica.id, } res = self.client.post(url, formData) self.assertEqual(302, res.status_code) self.assertTemplateNotUsed( res, "admin/shares/replicas/resync_replica.html") api_manila.share_replica_resync.assert_called_once_with( mock.ANY, self.share_replica) return res def test_resync_post(self): self.mock_object(api_manila, "share_replica_resync") res = self._resync_post() self.assertRedirectsNoFollow( res, reverse("horizon:admin:shares:manage_replicas", args=[self.share.id])) def test_resync_post_error(self): self.mock_object( api_manila, "share_replica_resync", mock.Mock(side_effect=Exception("Fake exception"))) res = self._resync_post() self.assertRedirectsNoFollow( res, reverse("horizon:admin:shares:index")) def test_reset_replica_status_get(self): url = reverse( "horizon:admin:shares:reset_replica_status", args=[self.share_replica.id]) self.mock_object(api_manila, "share_replica_get") self.mock_object(api_manila, "share_replica_reset_status") res = self.client.get(url) self.assertEqual(200, res.status_code) self.assertTemplateUsed( res, "admin/shares/replicas/reset_replica_status.html") self.assertFalse(api_manila.share_replica_get.called) self.assertFalse(api_manila.share_replica_reset_status.called) @ddt.data("available", "creating", "deleting", "error") def test_reset_replica_status_post(self, status): url = reverse( "horizon:admin:shares:reset_replica_status", args=[self.share_replica.id]) self.mock_object( api_manila, "share_replica_get", mock.Mock(return_value=self.share_replica)) self.mock_object(api_manila, "share_replica_reset_status") form_data = {"replica_status": status} res = self.client.post(url, form_data) self.assertEqual(302, res.status_code) self.assertTemplateNotUsed( res, "admin/shares/replicas/reset_replica_status.html") api_manila.share_replica_reset_status.assert_called_once_with( mock.ANY, self.share_replica, status) self.assertRedirectsNoFollow( res, reverse("horizon:admin:shares:manage_replicas", args=[self.share.id])) def test_reset_replica_status_error(self): status = "error" url = reverse( "horizon:admin:shares:reset_replica_status", args=[self.share_replica.id]) self.mock_object( api_manila, "share_replica_get", mock.Mock(return_value=self.share_replica)) self.mock_object( api_manila, "share_replica_reset_status", mock.Mock(side_effect=Exception("Fake exception"))) form_data = {"replica_status": status} res = self.client.post(url, form_data) self.assertEqual(302, res.status_code) self.assertTemplateNotUsed( res, "admin/shares/replicas/reset_replica_status.html") api_manila.share_replica_reset_status.assert_called_once_with( mock.ANY, self.share_replica, status) self.assertRedirectsNoFollow( res, reverse("horizon:admin:shares:index")) def test_reset_replica_state_get(self): url = reverse( "horizon:admin:shares:reset_replica_state", args=[self.share_replica.id]) self.mock_object(api_manila, "share_replica_get") self.mock_object(api_manila, "share_replica_reset_state") res = self.client.get(url) self.assertEqual(200, res.status_code) self.assertTemplateUsed( res, "admin/shares/replicas/reset_replica_state.html") self.assertFalse(api_manila.share_replica_get.called) self.assertFalse(api_manila.share_replica_reset_state.called) @ddt.data("active", "in_sync", "out_of_sync", "error") def test_reset_replica_state_post(self, state): url = reverse( "horizon:admin:shares:reset_replica_state", args=[self.share_replica.id]) self.mock_object( api_manila, "share_replica_get", mock.Mock(return_value=self.share_replica)) self.mock_object(api_manila, "share_replica_reset_state") form_data = {"replica_state": state} res = self.client.post(url, form_data) self.assertEqual(302, res.status_code) self.assertTemplateNotUsed( res, "admin/shares/replicas/reset_replica_state.html") api_manila.share_replica_reset_state.assert_called_once_with( mock.ANY, self.share_replica, state) self.assertRedirectsNoFollow( res, reverse("horizon:admin:shares:manage_replicas", args=[self.share.id])) def test_reset_replica_state_error(self): state = "error" url = reverse( "horizon:admin:shares:reset_replica_state", args=[self.share_replica.id]) self.mock_object( api_manila, "share_replica_get", mock.Mock(return_value=self.share_replica)) self.mock_object( api_manila, "share_replica_reset_state", mock.Mock(side_effect=Exception("Fake exception"))) form_data = {"replica_state": state} res = self.client.post(url, form_data) self.assertEqual(302, res.status_code) self.assertTemplateNotUsed( res, "admin/shares/replicas/reset_replica_state.html") api_manila.share_replica_reset_state.assert_called_once_with( mock.ANY, self.share_replica, state) self.assertRedirectsNoFollow( res, reverse("horizon:admin:shares:index")) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/shares/test_forms.py000066400000000000000000000102121323215354300257740ustar00rootroot00000000000000# Copyright (c) 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 django.core.handlers import wsgi import mock from manila_ui.api import manila as api from manila_ui.dashboards.admin.shares import forms from manila_ui.tests import helpers as base class ManilaDashboardsAdminMigrationFormTests(base.APITestCase): def setUp(self): super(self.__class__, self).setUp() FAKE_ENVIRON = {'REQUEST_METHOD': 'GET', 'wsgi.input': 'fake_input'} self.request = wsgi.WSGIRequest(FAKE_ENVIRON) def _get_initial(self): initial = {'name': 'fake_name', 'share_id': 'fake_id'} kwargs = { 'prefix': None, 'initial': initial, } return kwargs @mock.patch('horizon.messages.success') def test_migration_start(self, mock_horizon_messages_success): self.mock_object( api, "share_network_list", mock.Mock(return_value=[base.FakeEntity('sn1_id', 'sn1_name'), base.FakeEntity('sn2_id', 'sn2_name')])) self.mock_object( api, "share_type_list", mock.Mock(return_value=[base.FakeEntity('st1_id', 'st1_name'), base.FakeEntity('st2_id', 'st2_name')])) self.mock_object( api, "pool_list", mock.Mock(return_value=[base.FakeEntity('ubuntu@beta#BETA', 'ubuntu@beta#BETA'), base.FakeEntity('ubuntu@alpha#ALPHA', 'ubuntu@alpha#ALPHA')])) form = forms.MigrationStart(self.request, **self._get_initial()) data = { 'force_host_assisted_migration': False, 'writable': True, 'preserve_metadata': True, 'preserve_snapshots': True, 'nondisruptive': True, 'new_share_network': 'fake_net_id', 'new_share_type': 'fake_type_id', 'host': 'fake_host', } result = form.handle(self.request, data) self.assertTrue(result) mock_horizon_messages_success.assert_called_once_with( self.request, mock.ANY) api.share_network_list.assert_called_once_with(mock.ANY) api.share_type_list.assert_called_once_with(mock.ANY) api.pool_list.assert_called_once_with(mock.ANY) @mock.patch('horizon.messages.success') def test_migration_complete(self, mock_horizon_messages_success): form = forms.MigrationComplete(self.request, **self._get_initial()) result = form.handle(self.request, {}) self.assertTrue(result) mock_horizon_messages_success.assert_called_once_with( self.request, mock.ANY) @mock.patch('horizon.messages.success') def test_migration_cancel(self, mock_horizon_messages_success): form = forms.MigrationCancel(self.request, **self._get_initial()) result = form.handle(self.request, {}) self.assertTrue(result) mock_horizon_messages_success.assert_called_once_with( self.request, mock.ANY) @mock.patch('horizon.messages.success') def test_migration_get_progress(self, mock_horizon_messages_success): result = ({'Response': 200}, {'total_progress': 25}) self.mock_object(api, 'migration_get_progress', mock.Mock(return_value=result)) form = forms.MigrationGetProgress(self.request, **self._get_initial()) result = form.handle(self.request, {}) self.assertTrue(result) mock_horizon_messages_success.assert_called_once_with( self.request, mock.ANY) manila-ui-2.13.0/manila_ui/tests/dashboards/admin/shares/tests.py000066400000000000000000000251371323215354300247650ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # Copyright (c) 2015 Mirantis, Inc. # # 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 django.core.urlresolvers import reverse import mock from openstack_dashboard.api import keystone as api_keystone from openstack_dashboard.api import neutron as api_neutron from openstack_dashboard.usage import quotas from manila_ui.api import manila as api_manila from manila_ui.dashboards.admin import utils from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test from manila_ui.tests.test_data import keystone_data INDEX_URL = reverse('horizon:admin:shares:index') @ddt.ddt class SharesTests(test.BaseAdminViewTests): def setUp(self): super(self.__class__, self).setUp() self.mock_object(utils.timeutils, 'now', mock.Mock(return_value=1)) self.mock_object( api_keystone, "tenant_list", mock.Mock(return_value=(keystone_data.projects, None))) # Reset taken list of projects to avoid test interference utils.PROJECTS = {} def test_index(self): snaps = [test_data.snapshot] shares = [test_data.share, test_data.nameless_share, test_data.other_share] utils.timeutils.now.side_effect = [4] + [24 + i for i in range(4)] self.mock_object( api_manila, "share_list", mock.Mock(return_value=shares)) self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=snaps)) self.mock_object( api_neutron, "is_service_enabled", mock.Mock(return_value=[True])) self.mock_object( quotas, "tenant_limit_usages", mock.Mock(return_value=test_data.quota_usage)) self.mock_object( quotas, "tenant_quota_usages", mock.Mock(return_value=test_data.quota_usage)) res = self.client.get(INDEX_URL) self.assertTemplateUsed(res, 'admin/shares/index.html') self.assertEqual(res.status_code, 200) api_manila.share_list.assert_called_with( mock.ANY, search_opts={'all_tenants': True}) api_manila.share_snapshot_list.assert_called_with( mock.ANY, detailed=True, search_opts={'all_tenants': True}) api_keystone.tenant_list.assert_called_once_with(mock.ANY) def test_delete_share(self): url = reverse('horizon:admin:shares:index') share = test_data.share formData = {'action': 'shares__delete__%s' % share.id} self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=[])) self.mock_object(api_manila, "share_delete") self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object( api_manila, "share_list", mock.Mock(return_value=[share])) res = self.client.post(url, formData) api_keystone.tenant_list.assert_called_once_with(mock.ANY) api_manila.share_delete.assert_called_once_with( mock.ANY, share.id, share_group_id=share.share_group_id) api_manila.share_list.assert_called_once_with( mock.ANY, search_opts={'all_tenants': True}) api_manila.share_snapshot_list.assert_called_once_with( mock.ANY, detailed=True, search_opts={'all_tenants': True}) self.assertRedirectsNoFollow(res, INDEX_URL) @ddt.data(None, Exception('fake')) def test_migration_start_post(self, exc): share = test_data.share url = reverse('horizon:admin:shares:migration_start', args=[share.id]) sn_choices = [test.FakeEntity('sn1_id', 'sn1_name'), test.FakeEntity('sn2_id', 'sn2_name')] st_choices = [test.FakeEntity('st1_id', 'st1_name'), test.FakeEntity('st2_id', 'st2_name')] dest_choices = [ test.FakeEntity('ubuntu@beta#BETA', 'ubuntu@beta#BETA'), test.FakeEntity('ubuntu@alpha#ALPHA', 'ubuntu@alpha#ALPHA') ] formData = { 'share_id': share.id, 'name': share.name, 'host': 'ubuntu@alpha#ALPHA', 'writable': True, 'preserve_metadata': True, 'preserve_snapshots': True, 'force_host_assisted_migration': True, 'nondisruptive': True, 'new_share_network': 'sn2_id', 'new_share_type': 'st2_id', } self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object( api_manila, "migration_start", mock.Mock(side_effect=exc)) self.mock_object( api_manila, "share_network_list", mock.Mock(return_value=sn_choices)) self.mock_object( api_manila, "share_type_list", mock.Mock(return_value=st_choices)) self.mock_object( api_manila, "pool_list", mock.Mock(return_value=dest_choices)) res = self.client.post(url, formData) api_manila.share_get.assert_called_once_with(mock.ANY, share.id) api_manila.migration_start.assert_called_once_with( mock.ANY, formData['share_id'], dest_host=formData['host'], force_host_assisted_migration=( formData['force_host_assisted_migration']), writable=formData['writable'], preserve_metadata=formData['preserve_metadata'], preserve_snapshots=formData['preserve_snapshots'], nondisruptive=formData['nondisruptive'], new_share_network_id=formData['new_share_network'], new_share_type_id=formData['new_share_type']) api_manila.share_network_list.assert_called_once_with(mock.ANY) api_manila.share_type_list.assert_called_once_with(mock.ANY) api_manila.pool_list.assert_called_once_with(mock.ANY) self.assertEqual(302, res.status_code) self.assertTemplateNotUsed(res, 'admin/shares/migration_start.html') self.assertRedirectsNoFollow(res, INDEX_URL) @ddt.data('migration_start', 'migration_cancel', 'migration_complete', 'migration_get_progress') def test_migration_forms_open_form_successfully(self, method): share = test_data.share url = reverse('horizon:admin:shares:' + method, args=[share.id]) self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object(api_manila, method) if method == 'migration_start': self.mock_object( api_manila, "share_network_list", mock.Mock( return_value=[test.FakeEntity('sn1_id', 'sn1_name'), test.FakeEntity('sn2_id', 'sn2_name')])) self.mock_object( api_manila, "share_type_list", mock.Mock( return_value=[test.FakeEntity('st1_id', 'st1_name'), test.FakeEntity('st2_id', 'st2_name')])) self.mock_object( api_manila, "pool_list", mock.Mock(return_value=[test.FakeEntity('ubuntu@beta#BETA', 'ubuntu@beta#BETA'), test.FakeEntity('ubuntu@alpha#ALPHA', 'ubuntu@alpha#ALPHA') ])) res = self.client.get(url) api_manila.share_get.assert_called_once_with(mock.ANY, share.id) self.assertFalse(getattr(api_manila, method).called) self.assertEqual(res.status_code, 200) self.assertTemplateUsed(res, 'admin/shares/' + method + '.html') if method == 'migration_start': api_manila.share_network_list.assert_called_once_with(mock.ANY) api_manila.share_type_list.assert_called_once_with(mock.ANY) api_manila.pool_list.assert_called_once_with(mock.ANY) @ddt.data('migration_start', 'migration_cancel', 'migration_complete', 'migration_get_progress') def test_migration_start_get_share_exception(self, method): share = test_data.share url = reverse('horizon:admin:shares:' + method, args=[share.id]) self.mock_object( api_manila, "share_get", mock.Mock(side_effect=Exception('fake'))) self.mock_object(api_manila, method) res = self.client.get(url) api_manila.share_get.assert_called_once_with(mock.ANY, share.id) self.assertFalse(getattr(api_manila, method).called) self.assertEqual(res.status_code, 302) self.assertTemplateNotUsed(res, 'admin/shares/' + method + '.html') @ddt.data({'method': 'migration_complete', 'exc': None}, {'method': 'migration_complete', 'exc': Exception('fake')}, {'method': 'migration_cancel', 'exc': None}, {'method': 'migration_cancel', 'exc': Exception('fake')}, {'method': 'migration_get_progress', 'exc': {'response': 200, 'total_progress': 25}}, {'method': 'migration_get_progress', 'exc': Exception('fake')}) @ddt.unpack def test_migration_forms_post(self, exc, method): share = test_data.share url = reverse('horizon:admin:shares:' + method, args=[share.id]) formData = { 'share_id': share.id, 'name': share.name, } self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object(api_manila, method, mock.Mock( side_effect=exc)) res = self.client.post(url, formData) api_manila.share_get.assert_called_once_with(mock.ANY, share.id) getattr(api_manila, method).assert_called_once_with( mock.ANY, formData['share_id']) status_code = 200 if exc else 302 self.assertEqual(res.status_code, status_code) if not exc: self.assertTemplateNotUsed( res, 'admin/shares/' + method + '.html') self.assertRedirectsNoFollow(res, INDEX_URL) else: self.assertTemplateUsed( res, 'admin/shares/' + method + '.html') manila-ui-2.13.0/manila_ui/tests/dashboards/project/000077500000000000000000000000001323215354300223325ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/__init__.py000066400000000000000000000000001323215354300244310ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/security_services/000077500000000000000000000000001323215354300261045ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/security_services/__init__.py000066400000000000000000000000001323215354300302030ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/security_services/tests.py000066400000000000000000000140521323215354300276220ustar00rootroot00000000000000# Copyright 2012 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # Copyright 2012 Nebula, Inc. # # 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 django.core.urlresolvers import reverse from horizon import exceptions as horizon_exceptions import mock from openstack_dashboard import api from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:project:security_services:index') class SecurityServicesViewTests(test.TestCase): def test_create_security_service(self): sec_service = test_data.sec_service formData = { 'name': u'new_sec_service', 'description': u'This is test security service', 'method': u'CreateForm', 'dns_ip': '1.2.3.4', 'user': 'SomeUser', 'password': 'safepass', 'confirm_password': 'safepass', 'type': 'ldap', 'domain': 'TEST', 'server': 'testserver', } url = reverse( 'horizon:project:security_services:security_service_create') self.mock_object( api_manila, "security_service_create", mock.Mock(return_value=sec_service)) res = self.client.post(url, formData) del formData['method'] del formData['confirm_password'] api_manila.security_service_create.assert_called_with( mock.ANY, **formData) self.assertRedirectsNoFollow(res, INDEX_URL) def test_delete_security_service(self): security_service = test_data.sec_service formData = { 'action': 'security_services__delete__%s' % security_service.id, } self.mock_object(api_manila, "security_service_delete") self.mock_object( api_manila, "security_service_list", mock.Mock(return_value=[security_service])) res = self.client.post(INDEX_URL, formData) api_manila.security_service_list.assert_called_with(mock.ANY) api_manila.security_service_delete.assert_called_with( mock.ANY, security_service.id) self.assertRedirectsNoFollow(res, INDEX_URL) def test_detail_view(self): sec_service = test_data.sec_service self.mock_object( api_manila, "security_service_get", mock.Mock(return_value=sec_service)) url = reverse( 'horizon:project:security_services:security_service_detail', args=[sec_service.id]) res = self.client.get(url) self.assertContains(res, "

Security Service Details: %s

" % sec_service.name, 1, 200) self.assertContains(res, "
%s
" % sec_service.name, 1, 200) self.assertContains(res, "
%s
" % sec_service.id, 1, 200) self.assertContains(res, "
%s
" % sec_service.user, 1, 200) self.assertContains(res, "
%s
" % sec_service.server, 1, 200) self.assertContains(res, "
%s
" % sec_service.dns_ip, 1, 200) self.assertContains(res, "
%s
" % sec_service.domain, 1, 200) self.assertNoMessages() api_manila.security_service_get.assert_called_once_with( mock.ANY, sec_service.id) def test_detail_view_with_exception(self): url = reverse( 'horizon:project:security_services:security_service_detail', args=[test_data.sec_service.id]) self.mock_object( api_manila, "security_service_get", mock.Mock(side_effect=horizon_exceptions.NotFound(404))) res = self.client.get(url) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.security_service_get.assert_called_once_with( mock.ANY, test_data.sec_service.id) def test_update_security_service_get(self): sec_service = test_data.sec_service url = reverse( 'horizon:project:security_services:security_service_update', args=[sec_service.id]) self.mock_object( api_manila, "security_service_get", mock.Mock(return_value=sec_service)) self.mock_object( api.neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.get(url) self.assertNoMessages() self.assertTemplateUsed( res, 'project/security_services/update.html') api_manila.security_service_get.assert_called_once_with( mock.ANY, sec_service.id) def test_update_security_service_post(self): sec_service = test_data.sec_service url = reverse( 'horizon:project:security_services:security_service_update', args=[sec_service.id]) formData = { 'method': 'UpdateForm', 'name': sec_service.name, 'description': sec_service.description, } self.mock_object(api_manila, "security_service_update") self.mock_object( api_manila, "security_service_get", mock.Mock(return_value=sec_service)) res = self.client.post(url, formData) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.security_service_get.assert_called_once_with( mock.ANY, sec_service.id) api_manila.security_service_update.assert_called_once_with( mock.ANY, sec_service.id, name=formData['name'], description=formData['description']) manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_group_snapshots/000077500000000000000000000000001323215354300267525ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_group_snapshots/__init__.py000066400000000000000000000000001323215354300310510ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_group_snapshots/tests.py000066400000000000000000000271361323215354300304770ustar00rootroot00000000000000# Copyright (c) 2017 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 django.core.urlresolvers import reverse import mock from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:project:share_group_snapshots:index') @ddt.ddt class ShareGroupSnapshotTests(test.TestCase): def setUp(self): super(self.__class__, self).setUp() self.sg = test_data.share_group self.sg_nl = test_data.share_group_nameless self.sg_dhss_true = test_data.share_group_dhss_true self.sgs = test_data.share_group_snapshot self.sgs_nl = test_data.share_group_snapshot_nameless def test_share_group_snapshots_list_get(self): share_groups = [self.sg, self.sg_nl, self.sg_dhss_true] sgss = [self.sgs, self.sgs_nl] self.mock_object( api_manila, 'share_group_snapshot_list', mock.Mock(return_value=sgss)) self.mock_object( api_manila, 'share_group_list', mock.Mock(return_value=share_groups)) res = self.client.get(INDEX_URL) self.assertStatusCode(res, 200) self.assertMessageCount(error=0) self.assertNoMessages() api_manila.share_group_snapshot_list.assert_called_once_with( mock.ANY, search_opts={'all_tenants': True}) api_manila.share_group_list.assert_called_once_with(mock.ANY) self.assertTemplateUsed( res, 'project/share_group_snapshots/index.html') self.assertContains(res, "

Share Group Snapshots

") self.assertContains( res, 'Delete Share Group Snapshot', len(sgss)) self.assertContains(res, 'Delete Share Group Snapshots', 1) for sgs in sgss: self.assertContains( res, 'value="share_group_snapshots__delete__%s' % sgs.id, 1) self.assertContains( res, '%(name)s-' % self.sgs_nl.id, 1) def test_share_group_snapshots_list_error_get(self): self.mock_object( api_manila, 'share_group_snapshot_list', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(INDEX_URL) self.assertStatusCode(res, 200) self.assertTemplateUsed( res, 'project/share_group_snapshots/index.html') self.assertContains(res, "

Share Group Snapshots

") self.assertContains(res, 'Delete Share Group Snapshot', 0) self.assertContains(res, 'Delete Share Group Snapshots', 0) self.assertNoMessages() @ddt.data( test_data.share_group_snapshot, test_data.share_group_snapshot_nameless, ) def test_share_group_snapshot_detailed_page_get(self, sgs): sg = test_data.share_group_nameless url = reverse( 'horizon:project:share_group_snapshots:detail', args=[sgs.id]) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(return_value=sgs)) self.mock_object( api_manila, 'share_group_get', mock.Mock(return_value=sg)) res = self.client.get(url) self.assertTemplateUsed( res, 'project/share_group_snapshots/detail.html') self.assertStatusCode(res, 200) api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, sgs.id) api_manila.share_group_get.assert_called_once_with( mock.ANY, sgs.share_group_id) def test_share_group_snapshot_detailed_page_error_get(self): url = reverse( 'horizon:project:share_group_snapshots:detail', args=[self.sgs.id]) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(url) self.assertTemplateNotUsed( res, 'admin/share_group_snapshots/detail.html') self.assertStatusCode(res, 302) self.assertMessageCount(error=1) self.assertMessageCount(success=0) @ddt.data( lambda *args, **kwargs: test_data.share_group, type('CustomExc', (Exception, ), {}), ) def test_share_group_snapshot_create_get(self, sg_get_side_effect): url = reverse( 'horizon:project:share_group_snapshots:create', args=[self.sg.id]) self.mock_object( api_manila, 'share_group_get', mock.Mock(side_effect=sg_get_side_effect)) res = self.client.get(url) self.assertTemplateUsed( res, 'project/share_group_snapshots/create.html') self.assertStatusCode(res, 200) self.assertNoMessages() api_manila.share_group_get.assert_called_once_with( mock.ANY, self.sg.id) self.assertMessageCount(error=0) def test_share_group_snapshot_create_post(self): url = reverse( 'horizon:project:share_group_snapshots:create', args=[self.sg.id]) form_data = { 'method': 'CreateShareGroupSnapshotForm', 'name': 'fake_SG_snapshot_name', 'description': 'fake SG snapshot description', 'share_group_id': self.sg.id, } self.mock_object( api_manila, "share_group_snapshot_create", mock.Mock(return_value=self.sgs)) res = self.client.post(url, form_data) self.assertTemplateNotUsed( res, 'project/share_group_snapshots/create.html') self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) self.assertMessageCount(error=0) self.assertMessageCount(success=1) api_manila.share_group_snapshot_create.assert_called_once_with( mock.ANY, self.sg.id, form_data['name'], form_data['description']) def test_share_group_snapshot_create_error_post(self): url = reverse( 'horizon:project:share_group_snapshots:create', args=[self.sg.id]) form_data = { 'method': 'CreateShareGroupSnapshotForm', 'name': 'fake_SG_snapshot_name', 'description': 'fake SG snapshot description', 'share_group_id': self.sg.id, } self.mock_object( api_manila, "share_group_snapshot_create", mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.post(url, form_data) self.assertTemplateNotUsed( res, 'project/share_group_snapshots/create.html') self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) self.assertMessageCount(error=1) self.assertMessageCount(success=0) api_manila.share_group_snapshot_create.assert_called_once_with( mock.ANY, self.sg.id, form_data['name'], form_data['description']) def test_share_group_snapshot_update_get(self): url = reverse( 'horizon:project:share_group_snapshots:update', args=[self.sgs.id]) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(return_value=self.sgs)) res = self.client.get(url) self.assertTemplateUsed( res, 'project/share_group_snapshots/update.html') self.assertStatusCode(res, 200) self.assertNoMessages() api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, self.sgs.id) def test_share_group_snapshot_update_error_get(self): url = reverse( 'horizon:project:share_group_snapshots:update', args=[self.sgs.id]) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(url) self.assertTemplateNotUsed( res, 'project/share_group_snapshots/update.html') self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) self.assertMessageCount(error=1) api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, self.sgs.id) def test_share_group_snapshot_update_post(self): self.mock_object(api_manila, "share_group_snapshot_update") self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(return_value=self.sgs)) form_data = { 'method': 'UpdateShareGroupSnapshotForm', 'name': self.sgs.name, 'description': self.sgs.description, } url = reverse( 'horizon:project:share_group_snapshots:update', args=[self.sgs.id]) res = self.client.post(url, form_data) self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_group_snapshot_update.assert_called_once_with( mock.ANY, self.sgs.id, form_data['name'], form_data['description']) api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, self.sgs.id) self.assertMessageCount(error=0) self.assertMessageCount(success=1) def test_share_group_snapshot_update_error_post(self): self.mock_object( api_manila, "share_group_snapshot_update", mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) self.mock_object( api_manila, 'share_group_snapshot_get', mock.Mock(return_value=self.sgs)) form_data = { 'method': 'UpdateShareGroupSnapshotForm', 'name': self.sgs.name, 'description': self.sgs.description, } url = reverse( 'horizon:project:share_group_snapshots:update', args=[self.sgs.id]) res = self.client.post(url, form_data) self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_group_snapshot_update.assert_called_once_with( mock.ANY, self.sgs.id, form_data['name'], form_data['description']) api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, self.sgs.id) self.assertMessageCount(error=1) self.assertMessageCount(success=0) def test_share_group_snapshot_delete_post(self): data = {'action': 'share_group_snapshots__delete__%s' % self.sgs.id} self.mock_object(api_manila, "share_group_snapshot_delete") self.mock_object( api_manila, "share_group_snapshot_list", mock.Mock(return_value=[self.sgs])) res = self.client.post(INDEX_URL, data) self.assertStatusCode(res, 302) self.assertMessageCount(success=1) api_manila.share_group_snapshot_delete.assert_called_once_with( mock.ANY, self.sgs.id) api_manila.share_group_snapshot_list.assert_called_once_with( mock.ANY, search_opts={'all_tenants': True}) self.assertRedirectsNoFollow(res, INDEX_URL) manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_groups/000077500000000000000000000000001323215354300250335ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_groups/__init__.py000066400000000000000000000000001323215354300271320ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_groups/tests.py000066400000000000000000000366721323215354300265650ustar00rootroot00000000000000# Copyright (c) 2017 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 django.core.urlresolvers import reverse import mock from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:project:share_groups:index') @ddt.ddt class ShareGroupTests(test.TestCase): def setUp(self): super(self.__class__, self).setUp() self.sg = test_data.share_group self.sg_nl = test_data.share_group_nameless self.sg_dhss_true = test_data.share_group_dhss_true def test_share_groups_list_get(self): sgs = [self.sg, self.sg_nl, self.sg_dhss_true] self.mock_object( api_manila, 'share_group_list', mock.Mock(return_value=sgs)) res = self.client.get(INDEX_URL) self.assertStatusCode(res, 200) api_manila.share_group_list.assert_called_once_with( mock.ANY, detailed=True) self.assertTemplateUsed(res, 'project/share_groups/index.html') self.assertContains(res, "

Share Groups

") self.assertContains(res, 'Delete Share Group', len(sgs)) self.assertContains(res, 'Delete Share Groups', 1) for sg in sgs: self.assertContains( res, 'value="share_groups__delete__%s' % sg.id, 1) self.assertContains( res, '%(name)s' % { 'id': sg.id, 'name': sg.name}, 1) self.assertContains( res, '-' % self.sg_nl.id, 1) self.assertNoMessages() def test_share_group_list_error_get(self): self.mock_object( api_manila, 'share_group_list', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(INDEX_URL) self.assertStatusCode(res, 200) self.assertTemplateUsed(res, 'project/share_groups/index.html') self.assertContains(res, "

Share Groups

") self.assertContains(res, 'Delete Share Group', 0) self.assertContains(res, 'Delete Share Groups', 0) self.assertNoMessages() @ddt.data( test_data.share_group_nameless, test_data.share_group_dhss_true, ) def test_share_group_detailed_page_get(self, sg): url = reverse('horizon:project:share_groups:detail', args=[sg.id]) shares = [test_data.share, test_data.nameless_share] self.mock_object( api_manila, 'share_group_get', mock.Mock(return_value=sg)) self.mock_object( api_manila, 'share_list', mock.Mock(return_value=shares)) self.mock_object( api_manila, 'share_type_list', mock.Mock(return_value=[ test_data.share_type, test_data.share_type_dhss_true])) res = self.client.get(url) self.assertTemplateUsed(res, 'project/share_groups/detail.html') self.assertStatusCode(res, 200) for share in shares: data = {'id': share.id, 'name': share.name or share.id} self.assertContains( res, '%(name)s' % data) def test_share_group_detailed_page_error_get(self): url = reverse('horizon:project:share_groups:detail', args=[self.sg.id]) self.mock_object( api_manila, 'share_group_get', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(url) self.assertTemplateNotUsed(res, 'project/share_groups/detail.html') self.assertStatusCode(res, 302) self.assertMessageCount(error=1) self.assertMessageCount(success=0) def test_share_group_update_get(self): url = reverse('horizon:project:share_groups:update', args=[self.sg.id]) self.mock_object( api_manila, 'share_group_get', mock.Mock(return_value=self.sg)) res = self.client.get(url) self.assertTemplateUsed(res, 'project/share_groups/update.html') self.assertStatusCode(res, 200) self.assertNoMessages() api_manila.share_group_get.assert_called_once_with( mock.ANY, self.sg.id) def test_share_group_update_error_get(self): url = reverse('horizon:project:share_groups:update', args=[self.sg.id]) self.mock_object( api_manila, 'share_group_get', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) res = self.client.get(url) self.assertTemplateNotUsed(res, 'project/share_groups/update.html') self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) self.assertMessageCount(error=1) api_manila.share_group_get.assert_called_once_with( mock.ANY, self.sg.id) def test_share_group_update_post(self): self.mock_object(api_manila, "share_group_update") self.mock_object( api_manila, 'share_group_get', mock.Mock(return_value=self.sg)) form_data = { 'method': 'UpdateShareGroupForm', 'name': self.sg.name, 'description': self.sg.description, } url = reverse('horizon:project:share_groups:update', args=[self.sg.id]) res = self.client.post(url, form_data) self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_group_update.assert_called_once_with( mock.ANY, self.sg.id, form_data['name'], form_data['description']) api_manila.share_group_get.assert_called_once_with( mock.ANY, self.sg.id) self.assertMessageCount(error=0) self.assertMessageCount(success=1) def test_share_group_update_error_post(self): self.mock_object( api_manila, 'share_group_update', mock.Mock(side_effect=type('CustomExc', (Exception, ), {}))) self.mock_object( api_manila, 'share_group_get', mock.Mock(return_value=self.sg)) form_data = { 'method': 'UpdateShareGroupForm', 'name': self.sg.name, 'description': self.sg.description, } url = reverse('horizon:project:share_groups:update', args=[self.sg.id]) res = self.client.post(url, form_data) self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_group_update.assert_called_once_with( mock.ANY, self.sg.id, form_data['name'], form_data['description']) api_manila.share_group_get.assert_called_once_with( mock.ANY, self.sg.id) self.assertMessageCount(error=1) self.assertMessageCount(success=0) def test_share_group_delete_post(self): sg = test_data.share_group_dhss_true data = {'action': 'share_groups__delete__%s' % sg.id} self.mock_object(api_manila, "share_group_delete") self.mock_object( api_manila, "share_group_list", mock.Mock(return_value=[sg])) res = self.client.post(INDEX_URL, data) self.assertStatusCode(res, 302) self.assertMessageCount(success=1) api_manila.share_group_delete.assert_called_once_with(mock.ANY, sg.id) api_manila.share_group_list.assert_called_once_with( mock.ANY, detailed=True) self.assertRedirectsNoFollow(res, INDEX_URL) def test_share_group_create_get(self): url = reverse('horizon:project:share_groups:create') self.mock_object( api_manila, 'share_group_type_list', mock.Mock(return_value=[ test_data.share_group_type, test_data.share_group_type_private, test_data.share_group_type_dhss_true, ])) self.mock_object( api_manila, 'share_group_snapshot_list', mock.Mock(return_value=[ test_data.share_group_snapshot, test_data.share_group_snapshot_nameless, ])) self.mock_object( api_manila, 'share_network_list', mock.Mock(return_value=[ test_data.inactive_share_network, test_data.active_share_network, ])) self.mock_object( api_manila, 'share_type_list', mock.Mock(return_value=[ test_data.share_type, test_data.share_type_private, test_data.share_type_dhss_true, ])) self.mock_object( api_manila, 'availability_zone_list', mock.Mock(return_value=[])) res = self.client.get(url) self.assertTemplateUsed(res, 'project/share_groups/create.html') self.assertStatusCode(res, 200) self.assertNoMessages() self.assertMessageCount(error=0) api_manila.share_group_type_list.assert_called_once_with(mock.ANY) api_manila.share_group_snapshot_list.assert_called_once_with(mock.ANY) api_manila.share_network_list.assert_called_once_with(mock.ANY) api_manila.share_type_list.assert_called_once_with(mock.ANY) api_manila.availability_zone_list.assert_called_once_with(mock.ANY) def test_share_group_create_post(self): url = reverse('horizon:project:share_groups:create') form_data = { 'method': 'CreateShareGroupForm', 'name': 'fake_sg_name', 'description': 'fake SG description', 'sgt': test_data.share_group_type.id, 'share-type-choices-%s' % test_data.share_group_type.id: ( test_data.share_group_type.share_types[0]), 'availability_zone': '', 'share_network': test_data.inactive_share_network.id, 'snapshot': '', } self.mock_object( api_manila, "share_group_create", mock.Mock(return_value=self.sg)) self.mock_object( api_manila, 'share_group_type_list', mock.Mock(return_value=[ test_data.share_group_type, test_data.share_group_type_private, test_data.share_group_type_dhss_true, ])) self.mock_object( api_manila, 'share_group_snapshot_list', mock.Mock(return_value=[ test_data.share_group_snapshot, test_data.share_group_snapshot_nameless, ])) self.mock_object( api_manila, 'share_network_list', mock.Mock(return_value=[ test_data.inactive_share_network, test_data.active_share_network, ])) self.mock_object( api_manila, 'share_type_list', mock.Mock(return_value=[ test_data.share_type, test_data.share_type_private, test_data.share_type_dhss_true, ])) self.mock_object( api_manila, 'availability_zone_list', mock.Mock(return_value=[])) res = self.client.post(url, form_data) self.assertTemplateNotUsed(res, 'project/share_groups/create.html') self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_group_type_list.assert_called_once_with(mock.ANY) api_manila.share_group_snapshot_list.assert_called_once_with(mock.ANY) api_manila.share_network_list.assert_called_once_with(mock.ANY) api_manila.share_type_list.assert_called_once_with(mock.ANY) api_manila.availability_zone_list.assert_called_once_with(mock.ANY) api_manila.share_group_create.assert_called_once_with( mock.ANY, name=form_data['name'], description=form_data['description'], share_group_type=test_data.share_group_type.id, share_types=[test_data.share_type.id], share_network=form_data['share_network'], source_share_group_snapshot=None, availability_zone=form_data['availability_zone']) def test_share_group_create_from_snapshot_post(self): url = reverse('horizon:project:share_groups:create') form_data = { 'method': 'CreateShareGroupForm', 'name': 'fake_sg_name', 'description': 'fake SG description', 'sgt': '', 'snapshot': test_data.share_group_snapshot.id, } self.mock_object( api_manila, "share_group_snapshot_get", mock.Mock(return_value=test_data.share_group_snapshot)) self.mock_object( api_manila, "share_group_get", mock.Mock(return_value=self.sg_nl)) self.mock_object( api_manila, "share_group_create", mock.Mock(return_value=self.sg)) self.mock_object( api_manila, 'share_group_type_list', mock.Mock(return_value=[ test_data.share_group_type, test_data.share_group_type_private, test_data.share_group_type_dhss_true, ])) self.mock_object( api_manila, 'share_group_snapshot_list', mock.Mock(return_value=[ test_data.share_group_snapshot, test_data.share_group_snapshot_nameless, ])) self.mock_object( api_manila, 'share_network_list', mock.Mock(return_value=[ test_data.inactive_share_network, test_data.active_share_network, ])) self.mock_object( api_manila, 'share_type_list', mock.Mock(return_value=[ test_data.share_type, test_data.share_type_private, test_data.share_type_dhss_true, ])) self.mock_object( api_manila, 'availability_zone_list', mock.Mock(return_value=[])) res = self.client.post(url, form_data) self.assertTemplateNotUsed(res, 'project/share_groups/create.html') self.assertStatusCode(res, 302) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_group_snapshot_list.assert_not_called() api_manila.share_group_type_list.assert_not_called() api_manila.share_network_list.assert_not_called() api_manila.share_type_list.assert_not_called() api_manila.availability_zone_list.assert_not_called() api_manila.share_group_snapshot_get.assert_called_once_with( mock.ANY, test_data.share_group_snapshot.id) api_manila.share_group_create.assert_called_once_with( mock.ANY, name=form_data['name'], description=form_data['description'], share_group_type=test_data.share_group_type.id, share_types=None, share_network=None, source_share_group_snapshot=test_data.share_group_snapshot.id, availability_zone=None) manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_networks/000077500000000000000000000000001323215354300253705ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_networks/__init__.py000066400000000000000000000000001323215354300274670ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_networks/tests.py000066400000000000000000000231611323215354300271070ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # # 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 django.core.urlresolvers import reverse import mock from neutronclient.client import exceptions from openstack_auth import policy from openstack_dashboard import api from manila_ui.api import manila as api_manila from manila_ui.api import network as api_manila_network from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:project:share_networks:index') class ShareNetworksViewTests(test.TestCase): def test_create_share_network(self): share_net = test_data.active_share_network url = reverse('horizon:project:share_networks:share_network_create') neutron_net_id = self.networks.first().id formData = { 'name': 'new_share_network', 'description': 'This is test share network', 'method': 'CreateForm', 'neutron_net_id': neutron_net_id, } for net in self.networks.list(): formData['subnet-choices-%s' % net.id] = net.subnets[0].id self.mock_object( api.neutron, "subnet_list", mock.Mock(return_value=self.subnets.list())) self.mock_object( api_manila_network, "network_list", mock.Mock(return_value=self.networks.list())) self.mock_object( api_manila, "share_network_create", mock.Mock(return_value=share_net)) self.client.post(url, formData) api_manila.share_network_create.assert_called_with( mock.ANY, name=formData['name'], neutron_net_id=neutron_net_id, neutron_subnet_id=formData['subnet-choices-%s' % neutron_net_id], description=formData['description']) api_manila_network.network_list.assert_called_once_with(mock.ANY) api.neutron.subnet_list.assert_has_calls([ mock.call(mock.ANY, network_id=network.id) for network in self.networks.list() ], any_order=True) def test_delete_share_network(self): share_network = test_data.inactive_share_network formData = {'action': 'share_networks__delete__%s' % share_network.id} self.mock_object(api_manila, "share_network_delete") self.mock_object( api_manila, "share_network_list", mock.Mock(return_value=[ test_data.active_share_network, share_network])) self.mock_object( api.neutron, "network_list", mock.Mock(return_value=self.networks.list())) self.mock_object( api.neutron, "subnet_list", mock.Mock(return_value=self.subnets.list())) res = self.client.post(INDEX_URL, formData) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_network_list.assert_called_once_with( mock.ANY, detailed=True) api_manila.share_network_delete.assert_called_once_with( mock.ANY, share_network.id) api.neutron.network_list.assert_called_once_with(mock.ANY) api.neutron.subnet_list.assert_called_once_with(mock.ANY) def test_detail_view(self): share_net = test_data.active_share_network sec_service = test_data.sec_service self.mock_object( api_manila, "share_server_list", mock.Mock(return_value=[])) self.mock_object( api_manila, "share_network_get", mock.Mock(return_value=share_net)) self.mock_object( api_manila, "share_network_security_service_list", mock.Mock(return_value=[sec_service])) network = self.networks.first() subnet = self.subnets.first() self.mock_object( api.neutron, "network_get", mock.Mock(return_value=network)) self.mock_object( api.neutron, "subnet_get", mock.Mock(return_value=subnet)) url = reverse('horizon:project:share_networks:share_network_detail', args=[share_net.id]) res = self.client.get(url) self.assertContains(res, "

Share Network Details: %s

" % share_net.name, 1, 200) self.assertContains(res, "
%s
" % share_net.name, 1, 200) self.assertContains(res, "
%s
" % share_net.id, 1, 200) self.assertContains(res, "
%s
" % network.name_or_id, 1, 200) self.assertContains(res, "
%s
" % subnet.name_or_id, 1, 200) self.assertContains(res, "%s" % (sec_service.id, sec_service.name), 1, 200) self.assertNoMessages() api_manila.share_network_security_service_list.assert_called_once_with( mock.ANY, share_net.id) api_manila.share_server_list.assert_called_once_with( mock.ANY, search_opts={'share_network_id': share_net.id}) api_manila.share_network_get.assert_called_once_with( mock.ANY, share_net.id) api.neutron.network_get.assert_called_once_with( mock.ANY, share_net.neutron_net_id) api.neutron.subnet_get.assert_called_once_with( mock.ANY, share_net.neutron_subnet_id) def test_detail_view_network_not_found(self): share_net = test_data.active_share_network sec_service = test_data.sec_service url = reverse('horizon:project:share_networks:share_network_detail', args=[share_net.id]) self.mock_object( api_manila, "share_server_list", mock.Mock(return_value=[])) self.mock_object( api_manila, "share_network_get", mock.Mock(return_value=share_net)) self.mock_object( api_manila, "share_network_security_service_list", mock.Mock(return_value=[sec_service])) self.mock_object( api.neutron, "network_get", mock.Mock( side_effect=exceptions.NeutronClientException('fake', 500))) self.mock_object( api.neutron, "subnet_get", mock.Mock( side_effect=exceptions.NeutronClientException('fake', 500))) res = self.client.get(url) self.assertContains(res, "

Share Network Details: %s

" % share_net.name, 1, 200) self.assertContains(res, "
%s
" % share_net.name, 1, 200) self.assertContains(res, "
%s
" % share_net.id, 1, 200) self.assertContains(res, "
Unknown
", 2, 200) self.assertNotContains(res, "
%s
" % share_net.neutron_net_id) self.assertNotContains(res, "
%s
" % share_net.neutron_subnet_id) self.assertContains(res, "%s" % (sec_service.id, sec_service.name), 1, 200) self.assertNoMessages() api_manila.share_network_security_service_list.assert_called_once_with( mock.ANY, share_net.id) api_manila.share_server_list.assert_called_once_with( mock.ANY, search_opts={'share_network_id': share_net.id}) api_manila.share_network_get.assert_called_once_with( mock.ANY, share_net.id) api.neutron.network_get.assert_called_once_with( mock.ANY, share_net.neutron_net_id) api.neutron.subnet_get.assert_called_once_with( mock.ANY, share_net.neutron_subnet_id) def test_update_share_network(self): share_net = test_data.inactive_share_network formData = { 'method': 'UpdateForm', 'name': share_net.name, 'description': share_net.description, } url = reverse('horizon:project:share_networks:share_network_update', args=[share_net.id]) self.mock_object(api_manila, "share_network_update") self.mock_object( api_manila, "share_network_get", mock.Mock(return_value=share_net)) self.mock_object( api_manila, "share_network_security_service_list", mock.Mock(return_value=[test_data.sec_service])) self.mock_object( api_manila, "security_service_list", mock.Mock(return_value=[test_data.sec_service])) self.mock_object( policy, 'check', mock.Mock(side_effect=(lambda *args, **kwargs: True))) res = self.client.post(url, formData) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_network_security_service_list.assert_called_once_with( mock.ANY, share_net.id) api_manila.security_service_list.assert_has_calls([ mock.call(mock.ANY), mock.call(mock.ANY, search_opts={'share_network_id': share_net.id}) ]) api_manila.share_network_get.assert_called_once_with( mock.ANY, share_net.id) api_manila.share_network_update.assert_called_once_with( mock.ANY, share_net.id, name=formData['name'], description=formData['description']) self.assertTrue(policy.check.called) manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_snapshots/000077500000000000000000000000001323215354300255365ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_snapshots/__init__.py000066400000000000000000000000001323215354300276350ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_snapshots/test_tables.py000066400000000000000000000043321323215354300304230ustar00rootroot00000000000000# Copyright (c) 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 django.core.handlers import wsgi import mock from manila_ui.dashboards.project.share_snapshots import tables from manila_ui.tests import helpers as base @ddt.ddt class CreateSnapshotTests(base.APITestCase): def setUp(self): super(self.__class__, self).setUp() FAKE_ENVIRON = {'REQUEST_METHOD': 'GET', 'wsgi.input': 'fake_input'} self.request = wsgi.WSGIRequest(FAKE_ENVIRON) self.create_snapshot = tables.CreateShareSnapshot() def _get_fake_share(self, **kwargs): if 'status' not in kwargs.keys(): kwargs.update({'status': 'available'}) return type("Share", (object, ), kwargs)() @ddt.data(True, False) @mock.patch('openstack_dashboard.usage.quotas.tenant_quota_usages') def test_allowed_with_snapshot_support_attr(self, snapshot_support, mock_quota_usages): mock_quota_usages.return_value = {'snapshots': {'available': 1}} share = self._get_fake_share(snapshot_support=snapshot_support) result = self.create_snapshot.allowed(self.request, share) self.assertEqual(snapshot_support, result) mock_quota_usages.assert_called_once_with(self.request) @mock.patch('openstack_dashboard.usage.quotas.tenant_quota_usages') def test_allowed_no_snapshot_support_attr(self, mock_quota_usages): mock_quota_usages.return_value = {'snapshots': {'available': 1}} share = self._get_fake_share() result = self.create_snapshot.allowed(self.request, share) self.assertTrue(result) mock_quota_usages.assert_called_once_with(self.request) manila-ui-2.13.0/manila_ui/tests/dashboards/project/share_snapshots/tests.py000066400000000000000000000315641323215354300272630ustar00rootroot00000000000000# Copyright 2014 NetApp, Inc. # # 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 django.core.urlresolvers import reverse import mock from openstack_dashboard.api import neutron from openstack_dashboard.usage import quotas from manila_ui.api import manila as api_manila from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:project:share_snapshots:index') @ddt.ddt class SnapshotSnapshotViewTests(test.TestCase): def test_create_snapshot_get(self): share = test_data.share usage_limit = { 'maxTotalShareGigabytes': 250, 'totalShareGigabytesUsed': 20, } url = reverse('horizon:project:share_snapshots:share_snapshot_create', args=[share.id]) self.mock_object( quotas, "tenant_limit_usages", mock.Mock(return_value=usage_limit)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.get(url) self.assertNoMessages() self.assertTemplateUsed(res, 'project/share_snapshots/create.html') def test_create_snapshot_post(self): share = test_data.share snapshot = test_data.snapshot url = reverse('horizon:project:share_snapshots:share_snapshot_create', args=[share.id]) formData = { 'name': 'new_snapshot', 'description': 'This is test snapshot', 'method': 'CreateForm', 'size': 1, 'type': 'NFS', 'share_id': share.id, } self.mock_object( api_manila, "share_snapshot_create", mock.Mock(return_value=snapshot)) res = self.client.post(url, formData) api_manila.share_snapshot_create.assert_called_once_with( mock.ANY, share.id, formData['name'], formData['description']) self.assertRedirectsNoFollow(res, INDEX_URL) def test_delete_snapshot(self): share = test_data.share snapshot = test_data.snapshot formData = {'action': 'share_snapshots__delete__%s' % snapshot.id} self.mock_object(api_manila, "share_snapshot_delete") self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=[snapshot])) self.mock_object( api_manila, "share_list", mock.Mock(return_value=[share])) res = self.client.post(INDEX_URL, formData) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_snapshot_list.assert_called_once_with(mock.ANY) api_manila.share_list.assert_called_once_with(mock.ANY) api_manila.share_snapshot_delete.assert_called_once_with( mock.ANY, test_data.snapshot.id) def test_detail_view(self): snapshot = test_data.snapshot share = test_data.share url = reverse('horizon:project:share_snapshots:share_snapshot_detail', args=[snapshot.id]) self.mock_object( api_manila, "share_snapshot_get", mock.Mock(return_value=snapshot)) self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) res = self.client.get(url) self.assertContains(res, "

Snapshot Details: %s

" % snapshot.name, 1, 200) self.assertContains(res, "
%s
" % snapshot.name, 1, 200) self.assertContains(res, "
%s
" % snapshot.id, 1, 200) self.assertContains(res, "
%s
" % (snapshot.share_id, share.name), 1, 200) self.assertContains(res, "
%s GiB
" % snapshot.size, 1, 200) self.assertNoMessages() api_manila.share_get.assert_called_once_with(mock.ANY, share.id) api_manila.share_snapshot_get.assert_called_once_with( mock.ANY, snapshot.id) def test_detail_view_with_mount_support(self): snapshot = test_data.snapshot_mount_support share = test_data.share_mount_snapshot rules = [test_data.ip_rule, test_data.user_rule, test_data.cephx_rule] export_locations = test_data.user_snapshot_export_locations url = reverse('horizon:project:share_snapshots:share_snapshot_detail', args=[snapshot.id]) self.mock_object( api_manila, "share_snapshot_get", mock.Mock(return_value=snapshot)) self.mock_object( api_manila, "share_snapshot_rules_list", mock.Mock( return_value=rules)) self.mock_object( api_manila, "share_snap_export_location_list", mock.Mock( return_value=export_locations)) self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) res = self.client.get(url) self.assertContains(res, "

Snapshot Details: %s

" % snapshot.name, 1, 200) self.assertContains(res, "
%s
" % snapshot.name, 1, 200) self.assertContains(res, "
%s
" % snapshot.id, 1, 200) self.assertContains(res, "
%s
" % (snapshot.share_id, share.name), 1, 200) self.assertContains(res, "
%s GiB
" % snapshot.size, 1, 200) for el in export_locations: self.assertContains(res, "value=\"%s\"" % el.path, 1, 200) for rule in rules: self.assertContains(res, "
%s
" % rule.access_type, 1, 200) self.assertContains( res, "
Access to: %s
" % rule.access_to, 1, 200) self.assertContains( res, "
Status: active
", len(rules), 200) self.assertNoMessages() api_manila.share_get.assert_called_once_with(mock.ANY, share.id) api_manila.share_snapshot_get.assert_called_once_with( mock.ANY, snapshot.id) api_manila.share_snapshot_rules_list.assert_called_once_with( mock.ANY, snapshot.id) api_manila.share_snap_export_location_list.assert_called_once_with( mock.ANY, snapshot) def test_update_snapshot_get(self): snapshot = test_data.snapshot url = reverse('horizon:project:share_snapshots:share_snapshot_edit', args=[snapshot.id]) self.mock_object( api_manila, "share_snapshot_get", mock.Mock(return_value=snapshot)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.get(url) api_manila.share_snapshot_get.assert_called_once_with( mock.ANY, snapshot.id) self.assertNoMessages() self.assertTemplateUsed(res, 'project/share_snapshots/update.html') def test_update_snapshot_post(self): snapshot = test_data.snapshot url = reverse('horizon:project:share_snapshots:share_snapshot_edit', args=[snapshot.id]) formData = { 'method': 'UpdateForm', 'name': snapshot.name, 'description': snapshot.description, } self.mock_object(api_manila, "share_snapshot_update") self.mock_object(api_manila, "share_snapshot_get", mock.Mock(return_value=snapshot)) res = self.client.post(url, formData) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_snapshot_get.assert_called_once_with( mock.ANY, snapshot.id) api_manila.share_snapshot_update.assert_called_once_with( mock.ANY, snapshot.id, formData['name'], formData['description']) def test_list_rules(self): snapshot = test_data.snapshot rules = [test_data.ip_rule, test_data.user_rule, test_data.cephx_rule] self.mock_object( api_manila, "share_snapshot_get", mock.Mock( return_value=snapshot)) self.mock_object( api_manila, "share_snapshot_rules_list", mock.Mock( return_value=rules)) url = reverse( 'horizon:project:share_snapshots:share_snapshot_manage_rules', args=[snapshot.id]) res = self.client.get(url) self.assertEqual(res.status_code, 200) self.assertTemplateUsed( res, 'project/share_snapshots/manage_rules.html') api_manila.share_snapshot_rules_list.assert_called_once_with( mock.ANY, snapshot.id) def test_list_rules_exception(self): snapshot = test_data.snapshot self.mock_object( api_manila, "share_snapshot_get", mock.Mock( return_value=snapshot)) self.mock_object( api_manila, "share_snapshot_rules_list", mock.Mock(side_effect=Exception('fake'))) url = reverse( 'horizon:project:share_snapshots:share_snapshot_manage_rules', args=[snapshot.id]) res = self.client.get(url) self.assertEqual(res.status_code, 302) self.assertTemplateNotUsed( res, 'project/share_snapshots/manage_rules.html') api_manila.share_snapshot_rules_list.assert_called_once_with( mock.ANY, snapshot.id) def test_create_rule_get(self): snapshot = test_data.snapshot url = reverse( 'horizon:project:share_snapshots:share_snapshot_rule_add', args=[snapshot.id]) self.mock_object( api_manila, "share_snapshot_get", mock.Mock( return_value=snapshot)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.get(url) self.assertNoMessages() self.assertTemplateUsed(res, 'project/share_snapshots/rule_add.html') def test_create_rule_get_exception(self): snapshot = test_data.snapshot url = reverse( 'horizon:project:share_snapshots:share_snapshot_rule_add', args=[snapshot.id]) self.mock_object( api_manila, "share_snapshot_get", mock.Mock( side_effect=Exception('fake'))) res = self.client.get(url) self.assertEqual(res.status_code, 302) self.assertTemplateNotUsed( res, 'project/share_snapshots/rule_add.html') @ddt.data(None, Exception('fake')) def test_create_rule_post(self, exc): snapshot = test_data.snapshot self.mock_object( api_manila, "share_snapshot_get", mock.Mock(return_value=snapshot)) url = reverse( 'horizon:project:share_snapshots:share_snapshot_rule_add', args=[snapshot.id]) self.mock_object( api_manila, "share_snapshot_allow", mock.Mock(side_effect=exc)) formData = { 'access_type': 'user', 'method': u'CreateForm', 'access_to': 'someuser', } res = self.client.post(url, formData) self.assertEqual(res.status_code, 302) api_manila.share_snapshot_allow.assert_called_once_with( mock.ANY, snapshot.id, access_type=formData['access_type'], access_to=formData['access_to']) self.assertRedirectsNoFollow( res, reverse( 'horizon:project:share_snapshots:share_snapshot_manage_rules', args=[snapshot.id]) ) @ddt.data(None, Exception('fake')) def test_delete_rule(self, exc): snapshot = test_data.snapshot rule = test_data.ip_rule formData = {'action': 'rules__delete__%s' % rule.id} self.mock_object( api_manila, "share_snapshot_get", mock.Mock( return_value=snapshot)) self.mock_object(api_manila, "share_snapshot_deny", mock.Mock(side_effect=exc)) self.mock_object( api_manila, "share_snapshot_rules_list", mock.Mock( return_value=[rule])) url = reverse( 'horizon:project:share_snapshots:share_snapshot_manage_rules', args=[snapshot.id]) res = self.client.post(url, formData) self.assertEqual(res.status_code, 302) api_manila.share_snapshot_deny.assert_called_with( mock.ANY, snapshot.id, rule.id) api_manila.share_snapshot_rules_list.assert_called_with( mock.ANY, snapshot.id) manila-ui-2.13.0/manila_ui/tests/dashboards/project/shares/000077500000000000000000000000001323215354300236175ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/shares/__init__.py000066400000000000000000000000001323215354300257160ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/shares/replicas/000077500000000000000000000000001323215354300254215ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/shares/replicas/__init__.py000066400000000000000000000000001323215354300275200ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/dashboards/project/shares/replicas/tests.py000066400000000000000000000312301323215354300271340ustar00rootroot00000000000000# Copyright (c) 2016 Mirantis, Inc. # # 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 import ddt from django.core.urlresolvers import reverse import mock from openstack_dashboard.api import neutron from manila_ui.api import manila as api_manila from manila_ui.dashboards.project.shares.replicas import tables as r_tables from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:project:shares:index') class FakeAZ(object): def __init__(self, name): self.name = name @ddt.ddt class ReplicasTests(test.TestCase): def setUp(self): super(self.__class__, self).setUp() self.share = test_data.share self.share_replica = test_data.share_replica self.share_replica2 = test_data.share_replica2 self.mock_object( api_manila, "share_get", mock.Mock(return_value=self.share)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) def test_create_get(self): url = reverse( "horizon:project:shares:create_replica", args=[self.share.id]) old_az = self.share.availability_zone new_az = old_az + "_new" self.mock_object(api_manila, "share_replica_create") self.mock_object( api_manila, "availability_zone_list", mock.Mock(return_value=[FakeAZ(new_az), FakeAZ(old_az)])) res = self.client.get(url) self.assertEqual(200, res.status_code) self.assertFalse(api_manila.share_replica_create.called) api_manila.availability_zone_list.assert_called_once_with(mock.ANY) self.assertNoMessages() self.assertTemplateUsed( res, "project/shares/replicas/create_replica.html") def _create_post(self): url = reverse( "horizon:project:shares:create_replica", args=[self.share.id]) old_az = self.share.availability_zone new_az = old_az + "_new" formData = { "share_id": self.share.id, "availability_zone": new_az, } self.mock_object( api_manila, "availability_zone_list", mock.Mock(return_value=[FakeAZ(new_az), FakeAZ(old_az)])) self.mock_object( api_manila, "share_replica_create", mock.Mock(return_value=test_data.share_replica)) res = self.client.post(url, formData) self.assertEqual(302, res.status_code) api_manila.share_replica_create.assert_called_once_with( mock.ANY, self.share.id, formData["availability_zone"]) api_manila.share_replica_create.assert_called_once_with( mock.ANY, formData["share_id"], formData["availability_zone"]) api_manila.availability_zone_list.assert_called_once_with(mock.ANY) self.assertRedirectsNoFollow( res, reverse("horizon:project:shares:manage_replicas", args=[self.share.id])) def test_create_post(self): self.mock_object(api_manila, "share_replica_create") self._create_post() def test_create_post_error(self): self.mock_object( api_manila, "share_replica_create", mock.Mock(side_effect=Exception("Fake exception"))) self._create_post() def test_detail(self): url = reverse( "horizon:project:shares:replica_detail", args=[self.share_replica.id]) export_locations = test_data.export_locations self.mock_object( api_manila, "share_replica_get", mock.Mock(return_value=self.share_replica)) self.mock_object( api_manila, "share_instance_export_location_list", mock.Mock(return_value=export_locations)) res = self.client.get(url) self.assertEqual(200, res.status_code) self.assertTemplateUsed(res, "project/shares/replicas/detail.html") self.assertNoMessages() self.assertContains(res, "

Share Replica Overview", 1, 200) self.assertContains(res, ">%s" % self.share.id, 1, 200) self.assertContains(res, "
%s
" % self.share_replica.id, 1, 200) self.assertContains( res, "
%s
" % self.share.availability_zone, 1, 200) for el in export_locations: self.assertContains(res, "value=\"%s\"" % el.path, 1, 200) self.assertContains( res, "
Preferred: %s
" % el.preferred, 1, 200) self.assertContains( res, "
Is admin only: %s
" % el.is_admin_only, 1, 200) self.assertNoMessages() api_manila.share_replica_get.assert_called_once_with( mock.ANY, self.share_replica.id) api_manila.share_instance_export_location_list.assert_called_once_with( mock.ANY, self.share_replica.id) def test_detail_not_found(self): url = reverse("horizon:project:shares:replica_detail", args=[self.share_replica.id]) self.mock_object( api_manila, "share_replica_get", mock.Mock( side_effect=Exception("Fake replica NotFound exception"))) self.mock_object(api_manila, "share_instance_export_location_list") res = self.client.get(url) self.assertEqual(302, res.status_code) self.assertRedirectsNoFollow(res, INDEX_URL) self.assertTemplateNotUsed(res, "project/shares/replicas/detail.html") api_manila.share_replica_get.assert_called_once_with( mock.ANY, self.share_replica.id) self.assertFalse(api_manila.share_instance_export_location_list.called) def test_list(self): self.mock_object( api_manila, "share_replica_list", mock.Mock(return_value=[self.share_replica])) url = reverse( "horizon:project:shares:manage_replicas", args=[self.share.id]) res = self.client.get(url) self.assertEqual(200, res.status_code) self.assertTemplateUsed( res, "project/shares/replicas/manage_replicas.html") api_manila.share_get.assert_called_with(mock.ANY, self.share.id) api_manila.share_replica_list.assert_called_with( mock.ANY, self.share.id) def test_list_exception(self): self.mock_object( api_manila, "share_replica_list", mock.Mock(side_effect=Exception("Fake exception"))) url = reverse( "horizon:project:shares:manage_replicas", args=[self.share.id]) res = self.client.get(url) self.assertEqual(302, res.status_code) self.assertRedirectsNoFollow(res, INDEX_URL) self.assertTemplateNotUsed( res, "project/shares/replicas/manage_replicas.html") api_manila.share_replica_list.assert_called_with( mock.ANY, self.share.id) @ddt.data( ([test_data.share_replica], test_data.share_replica.id, None), ([test_data.share_replica], test_data.share_replica.id, 'dr'), ([test_data.share_replica], test_data.share_replica.id, 'readable'), ([test_data.share_replica], test_data.share_replica.id, 'writable'), ([test_data.share_replica, test_data.share_replica2], test_data.share_replica.id, 'dr'), ([test_data.share_replica, test_data.share_replica2], test_data.share_replica.id, 'readable'), ) @ddt.unpack def test_delete_not_allowed(self, replica_list, replica_id, replication_type): share = copy.copy(self.share) share.replication_type = replication_type formData = {"action": "replicas__delete__%s" % replica_id} self.mock_object(api_manila, "share_replica_delete") self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object( api_manila, "share_replica_list", mock.Mock(return_value=replica_list)) url = reverse( "horizon:project:shares:manage_replicas", args=[share.id]) res = self.client.post(url, formData) self.assertEqual(302, res.status_code) self.assertRedirectsNoFollow(res, url) api_manila.share_replica_list.assert_called_with(mock.ANY, share.id) self.assertFalse(api_manila.share_replica_delete.called) @ddt.data( ([test_data.share_replica, test_data.share_replica2], test_data.share_replica2.id, 'dr'), ([test_data.share_replica, test_data.share_replica2], test_data.share_replica2.id, 'readable'), ([test_data.share_replica, test_data.share_replica3], test_data.share_replica.id, 'writable'), ([test_data.share_replica, test_data.share_replica3], test_data.share_replica3.id, 'writable'), ) @ddt.unpack def test_delete_allowed(self, replica_list, replica_id, replication_type): share = copy.copy(self.share) share.replication_type = replication_type formData = {"action": "replicas__delete__%s" % replica_id} self.mock_object(api_manila, "share_replica_delete") self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object( api_manila, "share_replica_list", mock.Mock(return_value=replica_list)) url = reverse( "horizon:project:shares:manage_replicas", args=[share.id]) res = self.client.post(url, formData) self.assertEqual(302, res.status_code) self.assertRedirectsNoFollow(res, url) api_manila.share_replica_list.assert_called_with(mock.ANY, share.id) api_manila.share_replica_delete.assert_called_with( mock.ANY, replica_id) def test_set_as_active_get(self): url = reverse( "horizon:project:shares:set_replica_as_active", args=[self.share_replica.id]) self.mock_object(api_manila, "share_replica_get") self.mock_object(api_manila, "share_replica_promote") res = self.client.get(url) self.assertEqual(200, res.status_code) self.assertTemplateUsed( res, "project/shares/replicas/set_replica_as_active.html") self.assertFalse(api_manila.share_replica_get.called) self.assertFalse(api_manila.share_replica_promote.called) def _set_as_active_post(self): url = reverse( "horizon:project:shares:set_replica_as_active", args=[self.share_replica.id]) self.mock_object( api_manila, "share_replica_get", mock.Mock(return_value=self.share_replica)) formData = {"replica_id": self.share_replica.id} res = self.client.post(url, formData) self.assertEqual(302, res.status_code) self.assertTemplateNotUsed( res, "project/shares/replicas/set_replica_as_active.html") api_manila.share_replica_promote.assert_called_once_with( mock.ANY, self.share_replica) return res def test_set_as_active_post(self): self.mock_object(api_manila, "share_replica_promote") res = self._set_as_active_post() self.assertRedirectsNoFollow( res, reverse("horizon:project:shares:manage_replicas", args=[self.share.id])) def test_set_as_active_post_error(self): self.mock_object( api_manila, "share_replica_promote", mock.Mock(side_effect=Exception("Fake exception"))) res = self._set_as_active_post() self.assertRedirectsNoFollow( res, reverse("horizon:project:shares:index")) def test_replicas_table(self): replicas_table = r_tables.ReplicasTable(self.request) counter = 0 columns = ['created_at', 'updated_at'] for column in replicas_table.get_columns(): if column.name in columns: self.assertEqual(1, len(column.filters)) self.assertEqual( column.filters[0], r_tables.filters.parse_isotime) counter += 1 columns.remove(column.name) self.assertEqual( 2, counter, "The following columns are missing: %s." % ', '.join(columns)) manila-ui-2.13.0/manila_ui/tests/dashboards/project/shares/tests.py000066400000000000000000000747461323215354300253550ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # # 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 django.core.handlers import wsgi from django.core.urlresolvers import reverse from horizon import messages as horizon_messages import mock from openstack_dashboard.api import neutron from openstack_dashboard.usage import quotas import six from manila_ui.api import manila as api_manila from manila_ui.dashboards.project.shares import forms from manila_ui.dashboards import utils from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:project:shares:index') @ddt.ddt class ShareViewTests(test.APITestCase): class FakeAZ(object): def __init__(self, name): self.name = name def setUp(self): super(ShareViewTests, self).setUp() self.fake_share_type = mock.Mock() self.fake_share_type.name = 'fake' self.fake_share_type.id = 'fake_id' self.fake_share_type.get_keys = mock.Mock( return_value={'driver_handles_share_servers': 'True'}) self.share = test_data.share self.mock_object( api_manila, "share_group_list", mock.Mock(return_value=[])) self.mock_object( api_manila, "share_get", mock.Mock(return_value=self.share)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) self.mock_object(horizon_messages, "success") FAKE_ENVIRON = {'REQUEST_METHOD': 'GET', 'wsgi.input': 'fake_input'} self.request = wsgi.WSGIRequest(FAKE_ENVIRON) def test_index(self): snaps = [test_data.snapshot, test_data.snapshot_mount_support] shares = [test_data.share, test_data.nameless_share, test_data.other_share] share_networks = [test_data.inactive_share_network, test_data.active_share_network] self.mock_object( api_manila, "share_list", mock.Mock(return_value=shares)) self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=snaps)) self.mock_object( api_manila, "share_network_list", mock.Mock(return_value=share_networks)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) self.mock_object( quotas, "tenant_limit_usages", mock.Mock(return_value=test_data.quota_usage)) self.mock_object( quotas, "tenant_quota_usages", mock.Mock(return_value=test_data.quota_usage)) res = self.client.get(INDEX_URL) self.assertEqual(res.status_code, 200) self.assertTemplateUsed(res, 'project/shares/index.html') api_manila.share_snapshot_list.assert_called_with( mock.ANY, detailed=True) api_manila.share_list.assert_called_with(mock.ANY) api_manila.share_network_list.assert_called_with(mock.ANY) @mock.patch.object(api_manila, 'availability_zone_list') def test_create_share(self, az_list): url = reverse('horizon:project:shares:create') share = test_data.share share_net = test_data.active_share_network share_nets = [share_net] formData = { 'name': u'new_share', 'description': u'This is test share', 'method': u'CreateForm', 'share_network': share_net.id, 'size': 1, 'share_proto': u'NFS', 'share_type': 'fake', 'share-network-choices-fake': share_net.id, 'availability_zone': 'fake_az', } az_list.return_value = [self.FakeAZ('fake_az'), ] self.mock_object( api_manila, "share_create", mock.Mock(return_value=share)) self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=[])) self.mock_object( api_manila, "share_network_list", mock.Mock(return_value=share_nets)) self.mock_object( api_manila, "share_type_list", mock.Mock(return_value=[self.fake_share_type, ])) res = self.client.post(url, formData) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_create.assert_called_once_with( mock.ANY, size=formData['size'], name=formData['name'], description=formData['description'], proto=formData['share_proto'], snapshot_id=None, is_public=False, share_group_id=None, share_network=share_net.id, metadata={}, share_type=formData['share_type'], availability_zone=formData['availability_zone']) api_manila.share_snapshot_list.assert_called_once_with(mock.ANY) api_manila.share_network_list.assert_called_once_with(mock.ANY) api_manila.share_type_list.assert_called_once_with(mock.ANY) @mock.patch.object(api_manila, 'availability_zone_list') def test_create_share_from_snapshot(self, mock_az_list): share = test_data.share share_net = test_data.active_share_network share_nets = [share_net] snapshot = test_data.snapshot url = reverse('horizon:project:shares:create') formData = { 'name': u'new_share', 'description': u'This is test share from snapshot', 'method': u'CreateForm', 'share_network': share_net.id, 'size': snapshot.size, 'share_proto': 'NFS', 'share_type': 'fake', 'share_source_type': 'snapshot', 'snapshot': snapshot.id, 'share-network-choices-fake': share_net.id, 'availability_zone': 'fake_az', } mock_az_list.return_value = [self.FakeAZ('fake_az'), ] self.mock_object( api_manila, "share_create", mock.Mock(return_value=share)) self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=[snapshot])) self.mock_object( api_manila, "share_snapshot_get", mock.Mock(return_value=snapshot)) self.mock_object( api_manila, "share_network_list", mock.Mock(return_value=share_nets)) self.mock_object( api_manila, "share_type_list", mock.Mock(return_value=[self.fake_share_type, ])) res = self.client.post(url, formData) mock_az_list.assert_called_once_with(mock.ANY) api_manila.share_snapshot_list.assert_not_called() api_manila.share_snapshot_get.assert_called_once_with( mock.ANY, snapshot.id) api_manila.share_network_list.assert_called_once_with(mock.ANY) api_manila.share_type_list.assert_called_once_with(mock.ANY) api_manila.share_create.assert_called_with( mock.ANY, size=formData['size'], name=formData['name'], description=formData['description'], proto=formData['share_proto'], snapshot_id=snapshot.id, is_public=False, share_group_id=None, share_network=share_net.id, metadata={}, share_type=formData['share_type'], availability_zone=formData['availability_zone']) self.assertRedirectsNoFollow(res, INDEX_URL) def test_delete_share(self): formData = {'action': 'shares__delete__%s' % self.share.id} self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=[])) self.mock_object( api_manila, "share_network_list", mock.Mock(return_value=[])) self.mock_object(api_manila, "share_delete") self.mock_object( api_manila, "share_get", mock.Mock(return_value=self.share)) self.mock_object( api_manila, "share_list", mock.Mock(return_value=[self.share])) res = self.client.post(INDEX_URL, formData) api_manila.share_network_list.assert_called_once_with(mock.ANY) api_manila.share_snapshot_list.assert_called_once_with( mock.ANY, detailed=True) api_manila.share_list.assert_called_with(mock.ANY) api_manila.share_get.assert_called_with(mock.ANY, self.share.id) api_manila.share_delete.assert_called_with( mock.ANY, self.share.id, share_group_id=self.share.share_group_id) self.assertRedirectsNoFollow(res, INDEX_URL) def test_detail_view(self): share_net = test_data.active_share_network rules = [test_data.ip_rule, test_data.user_rule, test_data.cephx_rule] export_locations = test_data.export_locations url = reverse('horizon:project:shares:detail', args=[self.share.id]) self.mock_object( api_manila, "share_network_get", mock.Mock(return_value=share_net)) self.mock_object( api_manila, "share_rules_list", mock.Mock(return_value=rules)) self.mock_object( api_manila, "share_export_location_list", mock.Mock(return_value=export_locations)) res = self.client.get(url) self.assertContains( res, "

Share Details: %s

" % self.share.name, 1, 200) self.assertContains(res, "
%s
" % self.share.name, 1, 200) self.assertContains(res, "
%s
" % self.share.id, 1, 200) self.assertContains(res, "
%s GiB
" % self.share.size, 1, 200) self.assertContains( res, "
%s
" % self.share.share_proto, 1, 200) self.assertContains( res, "
%s
" % self.share.availability_zone, 1, 200) for el in export_locations: self.assertContains(res, "value=\"%s\"" % el.path, 1, 200) self.assertContains( res, "
Preferred: %s
" % el.preferred, 1, 200) self.assertContains( res, "
Is admin only: %s
" % el.is_admin_only, 1, 200) self.assertContains( res, ("
Share Replica ID: %s
" % export_locations[0].share_instance_id), 2, 200) for rule in rules: self.assertContains(res, "
%s
" % rule.access_type, 1, 200) self.assertContains( res, "
Access to: %s
" % rule.access_to, 1, 200) if 'cephx' == rule.access_type: self.assertContains( res, "
Access Key: %s
" % rule.access_key, 1, 200) self.assertContains( res, "
Access Key:
", len(rules) - sum(r.access_type == 'cephx' for r in rules), 200) self.assertContains( res, "
Access Level: rw
", len(rules), 200) self.assertContains( res, "
Status: active
", len(rules), 200) self.assertNoMessages() api_manila.share_rules_list.assert_called_once_with( mock.ANY, self.share.id) api_manila.share_export_location_list.assert_called_once_with( mock.ANY, self.share.id) def test_update_share_get(self): share = test_data.share url = reverse('horizon:project:shares:update', args=[share.id]) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.get(url) api_manila.share_get.assert_called_once_with(mock.ANY, share.id) self.assertNoMessages() self.assertTemplateUsed(res, 'project/shares/update.html') def test_update_share_post(self): self.mock_object(api_manila, "share_update") formData = { 'method': 'UpdateForm', 'name': self.share.name, 'description': self.share.description, 'is_public': False, } url = reverse('horizon:project:shares:update', args=[self.share.id]) res = self.client.post(url, formData) self.assertRedirectsNoFollow(res, INDEX_URL) api_manila.share_update.assert_called_once_with( mock.ANY, self.share, formData['name'], formData['description'], is_public=six.text_type(formData['is_public'])) api_manila.share_get.assert_has_calls( [mock.call(mock.ANY, self.share.id) for i in (1, 2)]) def test_list_rules(self): rules = [test_data.ip_rule, test_data.user_rule, test_data.cephx_rule] self.mock_object( api_manila, "share_rules_list", mock.Mock(return_value=rules)) url = reverse( 'horizon:project:shares:manage_rules', args=[self.share.id]) res = self.client.get(url) self.assertEqual(res.status_code, 200) self.assertTemplateUsed(res, 'project/shares/manage_rules.html') api_manila.share_rules_list.assert_called_once_with( mock.ANY, self.share.id) def test_create_rule_get(self): url = reverse('horizon:project:shares:rule_add', args=[self.share.id]) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.get(url) self.assertNoMessages() self.assertTemplateUsed(res, 'project/shares/rule_add.html') def test_create_rule_post(self): url = reverse('horizon:project:shares:rule_add', args=[self.share.id]) self.mock_object(api_manila, "share_allow") formData = { 'access_type': 'user', 'method': u'CreateForm', 'access_to': 'someuser', 'access_level': 'rw', } res = self.client.post(url, formData) api_manila.share_allow.assert_called_once_with( mock.ANY, self.share.id, access_type=formData['access_type'], access_to=formData['access_to'], access_level=formData['access_level']) self.assertRedirectsNoFollow( res, reverse('horizon:project:shares:manage_rules', args=[self.share.id]) ) def test_delete_rule(self): rule = test_data.ip_rule formData = {'action': 'rules__delete__%s' % rule.id} self.mock_object(api_manila, "share_deny") self.mock_object( api_manila, "share_rules_list", mock.Mock(return_value=[rule])) url = reverse( 'horizon:project:shares:manage_rules', args=[self.share.id]) self.client.post(url, formData) api_manila.share_deny.assert_called_with( mock.ANY, self.share.id, rule.id) api_manila.share_rules_list.assert_called_with(mock.ANY, self.share.id) def test_extend_share_get(self): share = test_data.share usage_limit = { 'maxTotalShareGigabytes': 250, 'totalShareGigabytesUsed': 20, } url = reverse('horizon:project:shares:extend', args=[share.id]) self.mock_object( quotas, "tenant_limit_usages", mock.Mock(return_value=usage_limit)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.get(url) api_manila.share_get.assert_called_once_with(mock.ANY, share.id) self.assertNoMessages() self.assertTemplateUsed(res, 'project/shares/extend.html') def test_extend_share_open_form_successfully(self): self.share.size = 5 usage_limit = { 'maxTotalShareGigabytes': self.share.size + 50, 'totalShareGigabytesUsed': self.share.size, } url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object(api_manila, "share_extend") self.mock_object( quotas, "tenant_limit_usages", mock.Mock(return_value=usage_limit)) response = self.client.get(url) self.assertEqual(200, response.status_code) self.assertTemplateUsed(response, 'project/shares/extend.html') api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id) self.assertFalse(api_manila.share_extend.called) quotas.tenant_limit_usages.assert_called_once_with(mock.ANY) def test_extend_share_get_with_api_exception(self): usage_limit = { 'maxTotalShareGigabytes': self.share.size + 50, 'totalShareGigabytesUsed': self.share.size, } url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object(api_manila, "share_extend") self.mock_object( quotas, "tenant_limit_usages", mock.Mock(return_value=usage_limit)) self.mock_object( api_manila, "share_get", mock.Mock(return_value=Exception('Fake share NotFound exception'))) response = self.client.get(url) self.assertEqual(404, response.status_code) self.assertTemplateNotUsed( response, 'project/shares/shares/extend.html') self.assertFalse(api_manila.share_extend.called) api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id) self.assertFalse(quotas.tenant_limit_usages.called) @ddt.data(6, 54, 55) def test_extend_share_post_successfully(self, new_size): self.share.size = 5 form_data = {'new_size': new_size} usage_limit = { 'maxTotalShareGigabytes': self.share.size + 50, 'totalShareGigabytesUsed': self.share.size, } url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object(api_manila, "share_extend") self.mock_object( quotas, "tenant_limit_usages", mock.Mock(return_value=usage_limit)) response = self.client.post(url, form_data) self.assertEqual(302, response.status_code) self.assertTemplateNotUsed( response, 'project/shares/extend.html') api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id) api_manila.share_extend.assert_called_once_with( mock.ANY, self.share.id, form_data['new_size']) quotas.tenant_limit_usages.assert_called_once_with(mock.ANY) self.assertRedirectsNoFollow(response, INDEX_URL) @ddt.data(0, 5, 56) def test_extend_share_post_with_invalid_value(self, new_size): self.share.size = 5 form_data = {'new_size': new_size} usage_limit = { 'maxTotalShareGigabytes': self.share.size + 50, 'totalShareGigabytesUsed': self.share.size, } url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object(api_manila, "share_extend") self.mock_object( quotas, "tenant_limit_usages", mock.Mock(return_value=usage_limit)) response = self.client.post(url, form_data) self.assertEqual(200, response.status_code) self.assertTemplateUsed(response, 'project/shares/extend.html') self.assertFalse(api_manila.share_extend.called) api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id) quotas.tenant_limit_usages.assert_called_with(mock.ANY) def test_extend_share_post_with_api_exception(self): self.share.size = 5 form_data = {'new_size': 30} usage_limit = { 'maxTotalShareGigabytes': self.share.size + 50, 'totalShareGigabytesUsed': self.share.size, } url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object( api_manila, "share_extend", mock.Mock(return_value=Exception('Fake API exception'))) self.mock_object( quotas, "tenant_limit_usages", mock.Mock(return_value=usage_limit)) response = self.client.post(url, form_data) self.assertEqual(302, response.status_code) self.assertTemplateNotUsed( response, 'project/shares/extend.html') api_manila.share_extend.assert_called_once_with( mock.ANY, self.share.id, form_data['new_size']) api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id) quotas.tenant_limit_usages.assert_called_once_with(mock.ANY) self.assertRedirectsNoFollow(response, INDEX_URL) def test_revert_to_snapshot_get_success(self): snapshots = [ type('FakeSnapshot', (object, ), {'name': s_n, 'id': s_id, 'created_at': c_at}) for s_n, s_id, c_at in ( ('foo_name', 'foo_id', '2017-04-20T12:31:14.000000'), ('bar_name', 'bar_id', '2017-04-20T12:31:16.000000')) ] url = reverse('horizon:project:shares:revert', args=[self.share.id]) self.mock_object(api_manila, "share_revert") self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=snapshots)) res = self.client.get(url) api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id) api_manila.share_snapshot_list.assert_called_once_with( mock.ANY, search_opts={'share_id': self.share.id}) api_manila.share_revert.assert_not_called() self.assertNoMessages() self.assertTemplateUsed(res, 'project/shares/revert.html') def test_revert_to_snapshot_post_success(self): snapshots = [ type('FakeSnapshot', (object, ), {'name': s_n, 'id': s_id, 'created_at': c_at}) for s_n, s_id, c_at in ( ('foo_name', 'foo_id', '2017-04-20T12:31:14.000000'), ('bar_name', 'bar_id', '2017-04-20T12:31:16.000000'), ('quuz_name', 'quuz_id', '2017-04-20T12:31:13.000000')) ] url = reverse('horizon:project:shares:revert', args=[self.share.id]) self.mock_object(api_manila, "share_revert") self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=snapshots)) data = {'snapshot': snapshots[1].id} res = self.client.post(url, data) api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id) api_manila.share_snapshot_list.assert_called_once_with( mock.ANY, search_opts={'share_id': self.share.id}) api_manila.share_revert.assert_called_once_with( mock.ANY, self.share.id, data['snapshot']) self.assertNoMessages() self.assertTemplateNotUsed(res, 'project/shares/revert.html') self.assertRedirectsNoFollow(res, INDEX_URL) def test_revert_to_snapshot_share_not_found(self): url = reverse("horizon:project:shares:revert", args=[self.share.id]) self.mock_object(api_manila, "share_revert") api_manila.share_get.side_effect = Exception( 'Fake share NotFound exception') self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=[])) res = self.client.get(url) self.assertEqual(404, res.status_code) self.assertTemplateNotUsed( res, 'project/shares/revert.html') api_manila.share_revert.assert_not_called() api_manila.share_snapshot_list.assert_not_called() api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id) def test_revert_to_snapshot_failed(self): snapshots = [ type('FakeSnapshot', (object, ), {'name': s_n, 'id': s_id, 'created_at': c_at}) for s_n, s_id, c_at in ( ('foo_name', 'foo_id', '2017-04-20T12:31:14.000000'), ('bar_name', 'bar_id', '2017-04-20T12:31:16.000000'), ('quuz_name', 'quuz_id', '2017-04-20T12:31:13.000000')) ] url = reverse('horizon:project:shares:revert', args=[self.share.id]) self.mock_object( api_manila, "share_revert", mock.Mock(side_effect=Exception('Fake reverting error'))) self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=snapshots)) data = {'snapshot': snapshots[1].id} res = self.client.post(url, data) self.assertEqual(302, res.status_code) api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id) api_manila.share_snapshot_list.assert_called_once_with( mock.ANY, search_opts={'share_id': self.share.id}) api_manila.share_revert.assert_called_once_with( mock.ANY, self.share.id, data['snapshot']) self.assertTemplateNotUsed(res, 'project/shares/revert.html') self.assertRedirectsNoFollow(res, INDEX_URL) def test_update_share_metadata_get(self): share = test_data.share_with_metadata url = reverse( 'horizon:project:shares:update_metadata', args=[share.id]) self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.get(url) api_manila.share_get.assert_called_once_with(mock.ANY, share.id) self.assertNoMessages() self.assertTemplateUsed( res, 'project/shares/update_metadata.html') def test_update_share_metadata_post(self): share = test_data.share_with_metadata data = { 'metadata': 'aaa=ccc', } form_data = { 'metadata': {'aaa': 'ccc'}, } url = reverse( 'horizon:project:shares:update_metadata', args=[share.id]) self.mock_object( api_manila, "share_get", mock.Mock(return_value=share)) self.mock_object(api_manila, "share_set_metadata") self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.post(url, data) api_manila.share_set_metadata.assert_called_once_with( mock.ANY, share, form_data['metadata']) self.assertRedirectsNoFollow(res, INDEX_URL) @ddt.data((True, True), (True, False), (False, False)) @ddt.unpack def test_enable_public_share_creation(self, enable_public_shares, is_public): def _get_form(**kwargs): return forms.CreateForm(self.request, **kwargs) self.mock_object( api_manila, "share_create", mock.Mock(return_value=self.share)) self.mock_object( api_manila, "share_snapshot_list", mock.Mock(return_value=[])) self.mock_object( api_manila, "share_network_list", mock.Mock(return_value=[test_data.active_share_network])) self.mock_object( api_manila, "share_type_list", mock.Mock(return_value=[self.fake_share_type, ])) self.mock_object( api_manila, "availability_zone_list", mock.Mock(return_value=[self.FakeAZ('fake_az'), ])) data = { 'name': u'new_share', 'description': u'This is test share', 'method': u'CreateForm', 'share_network': test_data.active_share_network.id, 'size': 1, 'share_proto': u'NFS', 'share_type': 'fake', 'share-network-choices-fake': test_data.active_share_network.id, 'availability_zone': 'fake_az', 'metadata': 'key=value', 'snapshot_id': None, } if enable_public_shares: data.update({'is_public': is_public}) with self.settings(OPENSTACK_MANILA_FEATURES={ 'enable_public_shares': enable_public_shares}): form = _get_form() result = form.handle(self.request, data) self.assertTrue(result) self.assertEqual( enable_public_shares, form.enable_public_shares) if enable_public_shares: self.assertIn("is_public", form.fields) self.assertTrue(form.fields["is_public"]) else: self.assertNotIn("is_public", form.fields) api_manila.share_create.assert_called_once_with( self.request, availability_zone=data['availability_zone'], description=data['description'], is_public=is_public, metadata=utils.parse_str_meta(data['metadata'])[0], name=data['name'], proto=data['share_proto'], share_group_id=None, share_network=test_data.active_share_network.id, share_type=data['share_type'], size=data['size'], snapshot_id=data['snapshot_id'], ) horizon_messages.success.assert_called_once_with( self.request, mock.ANY) @ddt.data((True, True), (True, False), (False, False)) @ddt.unpack def test_enable_public_share_update(self, enable_public_shares, is_public): def _get_form(initial): kwargs = { 'prefix': None, 'initial': initial, } return forms.UpdateForm(self.request, **kwargs) initial = {'share_id': 'fake_share_id'} self.mock_object( api_manila, "share_update", mock.Mock(return_value=self.share)) data = { 'name': u'old_share', 'description': u'This is test share', } if enable_public_shares: data.update({'is_public': is_public}) with self.settings(OPENSTACK_MANILA_FEATURES={ 'enable_public_shares': enable_public_shares}): form = _get_form(initial) result = form.handle(self.request, data) self.assertTrue(result) self.assertEqual( enable_public_shares, form.enable_public_shares) if enable_public_shares: self.assertIn("is_public", form.fields) self.assertTrue(form.fields["is_public"]) else: self.assertNotIn("is_public", form.fields) api_manila.share_update.assert_called_once_with( self.request, self.share, data['name'], data['description'], is_public=is_public, ) horizon_messages.success.assert_called_once_with( self.request, mock.ANY) manila-ui-2.13.0/manila_ui/tests/dashboards/project/test_data.py000066400000000000000000000425721323215354300246660ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # # 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 collections try: # NOTE(vponomaryov): Try import latest modules, assuming we have # manilaclient that is new enough and have v2 API support. from manilaclient.v2 import quotas from manilaclient.v2 import security_services from manilaclient.v2 import share_networks from manilaclient.v2 import share_snapshots from manilaclient.v2 import share_types from manilaclient.v2 import shares except ImportError: # NOTE(vponomaryov): If we got here then we have old manilaclient. from manilaclient.v1 import quotas from manilaclient.v1 import security_services from manilaclient.v1 import share_networks from manilaclient.v1 import share_snapshots from manilaclient.v1 import share_types from manilaclient.v1 import shares from manilaclient.v2 import share_export_locations from manilaclient.v2 import share_group_snapshots from manilaclient.v2 import share_group_types from manilaclient.v2 import share_groups from manilaclient.v2 import share_instances from manilaclient.v2 import share_replicas from manilaclient.v2 import share_servers from manilaclient.v2 import share_snapshot_export_locations from openstack_dashboard import api from openstack_dashboard.usage import quotas as usage_quotas class FakeAPIClient(object): client = "fake_client" share = shares.Share( shares.ShareManager(FakeAPIClient), {'id': "11023e92-8008-4c8b-8059-7f2293ff3887", 'status': 'available', 'size': 40, 'name': 'Share name', 'description': 'Share description', 'share_proto': 'NFS', 'metadata': {}, 'created_at': '2014-01-27 10:30:00', 'share_server_id': '1', 'share_network_id': '7f3d1c33-8d00-4511-29df-a2def31f3b5d', 'availability_zone': 'Test AZ', 'replication_type': 'readable', 'share_group_id': 'fake_share_group_id', 'mount_snapshot_support': False}) nameless_share = shares.Share( shares.ShareManager(FakeAPIClient), {'id': "4b069dd0-6eaa-4272-8abc-5448a68f1cce", 'status': 'available', 'size': 10, 'name': '', 'description': '', 'share_proto': 'NFS', 'export_location': "/dev/hda", 'metadata': {}, 'created_at': '2010-11-21 18:34:25', 'share_type': 'vol_type_1', 'share_server_id': '1', 'share_network_id': '7f3d1c33-8d00-4511-29df-a2def31f3b5d', 'availability_zone': 'Test AZ', 'replication_type': None, 'mount_snapshot_support': False}) share_with_metadata = shares.Share( shares.ShareManager(FakeAPIClient), {'id': "0ebb3748-c1dr-4bb6-8315-0354e7691fff", 'status': 'available', 'size': 40, 'name': 'Share with metadata', 'description': 'Share description', 'share_proto': 'NFS', 'metadata': {'aaa': 'bbb'}, 'created_at': '2016-06-31 00:00:00', 'share_server_id': '1', 'share_network_id': '7f3d1c33-8d00-4511-29df-a2def31f3b5d', 'availability_zone': 'Test AZ', 'replication_type': 'readable', 'mount_snapshot_support': False}) other_share = shares.Share( shares.ShareManager(FakeAPIClient), {'id': "21023e92-8008-1234-8059-7f2293ff3889", 'status': 'in-use', 'size': 10, 'name': u'my_share', 'description': '', 'share_proto': 'NFS', 'metadata': {}, 'created_at': '2013-04-01 10:30:00', 'share_type': None, 'share_server_id': '1', 'share_network_id': '7f3d1c33-8d00-4511-29df-a2def31f3b5d', 'availability_zone': 'Test AZ', 'replication_type': 'readable', 'mount_snapshot_support': False}) share_replica = share_replicas.ShareReplica( share_replicas.ShareReplicaManager(FakeAPIClient), {'id': '11023e92-8008-4c8b-8059-replica00001', 'availability_zone': share.availability_zone, 'host': 'fake_host_1', 'share_id': share.id, 'status': 'available', 'replica_state': 'active', 'created_at': '2016-07-19 19:46:13', 'updated_at': '2016-07-19 19:47:14'} ) share_replica2 = share_replicas.ShareReplica( share_replicas.ShareReplicaManager(FakeAPIClient), {'id': '11023e92-8008-4c8b-8059-replica00002', 'availability_zone': share.availability_zone, 'host': 'fake_host_2', 'share_id': share.id, 'status': 'available', 'replica_state': 'in_sync', 'created_at': '2016-07-19 20:46:13', 'updated_at': '2016-07-19 20:47:14'} ) share_replica3 = share_replicas.ShareReplica( share_replicas.ShareReplicaManager(FakeAPIClient), {'id': '11023e92-8008-4c8b-8059-replica00003', 'availability_zone': share.availability_zone, 'host': 'fake_host_3', 'share_id': share.id, 'status': 'available', 'replica_state': 'active', 'created_at': '2016-07-19 21:46:13', 'updated_at': '2016-07-19 21:47:14'} ) share_mount_snapshot = shares.Share( shares.ShareManager(FakeAPIClient), {'id': "11023e92-8008-4c8b-8059-7f2293ff3888", 'status': 'available', 'size': 40, 'name': 'Share name', 'description': 'Share description', 'share_proto': 'NFS', 'metadata': {}, 'created_at': '2014-01-27 10:30:00', 'share_server_id': '1', 'share_network_id': '7f3d1c33-8d00-4511-29df-a2def31f3b5d', 'availability_zone': 'Test AZ', 'replication_type': 'readable', 'mount_snapshot_support': True}) admin_export_location = share_export_locations.ShareExportLocation( share_export_locations.ShareExportLocationManager(FakeAPIClient), {'id': '6921e862-88bc-49a5-a2df-efeed9acd583', 'path': '1.1.1.1:/path/to/admin/share', 'preferred': False, 'is_admin_only': True, 'share_instance_id': 'e1c2d35e-fe67-4028-ad7a-45f668732b1d'} ) user_export_location = share_export_locations.ShareExportLocation( share_export_locations.ShareExportLocationManager(FakeAPIClient), {'id': 'b6bd76ce-12a2-42a9-a30a-8a43b503867d', 'path': '2.2.2.2:/path/to/user/share', 'preferred': True, 'is_admin_only': False, 'share_instance_id': 'e1c2d35e-fe67-4028-ad7a-45f668732b1d'} ) export_locations = [admin_export_location, user_export_location] admin_snapshot_export_locations = [ share_snapshot_export_locations.ShareSnapshotExportLocation( share_snapshot_export_locations.ShareSnapshotExportLocationManager( FakeAPIClient), {'id': '6921e862-88bc-49a5-a2df-efeed9acd584', 'path': '1.1.1.1:/path/to/admin/share', 'is_admin_only': True, 'share_snapshot_instance_id': 'e1c2d35e-fe67-4028-ad7a-45f668732b1e'} ), share_snapshot_export_locations.ShareSnapshotExportLocation( share_snapshot_export_locations.ShareSnapshotExportLocationManager( FakeAPIClient), {'id': '6921e862-88bc-49a5-a2df-efeed9acd585', 'path': '1.1.1.2:/path/to/admin/share', 'is_admin_only': False, 'share_snapshot_instance_id': 'e1c2d35e-fe67-4028-ad7a-45f668732b1f'} ) ] user_snapshot_export_locations = [ share_snapshot_export_locations.ShareSnapshotExportLocation( share_snapshot_export_locations.ShareSnapshotExportLocationManager( FakeAPIClient), {'id': 'b6bd76ce-12a2-42a9-a30a-8a43b503867e', 'path': '1.1.1.1:/path/to/user/share_snapshot'} ), share_snapshot_export_locations.ShareSnapshotExportLocation( share_snapshot_export_locations.ShareSnapshotExportLocationManager( FakeAPIClient), {'id': 'b6bd76ce-12a2-42a9-a30a-8a43b503867f', 'path': '1.1.1.2:/not/too/long/path/to/user/share_snapshot'} ) ] rule = collections.namedtuple('Access', ['access_type', 'access_to', 'state', 'id', 'access_level', 'access_key']) user_rule = rule('user', 'someuser', 'active', '10837072-c49e-11e3-bd64-60a44c371189', 'rw', '') ip_rule = rule('ip', '1.1.1.1', 'active', '2cc8e2f8-c49e-11e3-bd64-60a44c371189', 'rw', '') cephx_rule = rule('cephx', 'alice', 'active', '235481bc-1a84-11e6-9666-68f728a0492e', 'rw', 'AQAdFCNYDCapMRAANuK/CiEZbog2911a+t5dcQ==') snapshot = share_snapshots.ShareSnapshot( share_snapshots.ShareSnapshotManager(FakeAPIClient), {'id': '5f3d1c33-7d00-4511-99df-a2def31f3b5d', 'name': 'test snapshot', 'description': 'share snapshot', 'size': 40, 'status': 'available', 'share_id': '11023e92-8008-4c8b-8059-7f2293ff3887'}) snapshot_mount_support = share_snapshots.ShareSnapshot( share_snapshots.ShareSnapshotManager(FakeAPIClient), {'id': '5f3d1c33-7d00-4511-99df-a2def31f3b5e', 'name': 'test snapshot', 'description': 'share snapshot', 'size': 40, 'status': 'available', 'share_id': '11023e92-8008-4c8b-8059-7f2293ff3888'}) inactive_share_network = share_networks.ShareNetwork( share_networks.ShareNetworkManager(FakeAPIClient), {'id': '6f3d1c33-8d00-4511-29df-a2def31f3b5d', 'name': 'test_share_net', 'description': 'test share network', 'status': 'INACTIVE', 'neutron_net_id': 'fake_neutron_net_id', 'neutron_subnet_id': 'fake_neutron_subnet_id'}) active_share_network = share_networks.ShareNetwork( share_networks.ShareNetworkManager(FakeAPIClient), {'id': '7f3d1c33-8d00-4511-29df-a2def31f3b5d', 'name': 'test_share_net', 'description': 'test share network', 'status': 'ACTIVE', 'neutron_net_id': 'fake_neutron_net_id', 'neutron_subnet_id': 'fake_neutron_subnet_id'}) sec_service = security_services.SecurityService( security_services.SecurityServiceManager(FakeAPIClient), {'id': '7f3d1c33-8d10-4511-29df-a2def31f3b5d', 'server': '1.1.1.1', 'dns_ip': '2.2.2.2', 'user': 'someuser', 'password': 'somepass', 'type': 'active_directory', 'name': 'test-sec-service', 'description': 'test security service', 'domain': 'testdomain', }) share_instance = share_instances.ShareInstance( share_instances.ShareInstanceManager(FakeAPIClient), {'id': 'fake_share_instance_no_ss_id', 'status': 'available', 'host': 'host1@backend1#pool1', 'availability_zone': 'zone1', 'share_id': 'fake_share_id_1', 'share_network_id': 'fake_share_network_id_1', 'share_server_id': 'fake_share_server_id_1', 'created_at': '2016-04-26 13:14:15'} ) share_instance_no_ss = share_instances.ShareInstance( share_instances.ShareInstanceManager(FakeAPIClient), {'id': 'fake_share_instance_id', 'status': 'available', 'host': 'host2@backend2#pool2', 'availability_zone': 'zone2', 'share_id': 'fake_share_id_2', 'share_network_id': None, 'share_server_id': None, 'created_at': '2016-04-26 14:15:16'} ) share_server = share_servers.ShareServer( share_servers.ShareServerManager(FakeAPIClient), {'id': 'fake_share_server_id1', 'status': 'active', 'share_network_id': 'fake_share_network_id1', 'share_network_name': 'fake_share_network_name1', 'project_id': 'fake_project_id1', 'backend_details': { 'foo_key': 'foo_value', 'bar_key_foo': 'bar_value_foo', }, 'host': 'fakehost1@fakebackend1#fakepool1'} ) share_server_errored = share_servers.ShareServer( share_servers.ShareServerManager(FakeAPIClient), {'id': 'fake_share_server_id2', 'status': 'error', 'share_network_id': 'fake_share_network_id2', 'share_network_name': 'fake_share_network_name2', 'project_id': 'fake_project_id2', 'backend_details': {}, 'host': 'fakehost2@fakebackend2#fakepool2'} ) share_type = share_types.ShareType( share_types.ShareTypeManager(FakeAPIClient), {'id': 'share-type-id1', 'name': 'test-share-type1', 'share_type_access:is_public': True, 'extra_specs': { 'snapshot_support': True, 'driver_handles_share_servers': False} } ) share_type_private = share_types.ShareType( share_types.ShareTypeManager(FakeAPIClient), {'id': 'share-type-id2', 'name': 'test-share-type2', 'share_type_access:is_public': False, 'extra_specs': {'driver_handles_share_servers': False}} ) share_type_dhss_true = share_types.ShareType( share_types.ShareTypeManager(FakeAPIClient), {'id': 'share-type-id3', 'name': 'test-share-type3', 'share_type_access:is_public': True, 'extra_specs': {'driver_handles_share_servers': True}} ) share_group_type = share_group_types.ShareGroupType( share_group_types.ShareGroupTypeManager(FakeAPIClient), {'id': 'fake_share_group_type_id1', 'name': 'fake_share_group_type_name', 'share_types': [share_type.id], 'group_specs': {'k1': 'v1', 'k2': 'v2'}, 'is_public': True} ) share_group_type_private = share_group_types.ShareGroupType( share_group_types.ShareGroupTypeManager(FakeAPIClient), {'id': 'fake_private_share_group_type_id2', 'name': 'fake_private_share_group_type_name', 'share_types': [share_type.id, share_type_private.id], 'group_specs': {'k1': 'v1', 'k2': 'v2'}, 'is_public': False} ) share_group_type_dhss_true = share_group_types.ShareGroupType( share_group_types.ShareGroupTypeManager(FakeAPIClient), {'id': 'fake_share_group_type_id3', 'name': 'fake_share_group_type_name', 'share_types': [share_type_dhss_true.id], 'group_specs': {'k3': 'v3', 'k4': 'v4'}, 'is_public': True} ) share_group = share_groups.ShareGroup( share_groups.ShareGroupManager(FakeAPIClient), {'id': 'fake_share_group_id', 'name': 'fake_share_group_name', 'description': 'fake sg description', 'status': 'available', 'share_types': [share_type.id], 'share_group_type_id': share_group_type.id, 'source_share_group_snapshot_id': None, 'share_network_id': None, 'share_server_id': None, 'availability_zone': None, 'host': 'fake_host_987654321', 'consistent_snapshot_support': None, 'created_at': '2017-05-31T13:36:15.000000', 'project_id': 'fake_project_id_987654321'} ) share_group_nameless = share_groups.ShareGroup( share_groups.ShareGroupManager(FakeAPIClient), {'id': 'fake_nameless_share_group_id', 'name': None, 'status': 'available', 'share_types': [share_type.id], 'share_group_type_id': share_group_type.id, 'source_share_group_snapshot_id': None, 'share_network_id': None, 'share_server_id': None, 'availability_zone': None, 'host': 'fake_host_987654321', 'consistent_snapshot_support': None, 'created_at': '2017-05-31T13:36:15.000000', 'project_id': 'fake_project_id_987654321'} ) share_group_dhss_true = share_groups.ShareGroup( share_groups.ShareGroupManager(FakeAPIClient), {'id': 'fake_dhss_true_share_group_id', 'name': 'fake_dhss_true_share_group_name', 'status': 'available', 'share_types': [share_type_dhss_true.id], 'share_group_type_id': share_group_type_dhss_true.id, 'source_share_group_snapshot_id': None, 'share_network_id': 'fake_share_network_id', 'share_server_id': 'fake_share_server_id', 'availability_zone': None, 'host': 'fake_host_987654321', 'consistent_snapshot_support': None, 'created_at': '2017-05-31T23:59:59.000000', 'project_id': 'fake_project_id_987654321'} ) share_group_snapshot = share_group_snapshots.ShareGroupSnapshot( share_group_snapshots.ShareGroupSnapshotManager(FakeAPIClient), {'id': 'fake_share_group_snapshot_id_1', 'name': 'fake_share_group_snapshot_name', 'status': 'available', 'share_group_id': share_group.id, 'description': 'fake sgs description', 'created_at': '2017-06-01T13:13:13.000000', 'project_id': 'fake_project_id_987654321', 'members': [ {'share_id': 'fake_share_id_1', 'id': 'fake_ssi_id_1', 'size': 1}, {'share_id': 'fake_share_id_2', 'id': 'fake_ssi_id_2', 'size': 2}, ]} ) share_group_snapshot_nameless = share_group_snapshots.ShareGroupSnapshot( share_group_snapshots.ShareGroupSnapshotManager(FakeAPIClient), {'id': 'fake_share_group_snapshot_id_2_nameless', 'name': None, 'status': 'available', 'share_group_id': share_group_nameless.id, 'description': 'fake nameless sgs description', 'created_at': '2017-06-02T14:14:14.000000', 'project_id': 'fake_project_id_987654321', 'members': []} ) # Quota Sets quota_data = dict(shares='1', share_snapshots='1', share_gigabytes='1000') quota = quotas.QuotaSet(quotas.QuotaSetManager(FakeAPIClient), quota_data) # Quota Usages quota_usage_data = {'gigabytes': {'used': 0, 'quota': 1000}, 'shares': {'used': 0, 'quota': 10}, 'snapshots': {'used': 0, 'quota': 10}, 'share_networks': {'used': 0, 'quota': 10}} quota_usage = usage_quotas.QuotaUsage() for k, v in quota_usage_data.items(): quota_usage.add_quota(api.base.Quota(k, v['quota'])) quota_usage.tally(k, v['used']) # Manila Limits limits = {"absolute": {"totalSharesUsed": 1, "totalShareGigabytesUsed": 5, "maxTotalShareGigabytes": 1000, "maxTotalShares": 10}} manila-ui-2.13.0/manila_ui/tests/dashboards/project/tests.py000066400000000000000000000140111323215354300240430ustar00rootroot00000000000000# Copyright (c) 2014 NetApp, Inc. # # 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 django.core.urlresolvers import reverse from django.utils import translation import mock from openstack_dashboard.api import base from openstack_dashboard.usage import quotas from manila_ui.api import manila as api_manila from manila_ui.dashboards.project import shares from manila_ui.tests import helpers as test INDEX_URL = reverse('horizon:project:shares:index') class PieChartsTests(test.TestCase): def test_get_context_data(self): limits = { "totalSharesUsed": 1, "totalShareGigabytesUsed": 2, "totalShareNetworksUsed": 3, "totalShareSnapshotsUsed": 4, "totalSnapshotGigabytesUsed": 5, "maxTotalShares": 6, "maxTotalShareGigabytes": 7, "maxTotalShareNetworks": 8, "maxTotalShareSnapshots": 9, "maxTotalSnapshotGigabytes": 10, } existing_chart_name = "Foo" existing_chart = { "name": translation.ugettext_lazy(existing_chart_name), "used": 11, "max": 13, "text": "fake_text", } class ParentViewInstance(mock.MagicMock): def get_context_data(self, **kwargs): return {"charts": [existing_chart]} class ViewInstance(ParentViewInstance): usage = type("FakeUsage", (object, ), {"limits": limits}) view_instance = ViewInstance() result = shares.get_context_data( view_instance, fook="foov", bark="barv") charts = result.get("charts", []) self.assertEqual(6, len(charts)) expected_charts = { existing_chart_name: { "name": existing_chart_name, "used": existing_chart["used"], "max": existing_chart["max"], "text": existing_chart["text"]}, "Shares": {"name": "Shares", "used": 1, "max": 6, "text": False}, "Share Storage": { "name": "Share Storage", 'used': 2, "max": 7, "text": False}, "Share Networks": { "name": "Share Networks", "used": 3, "max": 8, "text": False}, "Share Snapshots": { "name": "Share Snapshots", "used": 4, "max": 9, "text": False}, "Share Snapshots Storage": { "name": "Share Snapshots Storage", "used": 5, "max": 10, "text": False}, } for chart in charts: name = chart["name"].title() self.assertEqual( {"name": name, "used": chart["used"], "max": chart["max"], "text": chart["text"]}, expected_charts.pop(name, "NotFound") ) @ddt.ddt class QuotaTests(test.TestCase): def test_get_disabled_quotas(self): self.mock_object( base, "is_service_enabled", mock.Mock(return_value=False)) result_quotas = quotas.get_disabled_quotas(self.request) expected_quotas = set(quotas.QUOTA_FIELDS) self.assertItemsEqual(result_quotas, expected_quotas) @ddt.data( shares.ManilaUpdateDefaultQuotaAction, shares.ManilaUpdateProjectQuotaAction, shares.ManilaCreateProjectQuotaAction, ) def test_manila_quota_action(self, class_ref): self.mock_object( quotas, 'get_disabled_quotas', mock.Mock(return_value=[])) class_instance = class_ref(self.request, 'foo') expected_fields = set([ 'shares', 'share_gigabytes', 'share_snapshots', 'share_snapshot_gigabytes', 'share_networks', ]) # NOTE(vponomaryov): iterate over reversed list of visible fields # because manila's fields are at the end always. for vf in reversed(class_instance.visible_fields()): if expected_fields and vf.name in expected_fields: self.assertEqual(-1, vf.field.min_value) self.assertIsInstance( vf.field, shares.horizon.forms.IntegerField) expected_fields.remove(vf.name) self.assertSetEqual(set([]), expected_fields) self.assertTrue(quotas.get_disabled_quotas.called) @ddt.data('default_quota_get', 'tenant_quota_get') def test__get_manila_quota_data(self, method_name): fake_quotas = [ type('Fake', (object, ), {'name': name}) for name in ('gigabytes', 'snapshots', 'snapshot_gigabytes') ] self.mock_object( api_manila, method_name, mock.Mock(return_value=fake_quotas)) self.mock_object( shares, '_get_manila_disabled_quotas', mock.Mock(return_value=[])) result = shares._get_manila_quota_data( self.request, method_name) expected = [ 'share_gigabytes', 'share_snapshot_gigabytes', 'share_snapshots', ] self.assertEqual(3, len(result)) self.assertEqual( expected, sorted([element.name for element in result])) getattr(api_manila, method_name).assert_called_once_with( self.request, self.request.user.tenant_id) shares._get_manila_disabled_quotas.asssert_called_once_with( self.request) def test_manila_quota_fields(self): expected_fields = ( "shares", "share_gigabytes", "share_snapshots", "share_snapshot_gigabytes", "share_networks", ) for ef in expected_fields: self.assertIn(ef, shares.quotas.QUOTA_FIELDS) manila-ui-2.13.0/manila_ui/tests/dashboards/test_utils.py000066400000000000000000000066421323215354300234450ustar00rootroot00000000000000# Copyright (c) 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 django.forms import ValidationError # noqa from manila_ui.dashboards import utils from manila_ui.tests import helpers as base @ddt.ddt class ManilaDashboardsUtilsTests(base.TestCase): @ddt.data( ("", {}, []), (" ", {}, []), ("\n", {}, []), ("f", {}, ["f"]), ("f=b", {"f": "b"}, []), ("foo=bar", {"foo": "bar"}, []), ("\nfoo \n", {}, ["foo"]), ("'foo'=\"bar\"\n'bar'", {"foo": "bar"}, ["bar"]), (" foo= bar ", {"foo": "bar"}, []), ("foo= \" bar\"\n", {"foo": " bar"}, []), ("\n\nset_me_key = 'value with spaces and equality 2=2'\nunset_key ", {"set_me_key": "value with spaces and equality 2=2"}, ["unset_key"]), ("f" * 255, {}, ["f" * 255]), ("f" * 255 + "=" + "b" * 255, {"f" * 255: "b" * 255}, []), ) @ddt.unpack def test_parse_str_meta_success( self, input_data, expect_set_dict, expected_unset_list): set_dict, unset_list = utils.parse_str_meta(input_data) self.assertEqual(expect_set_dict, set_dict) self.assertEqual(expected_unset_list, unset_list) @ddt.data( "a b", "'a b'", "\"a b\"", "f" * 256, "f" * 256 + "=bar", "foo=" + "b" * 256, "\"a b \"", "foo=bar\nfoo", "foo=bar\nfoo=quuz", ) def test_parse_str_meta_validation_error(self, input_data): self.assertRaises(ValidationError, utils.parse_str_meta, input_data) @ddt.data( (({"a": ""}, ), "a = <script>alert('A')/*
b = */</script>"), (({"fookey": "foovalue", "barkey": "barvalue"}, ), "barkey = barvalue
fookey = foovalue"), (({"foo": "barquuz"}, 1, 2), "fo... = ba..."), (({"foo": "barquuz", "zfoo": "zbarquuz"}, 1, 3), "foo = bar..."), (({"foo": "barquuz", "zfoo": "zbarquuz"}, 2, 3), "foo = bar...
zfo... = zba..."), (({"foo": "barquuz", "zfoo": "zbarquuz"}, 3, 3), "foo = bar...
zfo... = zba..."), (({"foo": "barquuz", "zfoo": "zbarquuz"}, 3, 8), "foo = barquuz
zfoo = zbarquuz"), ) @ddt.unpack def test_metadata_to_str(self, input_args, expected_output): result = utils.metadata_to_str(*input_args) self.assertEqual(expected_output, result) @ddt.data( ("ldap", "LDAP"), ("active_directory", "Active Directory"), ("kerberos", "Kerberos"), ("FaKe", "FaKe"), ) @ddt.unpack def test_get_nice_security_service_type(self, input_value, expected_value): security_service = type("FakeSS", (object, ), {"type": input_value})() result = utils.get_nice_security_service_type(security_service) self.assertEqual(expected_value, result) manila-ui-2.13.0/manila_ui/tests/helpers.py000066400000000000000000000042251323215354300205710ustar00rootroot00000000000000# # 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 mock import os import unittest from manila_ui import api from manila_ui.tests.test_data import utils from openstack_dashboard.test import helpers def create_stubs(stubs_to_create={}): return helpers.create_stubs(stubs_to_create) class ManilaTestsMixin(object): def _setup_test_data(self): super(ManilaTestsMixin, self)._setup_test_data() utils.load_test_data(self) def mock_object(self, obj, attr_name, new_attr=None, **kwargs): """Use python mock to mock an object attribute Mocks the specified objects attribute with the given value. Automatically performs 'addCleanup' for the mock. """ if not new_attr: new_attr = mock.Mock() patcher = mock.patch.object(obj, attr_name, new_attr, **kwargs) patcher.start() # NOTE(vponomaryov): 'self.addCleanup(patcher.stop)' is not called # here, because it is inherited from Horizon project's test class. return new_attr @unittest.skipIf(os.environ.get('SKIP_UNITTESTS', False), "The SKIP_UNITTESTS env variable is set.") class TestCase(ManilaTestsMixin, helpers.TestCase): pass class BaseAdminViewTests(ManilaTestsMixin, helpers.BaseAdminViewTests): pass class APITestCase(ManilaTestsMixin, helpers.APITestCase): def setUp(self): super(APITestCase, self).setUp() self._manilaclient = self.mock_object(api.manila, "manilaclient") self.manilaclient = self._manilaclient.return_value class FakeEntity(object): def __init__(self, id, name): self.id = id self.name = name manila-ui-2.13.0/manila_ui/tests/settings.py000066400000000000000000000020301323215354300207570ustar00rootroot00000000000000# # 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 horizon.test.settings import * # noqa from openstack_dashboard.test.settings import * # noqa # Load the pluggable dashboard settings import manila_ui.local.enabled import openstack_dashboard.enabled from openstack_dashboard.utils import settings MANILA_UI_APPS = list(INSTALLED_APPS) + ['manila_ui.dashboards'] settings.update_dashboards( [ manila_ui.local.enabled, openstack_dashboard.enabled, ], HORIZON_CONFIG, MANILA_UI_APPS, ) manila-ui-2.13.0/manila_ui/tests/test_data/000077500000000000000000000000001323215354300205225ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/test_data/__init__.py000066400000000000000000000000001323215354300226210ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/tests/test_data/keystone_data.py000066400000000000000000000022221323215354300237240ustar00rootroot00000000000000# 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. def data(TEST): # Add manila to the keystone data TEST.service_catalog.append( {"type": "share", "name": "Manila", "endpoints_links": [], "endpoints": [ {"region": "RegionOne", "adminURL": "http://admin.manila.example.com:8786/v1", "internalURL": "http://int.manila.example.com:8786/v1", "publicURL": "http://public.manila.example.com:8786/v1"}]}, ) projects = [ type("%sProject" % v, (object, ), {'id': '%s_id' % v, 'name': '%s_name' % v}) for v in ('foo', 'bar', 'quuz') ] manila-ui-2.13.0/manila_ui/tests/test_data/utils.py000066400000000000000000000022711323215354300222360ustar00rootroot00000000000000# # 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 openstack_dashboard.test.test_data import utils def load_test_data(load_onto=None): from manila_ui.tests.test_data import keystone_data as manila_keystone_data from openstack_dashboard.test.test_data import exceptions from openstack_dashboard.test.test_data import keystone_data # The order of these loaders matters, some depend on others. loaders = ( exceptions.data, keystone_data.data, manila_keystone_data.data, ) if load_onto: for data_func in loaders: data_func(load_onto) return load_onto else: return utils.TestData(*loaders) manila-ui-2.13.0/manila_ui/tests/urls.py000066400000000000000000000013111323215354300201050ustar00rootroot00000000000000# # 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 django.conf import urls import openstack_dashboard.urls urlpatterns = [ urls.url(r'', urls.include(openstack_dashboard.urls)) ] manila-ui-2.13.0/manila_ui/utils/000077500000000000000000000000001323215354300165505ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/utils/__init__.py000066400000000000000000000000001323215354300206470ustar00rootroot00000000000000manila-ui-2.13.0/manila_ui/utils/filters.py000066400000000000000000000013531323215354300205740ustar00rootroot00000000000000# Copyright 2012 Nebula, Inc. # # 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 django.template.defaultfilters import register # noqa @register.filter def get_item(dictionary, key): return dictionary.get(key) manila-ui-2.13.0/releasenotes/000077500000000000000000000000001323215354300161435ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/notes/000077500000000000000000000000001323215354300172735ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/notes/.placeholder000066400000000000000000000000001323215354300215440ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/notes/add-maprfs-protocol-5d7f4b4c47da8fab.yaml000066400000000000000000000001071323215354300264730ustar00rootroot00000000000000--- features: - Added native protocol for MapRFS manila share driver manila-ui-2.13.0/releasenotes/notes/add-revert-share-to-snapshot-support-cba6227cef75c1a7.yaml000066400000000000000000000001141323215354300316510ustar00rootroot00000000000000--- features: - Added possibility to revert share to its latest snapshot. manila-ui-2.13.0/releasenotes/notes/add-share-panel-group-to-admin-dashboard-ef6a02243c0e776c.yaml000066400000000000000000000010631323215354300321020ustar00rootroot00000000000000--- features: - Admin dashboard now has manila-specific panel group called 'share'. All 'tabs' we had before are panels in this group now. Each panel is loaded in separate page. It allows us to avoid making redundant API calls that we did loading all tabs at once. upgrade: - URLs for resources in admin dashboard were changed. One part of changes is removal of intermediate "shares" part. Example - was - "/admin/shares/share_networks/" became - "/admin/share_networks/" Other part is rename of resource actions to be more alike. manila-ui-2.13.0/releasenotes/notes/add-share-panel-group-to-project-dashboard-722ab48392588728.yaml000066400000000000000000000010731323215354300322030ustar00rootroot00000000000000--- features: - Project dashboard now has manila-specific panel group called 'share'. All 'tabs' we had before are panels in this group now. Each panel is loaded in separate page. It allows us to avoid making redundant API calls that we did loading all tabs at once. upgrade: - URLs for resources in project dashboard were changed. One part of changes is removal of intermediate "shares" part. Example - was - "/project/shares/share_networks/" became - "/project/share_networks/" Other part is rename of resource actions to be more alike. manila-ui-2.13.0/releasenotes/notes/bp-manila-mountable-snapshots-93a732ad0dc95ade.yaml000066400000000000000000000001231323215354300303710ustar00rootroot00000000000000--- features: - Added support for the mountable snapshots feature to manila-ui. manila-ui-2.13.0/releasenotes/notes/bp-ocata-migration-improvements-e0ecccbe95e3c265.yaml000066400000000000000000000002061323215354300310150ustar00rootroot00000000000000--- features: - Added preserve-snapshots option to share migration. fixes: - Updated descriptions of share migration parameters. manila-ui-2.13.0/releasenotes/notes/bug-1619244-1cc15914050d9a64.yaml000066400000000000000000000000721323215354300236300ustar00rootroot00000000000000--- fixes: - Fixed Manage Replicas button availability. manila-ui-2.13.0/releasenotes/notes/bug-1679960-fix-quota-names-overlapping-4277d45cd0110489.yaml000066400000000000000000000002321323215354300311300ustar00rootroot00000000000000--- fixes: - Fixed quota names overlapping with Cinder's quotas. Now it is possible to read/write any manila quotas not messing up Cinder's quotas. bug-1685657-fix-create-share-from-snapshot-form-7f5993c1100ce9b6.yaml000066400000000000000000000003101323215354300325400ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/notes--- fixes: - Fixed form of share creation from snapshot. Before it was losing source snapshot ID in request and was creating share from scratch instead of expected snapshot-sourced variant. manila-ui-2.13.0/releasenotes/notes/start-using-reno-49da440f5e237dda.yaml000066400000000000000000000001151323215354300256710ustar00rootroot00000000000000--- features: - Started using release notes to track changes to manila UI. manila-ui-2.13.0/releasenotes/source/000077500000000000000000000000001323215354300174435ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/_static/000077500000000000000000000000001323215354300210715ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/_static/.placeholder000066400000000000000000000000001323215354300233420ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/_templates/000077500000000000000000000000001323215354300216005ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/_templates/.placeholder000066400000000000000000000000001323215354300240510ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/conf.py000066400000000000000000000216271323215354300207520ustar00rootroot00000000000000# -*- coding: utf-8 -*- # 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. # manila-ui Release Notes documentation build configuration file, # created by sphinx-quickstart on Tue May 24 17:40:50 2016. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ import openstackdocstheme # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'reno.sphinxext', 'openstackdocstheme', ] # openstackdocsthem options repository_name = 'openstack/manila-ui' bug_project = 'manila-ui' bug_tag = 'release notes' html_last_updated_fmt = '%Y-%m-%d %H:%M' # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'manila-ui Release Notes' copyright = u'2016, Manila Developers' # Release notes are version independent release = '' # The short X.Y version. version = '' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'openstackdocs' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = [openstackdocstheme.get_html_theme_path()] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'ManilaUIReleaseNotesdoc' # -- Options for LaTeX output --------------------------------------------- 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': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'ManilaUIReleaseNotes.tex', u'manila-ui Release Notes Documentation', u'Manila Developers', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'manilauireleasenotes', u'manila-ui Release Notes Documentation', [u'Manila Developers'], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'ManilaUIReleaseNotes', u'manila-ui Release Notes Documentation', u'Manila Developers', 'ManilaUIReleaseNotes', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # -- Options for Internationalization output ------------------------------ locale_dirs = ['locale/'] manila-ui-2.13.0/releasenotes/source/index.rst000066400000000000000000000002211323215354300212770ustar00rootroot00000000000000 ======================= manila-ui Release Notes ======================= .. toctree:: :maxdepth: 1 unreleased pike ocata newton manila-ui-2.13.0/releasenotes/source/locale/000077500000000000000000000000001323215354300207025ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/de/000077500000000000000000000000001323215354300212725ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/de/LC_MESSAGES/000077500000000000000000000000001323215354300230575ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/de/LC_MESSAGES/releasenotes.po000066400000000000000000000127771323215354300261260ustar00rootroot00000000000000# Robert Simai , 2016. #zanata # Adriano Perri , 2017. #zanata # Andreas Jaeger , 2017. #zanata # Frank Kloeker , 2017. #zanata # Robert Simai , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui Release Notes 2.10.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-13 14:46+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-10-17 03:39+0000\n" "Last-Translator: Robert Simai \n" "Language-Team: German\n" "Language: de\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" msgid "2.2.0" msgstr "2.2.0" msgid "2.5.1-13" msgstr "2.5.1-13" msgid "2.7.0" msgstr "2.7.0" msgid "2.7.1" msgstr "2.7.1" msgid "2.7.1-10" msgstr "2.7.1-10" msgid "2.8.0" msgstr "2.8.0" msgid "2.9.0" msgstr "2.9.0" msgid "Added native protocol for MapRFS manila share driver" msgstr "Natives Protokoll für den MapRFS Manila Share Driver hinzugefügt" msgid "Added possibility to revert share to its latest snapshot." msgstr "" "Möglichkeit hinzugefügt, um das Share auf die letzte Schattenkopie " "zurückzusetzen." msgid "Added preserve-snapshots option to share migration." msgstr "Preserve-snapshots Option zum Teilen der Migration hinzugefügt." msgid "Added support for the mountable snapshots feature to manila-ui." msgstr "Unterstützung für mountbare Schattenkopien zur Manila UI hinzugefügt." msgid "" "Admin dashboard now has manila-specific panel group called 'share'. All " "'tabs' we had before are panels in this group now. Each panel is loaded in " "separate page. It allows us to avoid making redundant API calls that we did " "loading all tabs at once." msgstr "" "Das Admin Dashboard hat jetzt eine manila-spezifische Panelgruppe " "'Freigabe'. Alle 'Tabs' von vorher sind jetzt Panele in dieser Gruppe. Jedes " "Panel wird mit einer eigenen Seite geladen. Dies erlaubt auf redundante API-" "Aufrufe zu verzichten, die beim gleichzeitigen Laden aller Tabs auftraten." msgid "Bug Fixes" msgstr "Fehlerkorrekturen" msgid "Current Series Release Notes" msgstr "Aktuelle Serie Releasenotes" msgid "Fixed Manage Replicas button availability." msgstr "Verfügbarkeit des Replika Verwalten Buttons gefixt." msgid "" "Fixed form of share creation from snapshot. Before it was losing source " "snapshot ID in request and was creating share from scratch instead of " "expected snapshot-sourced variant." msgstr "" "Feste Form der Freigabeerstellung aus Schattenkopie. Vorher war es in der " "Anfrage eine lose Quell-Schattenkopie-ID und die Freigabe wurden von scratch " "anstatt der erwarteten Quell-Schattenkopie-Variante erstellt." msgid "" "Fixed quota names overlapping with Cinder's quotas. Now it is possible to " "read/write any manila quotas not messing up Cinder's quotas." msgstr "" "Überlappung von Kontingentnamen mit Cinder korrigiert. Es sit jetzt möglich " "beliebige Manila-Kontingente zu lesen/schreiben, ohne die Cinder-Kontingente " "zu zerstören." msgid "New Features" msgstr "Neue Funktionen" msgid "Newton Series Release Notes" msgstr "Newton Serie Releasenotes" msgid "Ocata Series Release Notes" msgstr "Ocata Serie Releasenotes" msgid "Pike Series Release Notes" msgstr "Pike Serie Release Notes" msgid "" "Project dashboard now has manila-specific panel group called 'share'. All " "'tabs' we had before are panels in this group now. Each panel is loaded in " "separate page. It allows us to avoid making redundant API calls that we did " "loading all tabs at once." msgstr "" "Projekt Dashboard hat nun eine manila-spezifische panel Gruppe namens \"share" "\". Alle \"Tabs\", die wir zuvor hatten sind nun panels in dieser Gruppe. " "Jeder panel wird auf einer separaten Seite geladen. Das erlaubt uns " "redundante API Aufrufe, welche wir beim Laden aller Tabs zur selben Zeit " "hatten, zu vermeiden." msgid "Started using release notes to track changes to manila UI." msgstr "" "Es wurde begonnen Releasenotes zu verwenden, um Änderungen der manila UI " "festzuhalten." msgid "" "URLs for resources in admin dashboard were changed. One part of changes is " "removal of intermediate \"shares\" part. Example - was - \"/admin/shares/" "share_networks/\" became - \"/admin/share_networks/\" Other part is rename " "of resource actions to be more alike." msgstr "" "URLs für Resourcen im Admin-Dashboard wurden geändert. Ein Teil der Änderung " "ist das Löschen des mittleren \"Freigabe\"-Teils. Beispiel - aus - \"/admin/" "shares/share_networks/\" wurde - \"/admin/share_networks/\" Ein anderer Teil " "ist das Umbenennen von Resourcen gleichförmiger Aktionen." msgid "" "URLs for resources in project dashboard were changed. One part of changes is " "removal of intermediate \"shares\" part. Example - was - \"/project/shares/" "share_networks/\" became - \"/project/share_networks/\" Other part is rename " "of resource actions to be more alike." msgstr "" "URLs für Resourcen im Admin-Dashboard wurden geändert. Ein Teil der Änderung " "ist das Löschen des mittleren \"Freigabe\"-Teils. Beispiel - aus - \"/admin/" "shares/share_networks/\" wurde - \"/admin/share_networks/\" Ein anderer Teil " "ist das Umbenennen von Resourcen gleichförmiger Aktionen." msgid "Updated descriptions of share migration parameters." msgstr "Beschreibungen zu Parametern für Share Migration hinzugefügt." msgid "Upgrade Notes" msgstr "Aktualisierungsnotizen" msgid "manila-ui Release Notes" msgstr "manila-ui Releasenotes" manila-ui-2.13.0/releasenotes/source/locale/en_GB/000077500000000000000000000000001323215354300216545ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/en_GB/LC_MESSAGES/000077500000000000000000000000001323215354300234415ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po000066400000000000000000000116661323215354300265040ustar00rootroot00000000000000# Andi Chandler , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui Release Notes 2.10.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-09 05:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-10-09 07:41+0000\n" "Last-Translator: Andi Chandler \n" "Language-Team: English (United Kingdom)\n" "Language: en-GB\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" msgid "2.2.0" msgstr "2.2.0" msgid "2.5.1-13" msgstr "2.5.1-13" msgid "2.7.0" msgstr "2.7.0" msgid "2.7.1" msgstr "2.7.1" msgid "2.7.1-10" msgstr "2.7.1-10" msgid "2.8.0" msgstr "2.8.0" msgid "2.9.0" msgstr "2.9.0" msgid "Added native protocol for MapRFS manila share driver" msgstr "Added native protocol for MapRFS Manila share driver" msgid "Added possibility to revert share to its latest snapshot." msgstr "Added possibility to revert share to its latest snapshot." msgid "Added preserve-snapshots option to share migration." msgstr "Added preserve-snapshots option to share migration." msgid "Added support for the mountable snapshots feature to manila-ui." msgstr "Added support for the mountable snapshots feature to Manila-UI." msgid "" "Admin dashboard now has manila-specific panel group called 'share'. All " "'tabs' we had before are panels in this group now. Each panel is loaded in " "separate page. It allows us to avoid making redundant API calls that we did " "loading all tabs at once." msgstr "" "Admin dashboard now has manila-specific panel group called 'share'. All " "'tabs' we had before are panels in this group now. Each panel is loaded in " "separate page. It allows us to avoid making redundant API calls that we did " "loading all tabs at once." msgid "Bug Fixes" msgstr "Bug Fixes" msgid "Current Series Release Notes" msgstr "Current Series Release Notes" msgid "Fixed Manage Replicas button availability." msgstr "Fixed Manage Replicas button availability." msgid "" "Fixed form of share creation from snapshot. Before it was losing source " "snapshot ID in request and was creating share from scratch instead of " "expected snapshot-sourced variant." msgstr "" "Fixed form of share creation from snapshot. Before it was losing source " "snapshot ID in request and was creating share from scratch instead of " "expected snapshot-sourced variant." msgid "" "Fixed quota names overlapping with Cinder's quotas. Now it is possible to " "read/write any manila quotas not messing up Cinder's quotas." msgstr "" "Fixed quota names overlapping with Cinder's quotas. Now it is possible to " "read/write any Manila quotas not messing up Cinder's quotas." msgid "New Features" msgstr "New Features" msgid "Newton Series Release Notes" msgstr "Newton Series Release Notes" msgid "Ocata Series Release Notes" msgstr "Ocata Series Release Notes" msgid "Pike Series Release Notes" msgstr "Pike Series Release Notes" msgid "" "Project dashboard now has manila-specific panel group called 'share'. All " "'tabs' we had before are panels in this group now. Each panel is loaded in " "separate page. It allows us to avoid making redundant API calls that we did " "loading all tabs at once." msgstr "" "Project dashboard now has manila-specific panel group called 'share'. All " "'tabs' we had before are panels in this group now. Each panel is loaded in " "separate page. It allows us to avoid making redundant API calls that we did " "loading all tabs at once." msgid "Started using release notes to track changes to manila UI." msgstr "Started using release notes to track changes to Manila UI." msgid "" "URLs for resources in admin dashboard were changed. One part of changes is " "removal of intermediate \"shares\" part. Example - was - \"/admin/shares/" "share_networks/\" became - \"/admin/share_networks/\" Other part is rename " "of resource actions to be more alike." msgstr "" "URLs for resources in admin dashboard were changed. One part of changes is " "removal of intermediate \"shares\" part. Example - was - \"/admin/shares/" "share_networks/\" became - \"/admin/share_networks/\" Other part is rename " "of resource actions to be more alike." msgid "" "URLs for resources in project dashboard were changed. One part of changes is " "removal of intermediate \"shares\" part. Example - was - \"/project/shares/" "share_networks/\" became - \"/project/share_networks/\" Other part is rename " "of resource actions to be more alike." msgstr "" "URLs for resources in project dashboard were changed. One part of changes is " "removal of intermediate \"shares\" part. Example - was - \"/project/shares/" "share_networks/\" became - \"/project/share_networks/\" Other part is rename " "of resource actions to be more alike." msgid "Updated descriptions of share migration parameters." msgstr "Updated descriptions of share migration parameters." msgid "Upgrade Notes" msgstr "Upgrade Notes" msgid "manila-ui Release Notes" msgstr "Manila-UI Release Notes" manila-ui-2.13.0/releasenotes/source/locale/fr/000077500000000000000000000000001323215354300213115ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/fr/LC_MESSAGES/000077500000000000000000000000001323215354300230765ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po000066400000000000000000000017421323215354300261330ustar00rootroot00000000000000# Gérald LONLAS , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui Release Notes 2.5.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-10-21 10:01+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2016-10-22 05:30+0000\n" "Last-Translator: Gérald LONLAS \n" "Language-Team: French\n" "Language: fr\n" "X-Generator: Zanata 3.7.3\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" msgid "2.2.0" msgstr "2.2.0" msgid "Current Series Release Notes" msgstr "Note de la release actuelle" msgid "New Features" msgstr "Nouvelles fonctionnalités" msgid "Newton Series Release Notes" msgstr "Note de release pour Newton" msgid "Started using release notes to track changes to manila UI." msgstr "" "Commence à utiliser les notes de Release pour suivre les changements de " "manila UI." msgid "manila-ui Release Notes" msgstr "Note de release de manila-ui" manila-ui-2.13.0/releasenotes/source/locale/id/000077500000000000000000000000001323215354300212765ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/id/LC_MESSAGES/000077500000000000000000000000001323215354300230635ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/id/LC_MESSAGES/releasenotes.po000066400000000000000000000125231323215354300261170ustar00rootroot00000000000000# suhartono , 2016. #zanata # suhartono , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui Release Notes 2.10.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-09 05:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-10-11 01:28+0000\n" "Last-Translator: suhartono \n" "Language-Team: Indonesian\n" "Language: id\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=1; plural=0\n" msgid "2.2.0" msgstr "2.2.0" msgid "2.5.1-13" msgstr "2.5.1-13" msgid "2.7.0" msgstr "2.7.0" msgid "2.7.1" msgstr "2.7.1" msgid "2.7.1-10" msgstr "2.7.1-10" msgid "2.8.0" msgstr "2.8.0" msgid "2.9.0" msgstr "2.9.0" msgid "Added native protocol for MapRFS manila share driver" msgstr "Ditambahkan protokol asli (native) untuk MapRFS manila share driver" msgid "Added possibility to revert share to its latest snapshot." msgstr "" "Ditambahkan kemungkinan untuk kembali share dengan snapshot terbarunya." msgid "Added preserve-snapshots option to share migration." msgstr "Ditambahkan opsi preserve-snapshots untuk berbagi migrasi." msgid "Added support for the mountable snapshots feature to manila-ui." msgstr "" "Dukungan yang ditambahkan untuk fitur mountable snapshots untuk manila-ui." msgid "" "Admin dashboard now has manila-specific panel group called 'share'. All " "'tabs' we had before are panels in this group now. Each panel is loaded in " "separate page. It allows us to avoid making redundant API calls that we did " "loading all tabs at once." msgstr "" "Dasbor admin sekarang memiliki grup panel khusus manila yang disebut " "'share'. Semua 'tab' yang kami miliki sebelumnya adalah panel dalam grup ini " "sekarang. Setiap panel dimuat di halaman terpisah. Ini memungkinkan kita " "untuk menghindari pembuatan API yang berlebihan sehingga kita dapat " "melakukan pemuatan semua tab sekaligus." msgid "Bug Fixes" msgstr "Bug Fixes" msgid "Current Series Release Notes" msgstr "Current Series Release Notes (catatan rilis seri Current)" msgid "Fixed Manage Replicas button availability." msgstr "Fixed Manage Replicas button availability." msgid "" "Fixed form of share creation from snapshot. Before it was losing source " "snapshot ID in request and was creating share from scratch instead of " "expected snapshot-sourced variant." msgstr "" "Bentuk tetap pembuatan share dari snapshot. Sebelum kehilangan ID snapshot " "sumber dalam permintaan dan menciptakan share dari awal bukan varian " "snapshot yang diharapkan." msgid "" "Fixed quota names overlapping with Cinder's quotas. Now it is possible to " "read/write any manila quotas not messing up Cinder's quotas." msgstr "" "Nama kuota tetap tumpang tindih dengan kuota Cinder. Sekarang mungkin untuk " "membaca / menulis setiap kuota manila yang tidak mengacaukan kuota Cinder." msgid "New Features" msgstr "New Features (fitur baru)" msgid "Newton Series Release Notes" msgstr "Newton Series Release Notes (catatan rilis seri Newton)" msgid "Ocata Series Release Notes" msgstr "Ocata Series Release Notes" msgid "Pike Series Release Notes" msgstr "Catatan Rilis Seri Pike" msgid "" "Project dashboard now has manila-specific panel group called 'share'. All " "'tabs' we had before are panels in this group now. Each panel is loaded in " "separate page. It allows us to avoid making redundant API calls that we did " "loading all tabs at once." msgstr "" "Dashboard proyek sekarang memiliki kelompok panel khusus manila yang disebut " "'share'. Semua 'tab' yang kami miliki sebelumnya adalah panel dalam grup ini " "sekarang. Setiap panel dimuat di halaman terpisah. Ini memungkinkan kita " "untuk menghindari pembuatan API yang berlebihan sehingga kita dapat " "melakukan pemuatan semua tab sekaligus." msgid "Started using release notes to track changes to manila UI." msgstr "Mulai menggunakan catatan rilis untuk melacak perubahan manila UI." msgid "" "URLs for resources in admin dashboard were changed. One part of changes is " "removal of intermediate \"shares\" part. Example - was - \"/admin/shares/" "share_networks/\" became - \"/admin/share_networks/\" Other part is rename " "of resource actions to be more alike." msgstr "" "URL untuk sumber daya di dasbor admin telah diubah. Salah satu bagian dari " "perubahan adalah penghapusan bagian \"shares\" perantara. Contoh - was - \"/" "admin/shares/share_networks/\" menjadi - \"/admin/share_networks/\" Bagian " "lainnya adalah mengubah nama tindakan sumber daya menjadi lebih mirip." msgid "" "URLs for resources in project dashboard were changed. One part of changes is " "removal of intermediate \"shares\" part. Example - was - \"/project/shares/" "share_networks/\" became - \"/project/share_networks/\" Other part is rename " "of resource actions to be more alike." msgstr "" "URL untuk sumber daya di dasbor proyek telah diubah. Salah satu bagian dari " "perubahan adalah penghapusan bagian \"shares\" perantara. Contoh- was - \"/" "project/shares/share_networks/\" menjadi - \"/project/share_networks/\" " "Bagian lainnya adalah mengubah nama tindakan sumber daya menjadi lebih mirip." msgid "Updated descriptions of share migration parameters." msgstr "Diperbarui deskripsi parameter share migration." msgid "Upgrade Notes" msgstr "Catatan Upgrade" msgid "manila-ui Release Notes" msgstr "Catatan rilis manila-ui " manila-ui-2.13.0/releasenotes/source/locale/ja/000077500000000000000000000000001323215354300212745ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/ja/LC_MESSAGES/000077500000000000000000000000001323215354300230615ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/ja/LC_MESSAGES/releasenotes.po000066400000000000000000000016411323215354300261140ustar00rootroot00000000000000# Shu Muto , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui Release Notes 2.7.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-03-21 16:11+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2016-06-16 05:49+0000\n" "Last-Translator: Shu Muto \n" "Language-Team: Japanese\n" "Language: ja\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=1; plural=0\n" msgid "2.2.0" msgstr "2.2.0" msgid "Current Series Release Notes" msgstr "開発中バージョンのリリースノート" msgid "New Features" msgstr "新機能" msgid "Started using release notes to track changes to manila UI." msgstr "Manila UI の変更を追跡するため、リリースノートの使用を開始しました。" msgid "manila-ui Release Notes" msgstr "Manila UI リリースノート" manila-ui-2.13.0/releasenotes/source/locale/ko_KR/000077500000000000000000000000001323215354300217075ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/ko_KR/LC_MESSAGES/000077500000000000000000000000001323215354300234745ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/ko_KR/LC_MESSAGES/releasenotes.po000066400000000000000000000026271323215354300265340ustar00rootroot00000000000000# Ian Y. Choi , 2016. #zanata # minwook-shin , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui Release Notes 2.10.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-09-23 01:14+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-08-16 07:50+0000\n" "Last-Translator: minwook-shin \n" "Language-Team: Korean (South Korea)\n" "Language: ko-KR\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=1; plural=0\n" msgid "2.2.0" msgstr "2.2.0" msgid "2.5.1-13" msgstr "2.5.1-13" msgid "2.7.0" msgstr "2.7.0" msgid "2.7.1" msgstr "2.7.1" msgid "2.8.0" msgstr "2.8.0" msgid "2.9.0" msgstr "2.9.0" msgid "Bug Fixes" msgstr "버그 수정" msgid "Current Series Release Notes" msgstr "현재 시리즈에 대한 릴리즈 노트" msgid "New Features" msgstr "새로운 기능" msgid "Newton Series Release Notes" msgstr "Newton 시리즈에 대한 릴리즈 노트" msgid "Ocata Series Release Notes" msgstr "Ocata 시리즈에 대한 릴리즈 노트" msgid "Started using release notes to track changes to manila UI." msgstr "" "manilla UI 변경 사항을 추적하기 위해 릴리즈 노트 사용을 시작하였습니다." msgid "Upgrade Notes" msgstr "업그레이드 노트" msgid "manila-ui Release Notes" msgstr "manila-ui 릴리즈 노트" manila-ui-2.13.0/releasenotes/source/locale/zh_CN/000077500000000000000000000000001323215354300217035ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/zh_CN/LC_MESSAGES/000077500000000000000000000000001323215354300234705ustar00rootroot00000000000000manila-ui-2.13.0/releasenotes/source/locale/zh_CN/LC_MESSAGES/releasenotes.po000066400000000000000000000035351323215354300265270ustar00rootroot00000000000000# linlin <469923498@qq.com>, 2016. #zanata # sunanchen , 2016. #zanata # Bin , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: manila-ui Release Notes 2.10.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-08-26 15:43+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-07-27 03:57+0000\n" "Last-Translator: Bin \n" "Language-Team: Chinese (China)\n" "Language: zh-CN\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=1; plural=0\n" msgid "2.2.0" msgstr "2.2.0版本" msgid "2.7.0" msgstr "2.7.0" msgid "2.7.1" msgstr "2.7.1" msgid "2.8.0" msgstr "2.8.0" msgid "2.9.0" msgstr "2.9.0" msgid "Added native protocol for MapRFS manila share driver" msgstr "为MapPFS的manila共享驱动添加本地协议。" msgid "Added possibility to revert share to its latest snapshot." msgstr "增加了将共享恢复到其最新快照的可能性。" msgid "Added preserve-snapshots option to share migration." msgstr "增加了共享迁移的保持快照选项。" msgid "Added support for the mountable snapshots feature to manila-ui." msgstr "增加了对manila-ui的可挂载快照特征支持。" msgid "Bug Fixes" msgstr "Bug修复" msgid "Current Series Release Notes" msgstr "当前版本发布说明" msgid "New Features" msgstr "新特性" msgid "Newton Series Release Notes" msgstr "Newton版本发布说明" msgid "Ocata Series Release Notes" msgstr "Ocata版本发布说明" msgid "Started using release notes to track changes to manila UI." msgstr "开始使用释放注释来追踪manila UI。" msgid "Updated descriptions of share migration parameters." msgstr "更新共享迁移参数的描述。" msgid "Upgrade Notes" msgstr "升级说明" msgid "manila-ui Release Notes" msgstr "manila-ui发布说明" manila-ui-2.13.0/releasenotes/source/newton.rst000066400000000000000000000002321323215354300215040ustar00rootroot00000000000000=================================== Newton Series Release Notes =================================== .. release-notes:: :branch: origin/stable/newton manila-ui-2.13.0/releasenotes/source/ocata.rst000066400000000000000000000002301323215354300212570ustar00rootroot00000000000000=================================== Ocata Series Release Notes =================================== .. release-notes:: :branch: origin/stable/ocata manila-ui-2.13.0/releasenotes/source/pike.rst000066400000000000000000000001751323215354300211300ustar00rootroot00000000000000========================== Pike Series Release Notes ========================== .. release-notes:: :branch: stable/pike manila-ui-2.13.0/releasenotes/source/unreleased.rst000066400000000000000000000001531323215354300223230ustar00rootroot00000000000000============================ Current Series Release Notes ============================ .. release-notes:: manila-ui-2.13.0/requirements.txt000066400000000000000000000007711323215354300167430ustar00rootroot00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. pbr!=2.1.0,>=2.0.0 # Apache-2.0 # Horizon Core Requirements Babel!=2.4.0,>=2.3.4 # BSD Django<2.0,>=1.8 # BSD django-compressor>=2.0 # MIT iso8601>=0.1.11 # MIT oslo.utils>=3.33.0 # Apache-2.0 python-keystoneclient>=3.8.0 # Apache-2.0 python-manilaclient>=1.16.0 # Apache-2.0 six>=1.10.0 # MIT manila-ui-2.13.0/run_tests.sh000077500000000000000000000377351323215354300160560ustar00rootroot00000000000000#!/bin/bash set -o errexit function usage { echo "Usage: $0 [OPTION]..." echo "Run Horizon's test suite(s)" echo "" echo " -V, --virtual-env Always use virtualenv. Install automatically" echo " if not present" echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local" echo " environment" echo " -c, --coverage Generate reports using Coverage" echo " -f, --force Force a clean re-build of the virtual" echo " environment. Useful when dependencies have" echo " been added." echo " -m, --manage Run a Django management command." echo " --makemessages Create/Update English translation files." echo " --compilemessages Compile all translation files." echo " --check-only Do not update translation files (--makemessages only)." echo " --pseudo Pseudo translate a language." echo " -p, --pep8 Just run pep8" echo " -8, --pep8-changed []" echo " Just run PEP8 and HACKING compliance check" echo " on files changed since HEAD~1 (or )" echo " -P, --no-pep8 Don't run pep8 by default" echo " -t, --tabs Check for tab characters in files." echo " -y, --pylint Just run pylint" echo " -q, --quiet Run non-interactively. (Relatively) quiet." echo " Implies -V if -N is not set." echo " --only-selenium Run only the Selenium unit tests" echo " --with-selenium Run unit tests including Selenium tests" echo " --selenium-headless Run Selenium tests headless" echo " --integration Run the integration tests (requires a running " echo " OpenStack environment)" echo " --runserver Run the Django development server for" echo " openstack_dashboard in the virtual" echo " environment." echo " --docs Just build the documentation" echo " --backup-environment Make a backup of the environment on exit" echo " --restore-environment Restore the environment before running" echo " --destroy-environment Destroy the environment and exit" echo " -h, --help Print this usage message" echo "" echo "Note: with no options specified, the script will try to run the tests in" echo " a virtual environment, If no virtualenv is found, the script will ask" echo " if you would like to create one. If you prefer to run tests NOT in a" echo " virtual environment, simply pass the -N option." exit } # DEFAULTS FOR RUN_TESTS.SH # root=`pwd -P` venv=$root/.venv venv_env_version=$venv/environments with_venv=tools/with_venv.sh included_dirs="manila_ui" always_venv=0 backup_env=0 command_wrapper="" destroy=0 force=0 just_pep8=0 just_pep8_changed=0 no_pep8=0 just_pylint=0 just_docs=0 just_tabs=0 never_venv=0 quiet=0 restore_env=0 runserver=0 only_selenium=0 with_selenium=0 selenium_headless=0 integration=0 testopts="" testargs="" with_coverage=0 makemessages=0 compilemessages=0 check_only=0 pseudo=0 manage=0 # Jenkins sets a "JOB_NAME" variable, if it's not set, we'll make it "default" [ "$JOB_NAME" ] || JOB_NAME="default" function process_option { # If running manage command, treat the rest of options as arguments. if [ $manage -eq 1 ]; then testargs="$testargs $1" return 0 fi case "$1" in -h|--help) usage;; -V|--virtual-env) always_venv=1; never_venv=0;; -N|--no-virtual-env) always_venv=0; never_venv=1;; -p|--pep8) just_pep8=1;; -8|--pep8-changed) just_pep8_changed=1;; -P|--no-pep8) no_pep8=1;; -y|--pylint) just_pylint=1;; -f|--force) force=1;; -t|--tabs) just_tabs=1;; -q|--quiet) quiet=1;; -c|--coverage) with_coverage=1;; -m|--manage) manage=1;; --makemessages) makemessages=1;; --compilemessages) compilemessages=1;; --check-only) check_only=1;; --pseudo) pseudo=1;; --only-selenium) only_selenium=1;; --with-selenium) with_selenium=1;; --selenium-headless) selenium_headless=1;; --integration) integration=1;; --docs) just_docs=1;; --runserver) runserver=1;; --backup-environment) backup_env=1;; --restore-environment) restore_env=1;; --destroy-environment) destroy=1;; -*) testopts="$testopts $1";; *) testargs="$testargs $1" esac } function run_management_command { ${command_wrapper} python $root/manage.py $testopts $testargs } function run_server { echo "Starting Django development server..." ${command_wrapper} python $root/manage.py runserver $testopts $testargs echo "Server stopped." } function run_pylint { echo "Running pylint ..." PYTHONPATH=$root ${command_wrapper} pylint --rcfile=.pylintrc -f parseable $included_dirs > pylint.txt || true CODE=$? grep Global -A2 pylint.txt if [ $CODE -lt 32 ]; then echo "Completed successfully." exit 0 else echo "Completed with problems." exit $CODE fi } function warn_on_flake8_without_venv { set +o errexit ${command_wrapper} python -c "import hacking" 2>/dev/null no_hacking=$? set -o errexit if [ $never_venv -eq 1 -a $no_hacking -eq 1 ]; then echo "**WARNING**:" >&2 echo "OpenStack hacking is not installed on your host. Its detection will be missed." >&2 echo "Please install or use virtual env if you need OpenStack hacking detection." >&2 fi } function run_pep8 { echo "Running flake8 ..." warn_on_flake8_without_venv DJANGO_SETTINGS_MODULE=manila_ui.tests.settings ${command_wrapper} flake8 } function run_pep8_changed { # NOTE(gilliard) We want use flake8 to check the entirety of every file that has # a change in it. Unfortunately the --filenames argument to flake8 only accepts # file *names* and there are no files named (eg) "nova/compute/manager.py". The # --diff argument behaves surprisingly as well, because although you feed it a # diff, it actually checks the file on disk anyway. local base_commit=${testargs:-HEAD~1} files=$(git diff --name-only $base_commit | tr '\n' ' ') echo "Running flake8 on ${files}" warn_on_flake8_without_venv diff -u --from-file /dev/null ${files} | DJANGO_SETTINGS_MODULE=manila_ui.tests.settings ${command_wrapper} flake8 --diff exit } function run_sphinx { echo "Building sphinx..." DJANGO_SETTINGS_MODULE=manila_ui.tests.settings ${command_wrapper} python setup.py build_sphinx echo "Build complete." } function tab_check { TAB_VIOLATIONS=`find $included_dirs -type f -regex ".*\.\(css\|js\|py\|html\)" -print0 | xargs -0 awk '/\t/' | wc -l` if [ $TAB_VIOLATIONS -gt 0 ]; then echo "TABS! $TAB_VIOLATIONS of them! Oh no!" HORIZON_FILES=`find $included_dirs -type f -regex ".*\.\(css\|js\|py|\html\)"` for TABBED_FILE in $HORIZON_FILES do TAB_COUNT=`awk '/\t/' $TABBED_FILE | wc -l` if [ $TAB_COUNT -gt 0 ]; then echo "$TABBED_FILE: $TAB_COUNT" fi done fi return $TAB_VIOLATIONS; } function destroy_venv { echo "Cleaning environment..." echo "Removing virtualenv..." rm -rf $venv echo "Virtualenv removed." } function environment_check { echo "Checking environment." if [ -f $venv_env_version ]; then set +o errexit cat requirements.txt test-requirements.txt | cmp $venv_env_version - > /dev/null local env_check_result=$? set -o errexit if [ $env_check_result -eq 0 ]; then # If the environment exists and is up-to-date then set our variables command_wrapper="${root}/${with_venv}" echo "Environment is up to date." return 0 fi fi if [ $always_venv -eq 1 ]; then install_venv else if [ ! -e ${venv} ]; then echo -e "Environment not found. Install? (Y/n) \c" else echo -e "Your environment appears to be out of date. Update? (Y/n) \c" fi read update_env if [ "x$update_env" = "xY" -o "x$update_env" = "x" -o "x$update_env" = "xy" ]; then install_venv else # Set our command wrapper anyway. command_wrapper="${root}/${with_venv}" fi fi } function sanity_check { # Anything that should be determined prior to running the tests, server, etc. # Don't sanity-check anything environment-related in -N flag is set if [ $never_venv -eq 0 ]; then if [ ! -e ${venv} ]; then echo "Virtualenv not found at $venv. Did install_venv.py succeed?" exit 1 fi fi # Remove .pyc files. This is sanity checking because they can linger # after old files are deleted. find . -name "*.pyc" -exec rm -rf {} \; } function backup_environment { if [ $backup_env -eq 1 ]; then echo "Backing up environment \"$JOB_NAME\"..." if [ ! -e ${venv} ]; then echo "Environment not installed. Cannot back up." return 0 fi if [ -d /tmp/.horizon_environment/$JOB_NAME ]; then mv /tmp/.horizon_environment/$JOB_NAME /tmp/.horizon_environment/$JOB_NAME.old rm -rf /tmp/.horizon_environment/$JOB_NAME fi mkdir -p /tmp/.horizon_environment/$JOB_NAME cp -r $venv /tmp/.horizon_environment/$JOB_NAME/ # Remove the backup now that we've completed successfully rm -rf /tmp/.horizon_environment/$JOB_NAME.old echo "Backup completed" fi } function restore_environment { if [ $restore_env -eq 1 ]; then echo "Restoring environment from backup..." if [ ! -d /tmp/.horizon_environment/$JOB_NAME ]; then echo "No backup to restore from." return 0 fi cp -r /tmp/.horizon_environment/$JOB_NAME/.venv ./ || true echo "Environment restored successfully." fi } function install_venv { # Install with install_venv.py export PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE-/tmp/.pip_download_cache} export PIP_USE_MIRRORS=true if [ $quiet -eq 1 ]; then export PIP_NO_INPUT=true fi echo "Fetching new src packages..." rm -rf $venv/src python tools/install_venv.py command_wrapper="$root/${with_venv}" # Make sure it worked and record the environment version sanity_check chmod -R 754 $venv cat requirements.txt test-requirements.txt > $venv_env_version } function run_tests { sanity_check if [ $with_selenium -eq 1 ]; then export WITH_SELENIUM=1 elif [ $only_selenium -eq 1 ]; then export WITH_SELENIUM=1 export SKIP_UNITTESTS=1 fi if [ $selenium_headless -eq 1 ]; then export SELENIUM_HEADLESS=1 fi if [ -z "$testargs" ]; then run_tests_all else run_tests_subset fi } function run_tests_subset { project=`echo $testargs | awk -F. '{print $1}'` ${command_wrapper} python $root/manage.py test --settings=$project.tests.settings $testopts $testargs } function run_tests_all { echo "Running Manila-UI application tests" export NOSE_XUNIT_FILE=manila_ui/nosetests.xml if [ "$NOSE_WITH_HTML_OUTPUT" = '1' ]; then export NOSE_HTML_OUT_FILE='manila_ui_nose_results.html' fi if [ $with_coverage -eq 1 ]; then ${command_wrapper} python -m coverage.__main__ erase coverage_run="python -m coverage.__main__ run -p" fi ${command_wrapper} ${coverage_run} $root/manage.py test manila_ui --settings=manila_ui.tests.settings $testopts # get results of the Horizon tests MANILA_UI_RESULT=$? if [ $with_coverage -eq 1 ]; then echo "Generating coverage reports" ${command_wrapper} python -m coverage.__main__ combine ${command_wrapper} python -m coverage.__main__ xml -i --omit='/usr*,setup.py,*egg*,.venv/*' ${command_wrapper} python -m coverage.__main__ html -i --omit='/usr*,setup.py,*egg*,.venv/*' -d reports fi # Remove the leftover coverage files from the -p flag earlier. rm -f .coverage.* PEP8_RESULT=0 if [ $no_pep8 -eq 0 ] && [ $only_selenium -eq 0 ]; then run_pep8 PEP8_RESULT=$? fi TEST_RESULT=$(($MANILA_UI_RESULT || $PEP8_RESULT)) if [ $TEST_RESULT -eq 0 ]; then echo "Tests completed successfully." else echo "Tests failed." fi exit $TEST_RESULT } function run_integration_tests { export INTEGRATION_TESTS=1 if [ $selenium_headless -eq 1 ]; then export SELENIUM_HEADLESS=1 fi echo "Running Horizon integration tests..." if [ -z "$testargs" ]; then ${command_wrapper} nosetests openstack_dashboard/test/integration_tests/tests else ${command_wrapper} nosetests $testargs fi exit 0 } function run_makemessages { OPTS="-l en --no-obsolete --settings=openstack_dashboard.test.settings" DASHBOARD_OPTS="--extension=html,txt,csv --ignore=openstack" echo -n "horizon: " cd horizon ${command_wrapper} $root/manage.py makemessages $OPTS HORIZON_PY_RESULT=$? echo -n "horizon javascript: " ${command_wrapper} $root/manage.py makemessages -d djangojs $OPTS HORIZON_JS_RESULT=$? echo -n "openstack_dashboard: " cd ../openstack_dashboard ${command_wrapper} $root/manage.py makemessages $DASHBOARD_OPTS $OPTS DASHBOARD_RESULT=$? cd .. if [ $check_only -eq 1 ]; then git checkout -- horizon/locale/en/LC_MESSAGES/django*.po git checkout -- openstack_dashboard/locale/en/LC_MESSAGES/django.po fi exit $(($HORIZON_PY_RESULT || $HORIZON_JS_RESULT || $DASHBOARD_RESULT)) } function run_compilemessages { OPTS="--settings=openstack_dashboard.test.settings" cd horizon ${command_wrapper} $root/manage.py compilemessages $OPTS HORIZON_PY_RESULT=$? cd ../openstack_dashboard ${command_wrapper} $root/manage.py compilemessages $OPTS DASHBOARD_RESULT=$? cd .. # English is the source language, so compiled catalogs are unnecessary. rm -vf horizon/locale/en/LC_MESSAGES/django*.mo rm -vf openstack_dashboard/locale/en/LC_MESSAGES/django.mo exit $(($HORIZON_PY_RESULT || $DASHBOARD_RESULT)) } function run_pseudo { for lang in $testargs # Use English po file as the source file/pot file just like real Horizon translations do ${command_wrapper} $root/tools/pseudo.py openstack_dashboard/locale/en/LC_MESSAGES/django.po openstack_dashboard/locale/$lang/LC_MESSAGES/django.po $lang ${command_wrapper} $root/tools/pseudo.py horizon/locale/en/LC_MESSAGES/django.po horizon/locale/$lang/LC_MESSAGES/django.po $lang ${command_wrapper} $root/tools/pseudo.py horizon/locale/en/LC_MESSAGES/djangojs.po horizon/locale/$lang/LC_MESSAGES/djangojs.po $lang done exit $? } # ---------PREPARE THE ENVIRONMENT------------ # # PROCESS ARGUMENTS, OVERRIDE DEFAULTS for arg in "$@"; do process_option $arg done if [ $quiet -eq 1 ] && [ $never_venv -eq 0 ] && [ $always_venv -eq 0 ] then always_venv=1 fi # If destroy is set, just blow it away and exit. if [ $destroy -eq 1 ]; then destroy_venv exit 0 fi # Ignore all of this if the -N flag was set if [ $never_venv -eq 0 ]; then # Restore previous environment if desired if [ $restore_env -eq 1 ]; then restore_environment fi # Remove the virtual environment if --force used if [ $force -eq 1 ]; then destroy_venv fi # Then check if it's up-to-date environment_check # Create a backup of the up-to-date environment if desired if [ $backup_env -eq 1 ]; then backup_environment fi fi # ---------EXERCISE THE CODE------------ # # Run management commands if [ $manage -eq 1 ]; then run_management_command exit $? fi # Build the docs if [ $just_docs -eq 1 ]; then run_sphinx exit $? fi # Update translation files if [ $makemessages -eq 1 ]; then run_makemessages exit $? fi # Compile translation files if [ $compilemessages -eq 1 ]; then run_compilemessages exit $? fi # Generate Pseudo translation if [ $pseudo -eq 1 ]; then run_pseudo exit $? fi # PEP8 if [ $just_pep8 -eq 1 ]; then run_pep8 exit $? fi if [ $just_pep8_changed -eq 1 ]; then run_pep8_changed exit $? fi # Pylint if [ $just_pylint -eq 1 ]; then run_pylint exit $? fi # Tab checker if [ $just_tabs -eq 1 ]; then tab_check exit $? fi # Integration tests if [ $integration -eq 1 ]; then run_integration_tests exit $? fi # Django development server if [ $runserver -eq 1 ]; then run_server exit $? fi # Full test suite run_tests || exit manila-ui-2.13.0/setup.cfg000066400000000000000000000014611323215354300152750ustar00rootroot00000000000000[metadata] name = manila-ui summary = Manila Management Dashboard description-file = README.rst author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = http://launchpad.net/manila-ui classifier = 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 :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.4 [files] packages = manila_ui [build_sphinx] source-dir = doc/source build-dir = doc/build all_files = 1 warning-is-error = 1 [upload_sphinx] upload-dir = doc/build/html manila-ui-2.13.0/setup.py000066400000000000000000000020061323215354300151620ustar00rootroot00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # 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. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. # solution from: http://bugs.python.org/issue15881#msg170215 try: import multiprocessing # noqa except ImportError: pass setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) manila-ui-2.13.0/test-requirements.txt000066400000000000000000000012241323215354300177120ustar00rootroot00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -e git://github.com/openstack/horizon.git#egg=horizon hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 ddt>=1.0.1 # MIT django-nose>=1.4.4 # BSD mock>=2.0.0 # BSD mox3>=0.20.0 # Apache-2.0 python-subunit>=1.0.0 # Apache-2.0/BSD sphinx!=1.6.6,>=1.6.2 # BSD openstackdocstheme>=1.17.0 # Apache-2.0 testrepository>=0.0.18 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD testtools>=2.2.0 # MIT reno>=2.5.0 # Apache-2.0 manila-ui-2.13.0/tools/000077500000000000000000000000001323215354300146125ustar00rootroot00000000000000manila-ui-2.13.0/tools/cover.sh000077500000000000000000000045331323215354300162740ustar00rootroot00000000000000#!/bin/bash # # 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. ALLOWED_EXTRA_MISSING=4 TESTR_ARGS="$*" show_diff () { head -1 $1 diff -U 0 $1 $2 | sed 1,2d } # # Stash uncommitted changes, checkout master and save coverage report uncommitted=$(git status --porcelain | grep -v "^??") [[ -n $uncommitted ]] && git stash > /dev/null git checkout HEAD^ baseline_report=$(mktemp -t manila_coverageXXXXXXX) find . -type f -name "*.pyc" -delete && ./run_tests.sh -N --coverage --no-pep8 $TESTR_ARGS coverage report > $baseline_report baseline_missing=$(awk 'END { print $3 }' $baseline_report) # Checkout back and unstash uncommitted changes (if any) git checkout - [[ -n $uncommitted ]] && git stash pop > /dev/null # Generate and save coverage report current_report=$(mktemp -t manila_coverageXXXXXXX) find . -type f -name "*.pyc" -delete && ./run_tests.sh -N --coverage --no-pep8 $TESTR_ARGS coverage report > $current_report current_missing=$(awk 'END { print $3 }' $current_report) # Show coverage details allowed_missing=$((baseline_missing+ALLOWED_EXTRA_MISSING)) echo "Allowed to introduce missing lines : ${ALLOWED_EXTRA_MISSING}" echo "Missing lines in master : ${baseline_missing}" echo "Missing lines in proposed change : ${current_missing}" if [ $allowed_missing -gt $current_missing ]; then if [ $baseline_missing -lt $current_missing ]; then show_diff $baseline_report $current_report echo "I believe you can cover all your code with 100% coverage!" else echo "Thank you! You are awesome! Keep writing unit tests! :)" fi exit_code=0 else show_diff $baseline_report $current_report echo "Please write more unit tests, we should keep our test coverage :( " exit_code=1 fi rm $baseline_report $current_report exit $exit_code manila-ui-2.13.0/tools/install_venv.py000066400000000000000000000117131323215354300176730ustar00rootroot00000000000000# Copyright 2012 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # Copyright 2012 OpenStack, LLC # # Copyright 2012 Nebula, Inc. # # 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. """ Installation script for the OpenStack Dashboard development virtualenv. """ import os import subprocess import sys ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) VENV = os.path.join(ROOT, '.venv') WITH_VENV = os.path.join(ROOT, 'tools', 'with_venv.sh') PIP_REQUIRES = os.path.join(ROOT, 'requirements.txt') TEST_REQUIRES = os.path.join(ROOT, 'test-requirements.txt') def die(message, *args): print >> sys.stderr, message % args sys.exit(1) def run_command(cmd, redirect_output=True, check_exit_code=True, cwd=ROOT, die_message=None): """ Runs a command in an out-of-process shell, returning the output of that command. Working directory is ROOT. """ if redirect_output: stdout = subprocess.PIPE else: stdout = None proc = subprocess.Popen(cmd, cwd=cwd, stdout=stdout) output = proc.communicate()[0] if check_exit_code and proc.returncode != 0: if die_message is None: die('Command "%s" failed.\n%s', ' '.join(cmd), output) else: die(die_message) return output HAS_EASY_INSTALL = bool(run_command(['which', 'easy_install'], check_exit_code=False).strip()) HAS_VIRTUALENV = bool(run_command(['which', 'virtualenv'], check_exit_code=False).strip()) def check_dependencies(): """Make sure virtualenv is in the path.""" print 'Checking dependencies...' if not HAS_VIRTUALENV: print 'Virtual environment not found.' # Try installing it via easy_install... if HAS_EASY_INSTALL: print 'Installing virtualenv via easy_install...', run_command(['easy_install', 'virtualenv'], die_message='easy_install failed to install virtualenv' '\ndevelopment requires virtualenv, please' ' install it using your favorite tool') if not run_command(['which', 'virtualenv']): die('ERROR: virtualenv not found in path.\n\ndevelopment ' ' requires virtualenv, please install it using your' ' favorite package management tool and ensure' ' virtualenv is in your path') print 'virtualenv installation done.' else: die('easy_install not found.\n\nInstall easy_install' ' (python-setuptools in ubuntu) or virtualenv by hand,' ' then rerun.') print 'dependency check done.' def create_virtualenv(venv=VENV): """Creates the virtual environment and installs PIP only into the virtual environment """ print 'Creating venv...', run_command(['virtualenv', '-q', '--no-site-packages', VENV]) print 'done.' print 'Installing pip in virtualenv...', if not run_command([WITH_VENV, 'easy_install', 'pip']).strip(): die("Failed to install pip.") print 'done.' print 'Installing distribute in virtualenv...' pip_install('distribute>=0.6.24') print 'done.' def pip_install(*args): args = [WITH_VENV, 'pip', 'install', '--upgrade'] + list(args) run_command(args, redirect_output=False) def install_dependencies(venv=VENV): print "Installing dependencies..." print "(This may take several minutes, don't panic)" pip_install('-r', TEST_REQUIRES) pip_install('-r', PIP_REQUIRES) # Tell the virtual env how to "import dashboard" py = 'python%d.%d' % (sys.version_info[0], sys.version_info[1]) pthfile = os.path.join(venv, "lib", py, "site-packages", "dashboard.pth") f = open(pthfile, 'w') f.write("%s\n" % ROOT) def install_horizon(): print 'Installing horizon module in development mode...' run_command([WITH_VENV, 'python', 'setup.py', 'develop'], cwd=ROOT) def print_summary(): summary = """ Horizon development environment setup is complete. To activate the virtualenv for the extent of your current shell session you can run: $ source .venv/bin/activate """ print summary def main(): check_dependencies() create_virtualenv() install_dependencies() install_horizon() print_summary() if __name__ == '__main__': main() manila-ui-2.13.0/tools/with_venv.sh000077500000000000000000000003321323215354300171600ustar00rootroot00000000000000#!/bin/bash TOOLS_PATH=${TOOLS_PATH:-$(dirname $0)} VENV_PATH=${VENV_PATH:-${TOOLS_PATH}} VENV_DIR=${VENV_NAME:-/../.venv} TOOLS=${TOOLS_PATH} VENV=${VENV:-${VENV_PATH}/${VENV_DIR}} source ${VENV}/bin/activate && "$@" manila-ui-2.13.0/tox.ini000066400000000000000000000032161323215354300147670ustar00rootroot00000000000000[tox] minversion = 1.6 envlist = py27,pep8,py27dj19,py27dj110 skipsdist = True [testenv] usedevelop = True install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} setenv = VIRTUAL_ENV={envdir} deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = /bin/bash run_tests.sh -N --no-pep8 {posargs} [testenv:py27] setenv = DJANGO_SETTINGS_MODULE=manila_ui.tests.settings [testenv:pep8] commands = flake8 [testenv:venv] commands = {posargs} # Django-1.8 is LTS [testenv:py27dj18] basepython = python2.7 commands = pip install django>=1.8,<1.9 /bin/bash run_tests.sh -N --no-pep8 {posargs} [testenv:py27dj19] basepython = python2.7 commands = pip install django>=1.9,<1.10 /bin/bash run_tests.sh -N --no-pep8 {posargs} [testenv:py27dj110] basepython = python2.7 commands = pip install django>=1.10,<1.11 /bin/bash run_tests.sh -N --no-pep8 {posargs} [testenv:cover] commands = {toxinidir}/tools/cover.sh {posargs} [testenv:docs] whitelist_externals = rm commands = rm -rf doc/build python setup.py build_sphinx [testenv:releasenotes] commands = sphinx-build -a -E -W -d releasenotes/build/doctrees \ -b html releasenotes/source releasenotes/build/html [testenv:debug] commands = oslo_debug_helper {posargs} [flake8] show-source = True # E123, E125 skipped as they are invalid PEP-8. # H405 multi line docstring summary not separated with an empty line ignore = E123,E125,H405 enable-extensions = H203,H106 exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,.ropeproject,tools