neutron-lbaas-dashboard-4.0.0/0000775000175100017510000000000013245512321016234 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/package.json0000666000175100017510000000161513245511613020532 0ustar zuulzuul00000000000000{ "version": "4.0.0b1", "private": true, "name": "neutron-lbaas-dashboard", "description": "Neutron LBaaS v2 Dashboard (deprecated)", "repository": "none", "license": "Apache 2.0", "devDependencies": { "eslint": "1.10.3", "eslint-config-openstack": "1.2.4", "eslint-plugin-angular": "1.0.1", "jasmine-core": "2.4.1", "karma": "1.1.2", "karma-chrome-launcher": "1.0.1", "karma-cli": "1.0.1", "karma-coverage": "1.1.1", "karma-jasmine": "1.0.2", "karma-ng-html2js-preprocessor": "1.0.0", "karma-phantomjs-launcher": "1.0.4", "karma-threshold-reporter": "0.1.15", "phantomjs-prebuilt": "2.1.14" }, "scripts": { "postinstall": "neutron_lbaas_dashboard/post_install.sh", "test": "karma start neutron_lbaas_dashboard/karma.conf.js --single-run", "lint": "eslint --no-color neutron_lbaas_dashboard/static" }, "dependencies": {} } neutron-lbaas-dashboard-4.0.0/releasenotes/0000775000175100017510000000000013245512321020725 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/releasenotes/notes/0000775000175100017510000000000013245512321022055 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/releasenotes/notes/bp-horizon-lbaas-v2-ui-ba7e4c97a0460f85.yaml0000666000175100017510000000167213245511613031304 0ustar zuulzuul00000000000000--- features: - A new dashboard wizard for Neutron LBaaS version 2. Allows you to create a version 2 load balancer and related resources such as a listener, pool, pool members, and health monitor. - A view of all the existing version 2 load balancers. - Ability to view details of a version 2 load balancer and drill down to see details for the listener, pool, pool member, and health monitor resources. - Ability to create, update, and delete the version 2 load balancer, listener, pool, pool member, and health monitor resources. - Ability to associate and disassociate floating IP addresses for a version 2 load balancer. - Ability to choose from SSL certificates stored by the key-manager service when creating a version 2 listener using the TERMINATED_HTTPS protocol. - Ability to choose from existing instances from the compute service or specify external members when adding members to a version 2 pool. ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/releasenotes/notes/neutron-lbaas-dashboard-deprecation-a3c910ababba8e78.yamlneutron-lbaas-dashboard-4.0.0/releasenotes/notes/neutron-lbaas-dashboard-deprecation-a3c910ababba8e70000666000175100017510000000066513245511613033341 0ustar zuulzuul00000000000000--- prelude: > As of the Queens release, neutron-lbaas-dashboard is now deprecated and being replaced by the octavia-dashboard project. Please see the FAQ for more information: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation deprecations: - | The neutron-lbaas-dashboard project is now deprecated. Please see the FAQ for more information: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation neutron-lbaas-dashboard-4.0.0/doc/0000775000175100017510000000000013245512321017001 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/doc/source/0000775000175100017510000000000013245512321020301 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/doc/source/usage.rst0000666000175100017510000000611613245511613022150 0ustar zuulzuul00000000000000========== User Guide ========== .. warning:: Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation Load-Balancer-as-a-Service (LBaaS) enables networking to distribute incoming requests evenly among designated instances. This distribution ensures that the workload is shared predictably among instances and enables more effective use of system resources. Use one of these load-balancing methods to distribute incoming requests: * Round robin: Rotates requests evenly between multiple instances. * Source IP: Requests from a unique source IP address are consistently directed to the same instance. * Least connections: Allocates requests to the instance with the least number of active connections. As an end user, you can create and manage load balancers and related objects for users in various projects. You can also delete load balancers and related objects. LBaaS v2 has several new concepts to understand: Load balancer The load balancer occupies a neutron network port and has an IP address assigned from a subnet. Listener Each port that listens for traffic on a particular load balancer is configured separately and tied to the load balancer. Multiple listeners can be associated with the same load balancer. Pool A pool is a group of hosts that sits behind the load balancer and serves traffic through the load balancer. Member Members are the actual IP addresses that receive traffic from the load balancer. Members are associated with pools. Health monitor Members may go offline from time to time and health monitors diverts traffic away from members that are not responding properly. Health monitors are associated with pools. View existing load balancers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #. Log in to the OpenStack dashboard. #. On the :guilabel:`Project` tab, open the :guilabel:`Network` tab, and click the :guilabel:`Load Balancers` category. This view shows the list of existing load balancers. To view details of any of the load balancers, click on the specific load balancer. Create a load balancer ~~~~~~~~~~~~~~~~~~~~~~ #. Log in to the OpenStack dashboard. #. On the :guilabel:`Project` tab, open the :guilabel:`Network` tab, and click the :guilabel:`Load Balancers` category. #. Click the :guilabel:`Create Load Balancer` button. Use the concepts described in the overview section to fill in the necessary information about the load balancer you want to create. Keep in mind, the health checks routinely run against each instance within a target load balancer and the result of the health check is used to determine if the instance receives new connections. .. note:: A message indicates whether the action succeeded. Delete a load balancer ~~~~~~~~~~~~~~~~~~~~~~ #. Select the load balancer you want to delete and click the :guilabel:`Delete Load Balancer` button. To be deleted successfully, a load balancer must not have any listeners or pools associated with it. The delete action is also available in the :guilabel:`Actions` column for the individual load balancers. neutron-lbaas-dashboard-4.0.0/doc/source/readme.rst0000666000175100017510000000003613245511613022274 0ustar zuulzuul00000000000000.. include:: ../../README.rst neutron-lbaas-dashboard-4.0.0/doc/source/reference.rst0000666000175100017510000000026513245511613023001 0ustar zuulzuul00000000000000========= Reference ========= Indices and search ------------------ .. toctree:: :hidden: contributor/modules/modules * :ref:`genindex` * :ref:`modindex` * :ref:`search` neutron-lbaas-dashboard-4.0.0/doc/source/conf.py0000777000175100017510000000755013245511613021617 0ustar zuulzuul00000000000000# -*- 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 logging import os import sys from sphinx import apidoc import django sys.path.insert(0, os.path.abspath('../..')) sys.path.insert(0, os.path.abspath('.')) logging.getLogger('openstack_dashboard.settings').setLevel(logging.ERROR) os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'openstack_dashboard.settings') django.setup() # -- 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 = [ 'openstackdocstheme', 'sphinx.ext.autodoc', 'sphinx.ext.coverage', # 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.viewcode', ] # 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'neutron-lbaas-dashboard' 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 = '_theme' # html_static_path = ['static'] html_theme = 'openstackdocs' html_theme_options = { 'display_toc': False } html_static_path = [] # 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} # A list of ignored prefixes for module index sorting. modindex_common_prefix = ['neutron-lbaas-dashboard.'] # TODO(mordred) We should extract this into a sphinx plugin def run_apidoc(_): cur_dir = os.path.abspath(os.path.dirname(__file__)) out_dir = os.path.join(cur_dir, 'contributor', 'modules') module = os.path.join(cur_dir, '..', '..', 'neutron_lbaas_dashboard') # Keep the order of arguments same as the sphinx-apidoc help, otherwise it # would cause unexpected errors: # sphinx-apidoc [options] -o # [exclude_pattern, ...] apidoc.main([ '--force', '-o', out_dir, module, 'neutron_lbaas_dashboard/tests', 'neutron_lbaas_dashboard/enabled', 'neutron_lbaas_dashboard/locale', 'neutron_lbaas_dashboard/static', 'neutron_lbaas_dashboard/post_install.sh', 'neutron_lbaas_dashboard/karma.conf.js' ]) def setup(app): app.connect('builder-inited', run_apidoc) neutron-lbaas-dashboard-4.0.0/doc/source/contributing.rst0000666000175100017510000000011313245511613023542 0ustar zuulzuul00000000000000============ Contributing ============ .. include:: ../../CONTRIBUTING.rst neutron-lbaas-dashboard-4.0.0/doc/source/index.rst0000666000175100017510000000111313245511613022143 0ustar zuulzuul00000000000000.. neutron-lbaas-dashboard 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. Welcome to neutron-lbaas-dashboard's documentation! ======================================================== .. warning:: Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation Contents: .. toctree:: :maxdepth: 2 readme installation usage contributing reference neutron-lbaas-dashboard-4.0.0/doc/source/installation.rst0000666000175100017510000000144713245511613023547 0ustar zuulzuul00000000000000============ Installation ============ .. warning:: Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation At the command line:: $ sudo pip install neutron-lbaas-dashboard Enable the plugin:: $ cp /usr/local/lib/python2.7/dist-packages/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.py /opt/stack/horizon/openstack_dashboard/enabled/ Note: This file may have installed in a different location depending on your host configuration. For example, on CentOS it may be in /usr/lib/python2.7/site-packages. Run the Django update commands (answer 'yes'):: $ /opt/stack/horizon/manage.py collectstatic $ /opt/stack/horizon/manage.py compress Restart Apache:: $ sudo service apache2 restart neutron-lbaas-dashboard-4.0.0/doc/requirements.txt0000666000175100017510000000042613245511613022274 0ustar zuulzuul00000000000000# 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. openstackdocstheme>=1.18.1 # Apache-2.0 sphinx!=1.6.6,>=1.6.2 # BSD neutron-lbaas-dashboard-4.0.0/devstack/0000775000175100017510000000000013245512321020040 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/devstack/README.rst0000666000175100017510000000147113245511613021537 0ustar zuulzuul00000000000000========================================== Neutron LBaaS v2 dashboard devstack plugin ========================================== This directory contains the neutron-lbaas-dashboard devstack plugin. To enable the plugin, add the following to your local.conf: enable_plugin neutron-lbaas-dashboard [GITREF] where is the URL of a neutron-lbaas-dashboard repository [GITREF] is an optional git ref (branch/ref/tag). The default is master. For example: enable_plugin neutron-lbaas-dashboard https://git.openstack.org/openstack/neutron-lbaas-dashboard Once you enable the plugin in your local.conf, ensure ``horizon`` and ``q-lbaasv2`` services are enabled. If both of them are enabled, neutron-lbaas-dashboard will be enabled automatically neutron-lbaas-dashboard-4.0.0/devstack/settings0000666000175100017510000000043713245511613021634 0ustar zuulzuul00000000000000NEUTRON_LBAAS_DASHBOARD_DIR=$DEST/neutron-lbaas-dashboard NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_NAME=_1481_project_ng_loadbalancersv2_panel.py NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_PATH=$NEUTRON_LBAAS_DASHBOARD_DIR/neutron_lbaas_dashboard/enabled/$NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_NAME neutron-lbaas-dashboard-4.0.0/devstack/plugin.sh0000666000175100017510000000230013245511613021672 0ustar zuulzuul00000000000000function neutron_lbaas_dashboard_install { setup_develop $NEUTRON_LBAAS_DASHBOARD_DIR } function neutron_lbaas_dashboard_configure { cp $NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_PATH \ $HORIZON_DIR/openstack_dashboard/local/enabled/ } if is_service_enabled horizon && is_service_enabled q-lbaasv2; then if [[ "$1" == "stack" && "$2" == "install" ]]; then # Perform installation of service source echo_summary "Installing neutron-lbaas-dashboard" neutron_lbaas_dashboard_install elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then echo_summary "Configuring neutron-lbaas-dashboard" neutron_lbaas_dashboard_configure elif [[ "$1" == "stack" && "$2" == "extra" ]]; then # Initialize and start the LBaaS service echo_summary "Initializing neutron-lbaas-dashboard" fi fi if [[ "$1" == "unstack" ]]; then # Shut down LBaaS dashboard services : fi if [[ "$1" == "clean" ]]; then # Remove state and transient data # Remember clean.sh first calls unstack.sh # Remove lbaas-dashboard enabled file and pyc rm -f "$HORIZON_DIR"/openstack_dashboard/local/enabled/"$NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_NAME"* fi neutron-lbaas-dashboard-4.0.0/babel-djangojs.cfg0000666000175100017510000000106013245511613021561 0ustar zuulzuul00000000000000[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] neutron-lbaas-dashboard-4.0.0/LICENSE0000666000175100017510000002363713245511613017261 0ustar zuulzuul00000000000000 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. neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/0000775000175100017510000000000013245512321023077 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/enabled/0000775000175100017510000000000013245512321024471 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/enabled/__init__.py0000666000175100017510000000000013245511613026575 0ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.pyneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel0000666000175100017510000000227413245511613033675 0ustar zuulzuul00000000000000# Copyright 2015 IBM Corp. # # 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 to be added to HORIZON_CONFIG. Required. PANEL = 'ngloadbalancersv2' # The slug of the dashboard the PANEL is associated with. Required. PANEL_DASHBOARD = 'project' # The slug of the panel group the PANEL is associated with. PANEL_GROUP = 'network' # Python panel class of the PANEL to be added. ADD_PANEL = ( 'neutron_lbaas_dashboard.dashboards.project.ngloadbalancersv2.panel' '.NGLoadBalancers') ADD_INSTALLED_APPS = ['neutron_lbaas_dashboard'] ADD_ANGULAR_MODULES = ['horizon.dashboard.project.lbaasv2'] ADD_SCSS_FILES = ['dashboard/project/lbaasv2/lbaasv2.scss'] AUTO_DISCOVER_STATIC_FILES = True neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/0000775000175100017510000000000013245512321023650 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/__init__.py0000666000175100017510000000000013245511613025754 0ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/rest/0000775000175100017510000000000013245512321024625 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/rest/__init__.py0000666000175100017510000000207713245511613026751 0ustar zuulzuul00000000000000# Copyright 2015 IBM Corp. # # 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 package holds the REST API that supports the LBaaS v2 dashboard Javascript code. It is not intended to be used outside of Horizon, and makes no promises of stability or fitness for purpose outside of that scope. It does not promise to adhere to the general OpenStack API Guidelines set out in https://wiki.openstack.org/wiki/APIChangeGuidelines. """ # import REST API modules here from neutron_lbaas_dashboard.api.rest import barbican # noqa from neutron_lbaas_dashboard.api.rest import lbaasv2 # noqa neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/rest/lbaasv2.py0000666000175100017510000006424113245511613026545 0ustar zuulzuul00000000000000# Copyright 2015 IBM Corp. # # 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. """API over the neutron LBaaS v2 service. """ from six.moves import _thread as thread from time import sleep from django.views import generic from horizon import conf from openstack_dashboard.api import neutron from openstack_dashboard.api.rest import urls from openstack_dashboard.api.rest import utils as rest_utils neutronclient = neutron.neutronclient def poll_loadbalancer_status(request, loadbalancer_id, callback, from_state='PENDING_UPDATE', to_state='ACTIVE', callback_kwargs=None): """Poll for the status of the load balancer. Polls for the status of the load balancer and calls a function when the status changes to a specified state. :param request: django request object :param loadbalancer_id: id of the load balancer to poll :param callback: function to call when polling is complete :param from_state: initial expected state of the load balancer :param to_state: state to check for :param callback_kwargs: kwargs to pass into the callback function """ interval = conf.HORIZON_CONFIG['ajax_poll_interval'] / 1000.0 status = from_state while status == from_state: sleep(interval) lb = neutronclient(request).show_loadbalancer( loadbalancer_id).get('loadbalancer') status = lb['provisioning_status'] if status == to_state: kwargs = {'loadbalancer_id': loadbalancer_id} if callback_kwargs: kwargs.update(callback_kwargs) callback(request, **kwargs) def create_loadbalancer(request): data = request.DATA spec = { 'vip_subnet_id': data['loadbalancer']['subnet'] } if data['loadbalancer'].get('name'): spec['name'] = data['loadbalancer']['name'] if data['loadbalancer'].get('description'): spec['description'] = data['loadbalancer']['description'] if data['loadbalancer'].get('ip'): spec['vip_address'] = data['loadbalancer']['ip'] loadbalancer = neutronclient(request).create_loadbalancer( {'loadbalancer': spec}).get('loadbalancer') if data.get('listener'): # There is work underway to add a new API to LBaaS v2 that will # allow us to pass in all information at once. Until that is # available we use a separate thread to poll for the load # balancer status and create the other resources when it becomes # active. args = (request, loadbalancer['id'], create_listener) kwargs = {'from_state': 'PENDING_CREATE'} thread.start_new_thread(poll_loadbalancer_status, args, kwargs) return loadbalancer def create_listener(request, **kwargs): """Create a new listener. """ data = request.DATA listenerSpec = { 'protocol': data['listener']['protocol'], 'protocol_port': data['listener']['port'], 'loadbalancer_id': kwargs['loadbalancer_id'] } if data['listener'].get('name'): listenerSpec['name'] = data['listener']['name'] if data['listener'].get('description'): listenerSpec['description'] = data['listener']['description'] if data.get('certificates'): listenerSpec['default_tls_container_ref'] = data['certificates'][0] listenerSpec['sni_container_refs'] = data['certificates'] listener = neutronclient(request).create_listener( {'listener': listenerSpec}).get('listener') if data.get('pool'): args = (request, kwargs['loadbalancer_id'], create_pool) kwargs = {'callback_kwargs': {'listener_id': listener['id']}} thread.start_new_thread(poll_loadbalancer_status, args, kwargs) return listener def create_pool(request, **kwargs): """Create a new pool. """ data = request.DATA poolSpec = { 'protocol': data['pool']['protocol'], 'lb_algorithm': data['pool']['method'], 'listener_id': kwargs['listener_id'] } if data['pool'].get('name'): poolSpec['name'] = data['pool']['name'] if data['pool'].get('description'): poolSpec['description'] = data['pool']['description'] pool = neutronclient(request).create_lbaas_pool( {'pool': poolSpec}).get('pool') if data.get('members'): args = (request, kwargs['loadbalancer_id'], add_member) kwargs = {'callback_kwargs': {'pool_id': pool['id'], 'index': 0}} thread.start_new_thread(poll_loadbalancer_status, args, kwargs) elif data.get('monitor'): args = (request, kwargs['loadbalancer_id'], create_health_monitor) kwargs = {'callback_kwargs': {'pool_id': pool['id']}} thread.start_new_thread(poll_loadbalancer_status, args, kwargs) return pool def create_health_monitor(request, **kwargs): """Create a new health monitor for a pool. """ data = request.DATA monitorSpec = { 'type': data['monitor']['type'], 'delay': data['monitor']['interval'], 'timeout': data['monitor']['timeout'], 'max_retries': data['monitor']['retry'], 'pool_id': kwargs['pool_id'] } if data['monitor'].get('method'): monitorSpec['http_method'] = data['monitor']['method'] if data['monitor'].get('path'): monitorSpec['url_path'] = data['monitor']['path'] if data['monitor'].get('status'): monitorSpec['expected_codes'] = data['monitor']['status'] return neutronclient(request).create_lbaas_healthmonitor( {'healthmonitor': monitorSpec}).get('healthmonitor') def add_member(request, **kwargs): """Add a member to a pool. """ data = request.DATA members = data.get('members') pool_id = kwargs.get('pool_id') if kwargs.get('members_to_add'): members_to_add = kwargs['members_to_add'] index = [members.index(member) for member in members if member['id'] == members_to_add[0]][0] loadbalancer_id = data.get('loadbalancer_id') else: index = kwargs.get('index') loadbalancer_id = kwargs.get('loadbalancer_id') member = members[index] memberSpec = { 'address': member['address'], 'protocol_port': member['port'], 'subnet_id': member['subnet'] } if member.get('weight'): memberSpec['weight'] = member['weight'] member = neutronclient(request).create_lbaas_member( pool_id, {'member': memberSpec}).get('member') index += 1 if kwargs.get('members_to_add'): args = (request, loadbalancer_id, update_member_list) members_to_add = kwargs['members_to_add'] members_to_add.pop(0) kwargs = {'callback_kwargs': { 'existing_members': kwargs.get('existing_members'), 'members_to_add': members_to_add, 'members_to_delete': kwargs.get('members_to_delete'), 'pool_id': pool_id}} thread.start_new_thread(poll_loadbalancer_status, args, kwargs) elif len(members) > index: args = (request, loadbalancer_id, add_member) kwargs = {'callback_kwargs': {'pool_id': pool_id, 'index': index}} thread.start_new_thread(poll_loadbalancer_status, args, kwargs) elif data.get('monitor'): args = (request, loadbalancer_id, create_health_monitor) kwargs = {'callback_kwargs': {'pool_id': pool_id}} thread.start_new_thread(poll_loadbalancer_status, args, kwargs) return member def remove_member(request, **kwargs): """Remove a member from the pool. """ data = request.DATA loadbalancer_id = data.get('loadbalancer_id') pool_id = kwargs.get('pool_id') if kwargs.get('members_to_delete'): members_to_delete = kwargs['members_to_delete'] member_id = members_to_delete.pop(0) neutronclient(request).delete_lbaas_member(member_id, pool_id) args = (request, loadbalancer_id, update_member_list) kwargs = {'callback_kwargs': { 'existing_members': kwargs.get('existing_members'), 'members_to_add': kwargs.get('members_to_add'), 'members_to_delete': members_to_delete}} thread.start_new_thread(poll_loadbalancer_status, args, kwargs) def update_loadbalancer(request, **kwargs): """Update a load balancer. """ data = request.DATA spec = {} loadbalancer_id = kwargs.get('loadbalancer_id') if data['loadbalancer'].get('name'): spec['name'] = data['loadbalancer']['name'] if data['loadbalancer'].get('description'): spec['description'] = data['loadbalancer']['description'] return neutronclient(request).update_loadbalancer( loadbalancer_id, {'loadbalancer': spec}).get('loadbalancer') def update_listener(request, **kwargs): """Update a listener. """ data = request.DATA listener_spec = {} listener_id = data['listener'].get('id') loadbalancer_id = data.get('loadbalancer_id') if data['listener'].get('name'): listener_spec['name'] = data['listener']['name'] if data['listener'].get('description'): listener_spec['description'] = data['listener']['description'] listener = neutronclient(request).update_listener( listener_id, {'listener': listener_spec}).get('listener') if data.get('pool'): args = (request, loadbalancer_id, update_pool) thread.start_new_thread(poll_loadbalancer_status, args) return listener def update_pool(request, **kwargs): """Update a pool. """ data = request.DATA pool_spec = {} pool_id = data['pool'].get('id') loadbalancer_id = data.get('loadbalancer_id') if data['pool'].get('name'): pool_spec['name'] = data['pool']['name'] if data['pool'].get('description'): pool_spec['description'] = data['pool']['description'] pools = neutronclient(request).update_lbaas_pool( pool_id, {'pool': pool_spec}).get('pools') # Assemble the lists of member id's to add and remove, if any exist tenant_id = request.user.project_id request_member_data = data.get('members', []) existing_members = neutronclient(request).list_lbaas_members( pool_id, tenant_id=tenant_id).get('members') (members_to_add, members_to_delete) = get_members_to_add_remove( request_member_data, existing_members) if members_to_add or members_to_delete: args = (request, loadbalancer_id, update_member_list) kwargs = {'callback_kwargs': {'existing_members': existing_members, 'members_to_add': members_to_add, 'members_to_delete': members_to_delete, 'pool_id': pool_id}} thread.start_new_thread(poll_loadbalancer_status, args, kwargs) elif data.get('monitor'): args = (request, loadbalancer_id, update_monitor) thread.start_new_thread(poll_loadbalancer_status, args) return pools def update_monitor(request, **kwargs): """Update a health monitor. """ data = request.DATA monitor_spec = {} monitor_id = data['monitor']['id'] if data['monitor'].get('interval'): monitor_spec['delay'] = data['monitor']['interval'] if data['monitor'].get('timeout'): monitor_spec['timeout'] = data['monitor']['timeout'] if data['monitor'].get('retry'): monitor_spec['max_retries'] = data['monitor']['retry'] if data['monitor'].get('method'): monitor_spec['http_method'] = data['monitor']['method'] if data['monitor'].get('path'): monitor_spec['url_path'] = data['monitor']['path'] if data['monitor'].get('status'): monitor_spec['expected_codes'] = data['monitor']['status'] healthmonitor = neutronclient(request).update_lbaas_healthmonitor( monitor_id, {'healthmonitor': monitor_spec}).get('healthmonitor') return healthmonitor def update_member_list(request, **kwargs): """Update the list of members by adding or removing the necessary members. """ data = request.DATA loadbalancer_id = data.get('loadbalancer_id') pool_id = kwargs.get('pool_id') existing_members = kwargs.get('existing_members') members_to_add = kwargs.get('members_to_add') members_to_delete = kwargs.get('members_to_delete') if members_to_delete: kwargs = {'existing_members': existing_members, 'members_to_add': members_to_add, 'members_to_delete': members_to_delete, 'pool_id': pool_id} remove_member(request, **kwargs) elif members_to_add: kwargs = {'existing_members': existing_members, 'members_to_add': members_to_add, 'members_to_delete': members_to_delete, 'pool_id': pool_id} add_member(request, **kwargs) elif data.get('monitor'): args = (request, loadbalancer_id, update_monitor) thread.start_new_thread(poll_loadbalancer_status, args) def get_members_to_add_remove(request_member_data, existing_members): new_member_ids = [member['id'] for member in request_member_data] existing_member_ids = [member['id'] for member in existing_members] members_to_add = [member_id for member_id in new_member_ids if member_id not in existing_member_ids] members_to_delete = [member_id for member_id in existing_member_ids if member_id not in new_member_ids] return members_to_add, members_to_delete def add_floating_ip_info(request, loadbalancers): """Add floating IP address info to each load balancer. """ floating_ips = neutron.tenant_floating_ip_list(request) for lb in loadbalancers: floating_ip = {} associated_ip = next((fip for fip in floating_ips if fip['fixed_ip'] == lb['vip_address']), None) if associated_ip is not None: floating_ip['id'] = associated_ip['id'] floating_ip['ip'] = associated_ip['ip'] lb['floating_ip'] = floating_ip @urls.register class LoadBalancers(generic.View): """API for load balancers. """ url_regex = r'lbaas/loadbalancers/$' @rest_utils.ajax() def get(self, request): """List load balancers for current project. The listing result is an object with property "items". """ tenant_id = request.user.project_id loadbalancers = neutronclient(request).list_loadbalancers( tenant_id=tenant_id).get('loadbalancers') if request.GET.get('full') and neutron.floating_ip_supported(request): add_floating_ip_info(request, loadbalancers) return {'items': loadbalancers} @rest_utils.ajax() def post(self, request): """Create a new load balancer. Creates a new load balancer as well as other optional resources such as a listener, pool, monitor, etc. """ return create_loadbalancer(request) @urls.register class LoadBalancerStatusTree(generic.View): """API for retrieving the resource status tree for a single load balancer. """ url_regex = r'lbaas/loadbalancers/(?P[^/]+)/statuses/$' @rest_utils.ajax() def get(self, request, loadbalancer_id): """Get the status tree for a specific load balancer. http://localhost/api/lbaas/loadbalancers/cc758c90-3d98-4ea1-af44-aab405c9c915/statuses """ return neutronclient(request).retrieve_loadbalancer_status( loadbalancer_id) @urls.register class LoadBalancer(generic.View): """API for retrieving, updating, and deleting a single load balancer. """ url_regex = r'lbaas/loadbalancers/(?P[^/]+)/$' @rest_utils.ajax() def get(self, request, loadbalancer_id): """Get a specific load balancer. http://localhost/api/lbaas/loadbalancers/cc758c90-3d98-4ea1-af44-aab405c9c915 """ loadbalancer = neutronclient(request).show_loadbalancer( loadbalancer_id).get('loadbalancer') if request.GET.get('full') and neutron.floating_ip_supported(request): add_floating_ip_info(request, [loadbalancer]) return loadbalancer @rest_utils.ajax() def put(self, request, loadbalancer_id): """Edit a load balancer. """ kwargs = {'loadbalancer_id': loadbalancer_id} update_loadbalancer(request, **kwargs) @rest_utils.ajax() def delete(self, request, loadbalancer_id): """Delete a specific load balancer. http://localhost/api/lbaas/loadbalancers/cc758c90-3d98-4ea1-af44-aab405c9c915 """ neutronclient(request).delete_loadbalancer(loadbalancer_id) @urls.register class Listeners(generic.View): """API for load balancer listeners. """ url_regex = r'lbaas/listeners/$' @rest_utils.ajax() def get(self, request): """List of listeners for the current project. The listing result is an object with property "items". """ loadbalancer_id = request.GET.get('loadbalancerId') tenant_id = request.user.project_id result = neutronclient(request).list_listeners(tenant_id=tenant_id) listener_list = result.get('listeners') if loadbalancer_id: listener_list = self._filter_listeners(listener_list, loadbalancer_id) return {'items': listener_list} @rest_utils.ajax() def post(self, request): """Create a new listener. Creates a new listener as well as other optional resources such as a pool, members, and health monitor. """ kwargs = {'loadbalancer_id': request.DATA.get('loadbalancer_id')} return create_listener(request, **kwargs) def _filter_listeners(self, listener_list, loadbalancer_id): filtered_listeners = [] for listener in listener_list: if listener['loadbalancers'][0]['id'] == loadbalancer_id: filtered_listeners.append(listener) return filtered_listeners @urls.register class Listener(generic.View): """API for retrieving, updating, and deleting a single listener. """ url_regex = r'lbaas/listeners/(?P[^/]+)/$' @rest_utils.ajax() def get(self, request, listener_id): """Get a specific listener. If the param 'includeChildResources' is passed in as a truthy value, the details of all resources that exist under the listener will be returned along with the listener details. http://localhost/api/lbaas/listeners/cc758c90-3d98-4ea1-af44-aab405c9c915 """ listener = neutronclient(request).show_listener( listener_id).get('listener') if request.GET.get('includeChildResources'): resources = {} resources['listener'] = listener if listener.get('default_pool_id'): pool_id = listener['default_pool_id'] pool = neutronclient(request).show_lbaas_pool( pool_id).get('pool') resources['pool'] = pool if pool.get('members'): tenant_id = request.user.project_id members = neutronclient(request).list_lbaas_members( pool_id, tenant_id=tenant_id).get('members') resources['members'] = members if pool.get('healthmonitor_id'): monitor_id = pool['healthmonitor_id'] monitor = neutronclient(request).show_lbaas_healthmonitor( monitor_id).get('healthmonitor') resources['monitor'] = monitor return resources else: return listener @rest_utils.ajax() def put(self, request, listener_id): """Edit a listener as well as any resources below it. """ kwargs = {'listener_id': listener_id} update_listener(request, **kwargs) @rest_utils.ajax() def delete(self, request, listener_id): """Delete a specific listener. http://localhost/api/lbaas/listeners/cc758c90-3d98-4ea1-af44-aab405c9c915 """ neutronclient(request).delete_listener(listener_id) @urls.register class Pools(generic.View): """API for load balancer pools. """ url_regex = r'lbaas/pools/$' @rest_utils.ajax() def post(self, request): """Create a new pool. Creates a new pool as well as other optional resources such as members and health monitor. """ kwargs = {'loadbalancer_id': request.DATA.get('loadbalancer_id'), 'listener_id': request.DATA.get('parentResourceId')} return create_pool(request, **kwargs) @urls.register class Pool(generic.View): """API for retrieving a single pool. """ url_regex = r'lbaas/pools/(?P[^/]+)/$' @rest_utils.ajax() def get(self, request, pool_id): """Get a specific pool. If the param 'includeChildResources' is passed in as a truthy value, the details of all resources that exist under the pool will be returned along with the pool details. http://localhost/api/lbaas/pools/cc758c90-3d98-4ea1-af44-aab405c9c915 """ pool = neutronclient(request).show_lbaas_pool(pool_id).get('pool') if request.GET.get('includeChildResources'): resources = {} resources['pool'] = pool if pool.get('members'): tenant_id = request.user.project_id members = neutronclient(request).list_lbaas_members( pool_id, tenant_id=tenant_id).get('members') resources['members'] = members if pool.get('healthmonitor_id'): monitor_id = pool['healthmonitor_id'] monitor = neutronclient(request).show_lbaas_healthmonitor( monitor_id).get('healthmonitor') resources['monitor'] = monitor return resources else: return pool @rest_utils.ajax() def put(self, request, pool_id): """Edit a listener as well as any resources below it. """ kwargs = {'pool_id': pool_id} update_pool(request, **kwargs) @rest_utils.ajax() def delete(self, request, pool_id): """Delete a specific pool. http://localhost/api/lbaas/pools/cc758c90-3d98-4ea1-af44-aab405c9c915 """ neutronclient(request).delete_lbaas_pool(pool_id) @urls.register class Members(generic.View): """API for load balancer members. """ url_regex = r'lbaas/pools/(?P[^/]+)/members/$' @rest_utils.ajax() def get(self, request, pool_id): """List of members for the current project. The listing result is an object with property "items". """ tenant_id = request.user.project_id result = neutronclient(request).list_lbaas_members(pool_id, tenant_id=tenant_id) return {'items': result.get('members')} @rest_utils.ajax() def put(self, request, pool_id): """Update the list of members for the current project. """ # Assemble the lists of member id's to add and remove, if any exist tenant_id = request.user.project_id request_member_data = request.DATA.get('members', []) existing_members = neutronclient(request).list_lbaas_members( pool_id, tenant_id=tenant_id).get('members') (members_to_add, members_to_delete) = get_members_to_add_remove( request_member_data, existing_members) if members_to_add or members_to_delete: kwargs = {'existing_members': existing_members, 'members_to_add': members_to_add, 'members_to_delete': members_to_delete, 'pool_id': pool_id} update_member_list(request, **kwargs) @urls.register class Member(generic.View): """API for retrieving a single member. """ url_regex = r'lbaas/pools/(?P[^/]+)' + \ '/members/(?P[^/]+)/$' @rest_utils.ajax() def get(self, request, member_id, pool_id): """Get a specific member belonging to a specific pool. """ return neutronclient(request).show_lbaas_member( member_id, pool_id).get('member') @rest_utils.ajax() def put(self, request, member_id, pool_id): """Edit a pool member. """ data = request.DATA spec = { 'weight': data['weight'] } return neutronclient(request).update_lbaas_member( member_id, pool_id, {'member': spec}) @urls.register class HealthMonitors(generic.View): """API for load balancer pool health monitors. """ url_regex = r'lbaas/healthmonitors/$' @rest_utils.ajax() def post(self, request): """Create a new health monitor. """ kwargs = {'loadbalancer_id': request.DATA.get('loadbalancer_id'), 'pool_id': request.DATA.get('parentResourceId')} return create_health_monitor(request, **kwargs) @urls.register class HealthMonitor(generic.View): """API for retrieving a single health monitor. """ url_regex = r'lbaas/healthmonitors/(?P[^/]+)/$' @rest_utils.ajax() def get(self, request, healthmonitor_id): """Get a specific health monitor. """ return neutronclient(request).show_lbaas_healthmonitor( healthmonitor_id).get('healthmonitor') @rest_utils.ajax() def delete(self, request, healthmonitor_id): """Delete a specific health monitor. http://localhost/api/lbaas/healthmonitors/cc758c90-3d98-4ea1-af44-aab405c9c915 """ neutronclient(request).delete_lbaas_healthmonitor(healthmonitor_id) @rest_utils.ajax() def put(self, request, healthmonitor_id): """Edit a health monitor. """ update_monitor(request) neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/rest/barbican.py0000666000175100017510000000666413245511613026761 0ustar zuulzuul00000000000000# Copyright 2016 IBM Corp. # # 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. """API over the barbican service. """ from barbicanclient import client as barbican_client from django.conf import settings from django.views import generic from keystoneclient.auth.identity import v2 as auth_v2 from keystoneclient.auth.identity import v3 as auth_v3 from keystoneclient import session from horizon.utils.memoized import memoized # noqa from openstack_dashboard.api import base from openstack_dashboard.api import keystone from openstack_dashboard.api.rest import urls from openstack_dashboard.api.rest import utils as rest_utils @memoized def barbicanclient(request): project_id = request.user.project_id region = request.user.services_region endpoint = base.url_for(request, 'key-manager') if keystone.get_version() < 3: auth = auth_v2.Token(settings.OPENSTACK_KEYSTONE_URL, request.user.token.id, tenant_id=project_id) else: domain_id = request.session.get('domain_context') auth = auth_v3.Token(settings.OPENSTACK_KEYSTONE_URL, request.user.token.id, project_id=project_id, project_domain_id=domain_id) insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False) cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None) # If 'insecure' is True, 'verify' is False in all cases; otherwise # pass the cacert path if it is present, or True if no cacert. verify = not insecure and (cacert or True) return barbican_client.Client(session=session.Session(auth=auth, verify=verify), endpoint=endpoint, region_name=region) @urls.register class SSLCertificates(generic.View): """API for working with SSL certificate containers. """ url_regex = r'barbican/certificates/$' @rest_utils.ajax() def get(self, request): """List certificate containers. The listing result is an object with property "items". """ limit = getattr(settings, 'API_RESULT_LIMIT', 1000) containers = barbicanclient(request).containers params = {'limit': limit, 'type': 'certificate'} result = containers._api.get('containers', params=params) return {'items': result.get('containers')} @urls.register class Secrets(generic.View): """API for working with secrets. """ url_regex = r'barbican/secrets/$' @rest_utils.ajax() def get(self, request): """List secrets. The listing result is an object with property "items". """ limit = getattr(settings, 'API_RESULT_LIMIT', 1000) secrets = barbicanclient(request).secrets params = {'limit': limit} result = secrets._api.get('secrets', params=params) return {'items': result.get('secrets')} neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/0000775000175100017510000000000013245512321025211 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/0000775000175100017510000000000013245512321026657 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/__init__.py0000666000175100017510000000000013245511613030763 0ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/0000775000175100017510000000000013245512321032246 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/views.py0000666000175100017510000000143113245511613033761 0ustar zuulzuul00000000000000# (c) Copyright 2015 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. from horizon.views import HorizonTemplateView class IndexView(HorizonTemplateView): template_name = 'project/ngloadbalancersv2/index.html' page_title = 'Load Balancers' ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates0000775000175100017510000000000013245512321034165 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ngloadbalancersv2/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates0000775000175100017510000000000013245512321034165 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ngloadbalancersv2/index.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates0000666000175100017510000000041313245511613034172 0ustar zuulzuul00000000000000{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Load Balancers" %}{% endblock %} {% block page_header %}{% endblock %} {% block ng_route_base %} {% endblock %} {% block main %}
{% endblock %} neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/urls.py0000666000175100017510000000144113245511613033612 0ustar zuulzuul00000000000000# (c) Copyright 2015 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. from django.conf.urls import url from neutron_lbaas_dashboard.dashboards.project.ngloadbalancersv2 import views urlpatterns = [ url('', views.IndexView.as_view(), name='index'), ] neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/panel.py0000666000175100017510000000344513245511613033732 0ustar zuulzuul00000000000000# (c) Copyright 2015 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. from oslo_log import log as logging from django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.api import neutron LOG = logging.getLogger(__name__) class NGLoadBalancers(horizon.Panel): name = _("Load Balancers") slug = 'ngloadbalancersv2' permissions = ('openstack.services.network',) def __init__(self): LOG.warning('neutron-lbaas-dashboard is now deprecated. See: ' 'https://wiki.openstack.org/wiki/Neutron/LBaaS/' 'Deprecation') def allowed(self, context): request = context['request'] try: if not neutron.is_service_enabled(request, config_name='enable_lb', ext_name='lbaasv2'): return False except Exception: LOG.error("Call to list enabled services failed. This is likely " "due to a problem communicating with the Neutron " "endpoint. Load Balancers v2 panel will not be " "displayed") return False return super(NGLoadBalancers, self).allowed(context) ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/__init__.pyneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/__init__.0000666000175100017510000000127713245511613034022 0ustar zuulzuul00000000000000# Copyright 2016 IBM Corp. # # 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. # Register the REST API URLs so they can be called from the JavaScript files from neutron_lbaas_dashboard.api import rest # noqa neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/__init__.py0000666000175100017510000000000013245511613027315 0ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/0000775000175100017510000000000013245512321024366 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/0000775000175100017510000000000013245512321025146 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/0000775000175100017510000000000013245512321026076 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/0000775000175100017510000000000013245512321032272 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.0000666000175100017510000003534013245511613033637 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.app.core.openstack-service-api') .factory('horizon.app.core.openstack-service-api.lbaasv2', lbaasv2API); lbaasv2API.$inject = [ 'horizon.framework.util.http.service', 'horizon.framework.widgets.toast.service' ]; /** * @ngdoc service * @name horizon.app.core.openstack-service-api.loadbalancers * @description Provides direct pass through to neutron LBaaS v2 with NO abstraction. * @param apiService The horizon core API service. * @param toastService The horizon toast service. * @returns The LBaaS V2 service API. */ function lbaasv2API(apiService, toastService) { var service = { getLoadBalancers: getLoadBalancers, getLoadBalancer: getLoadBalancer, deleteLoadBalancer: deleteLoadBalancer, createLoadBalancer: createLoadBalancer, editLoadBalancer: editLoadBalancer, getLoadBalancerStatusTree: getLoadBalancerStatusTree, getListeners: getListeners, getListener: getListener, createListener: createListener, editListener: editListener, deleteListener: deleteListener, getPool: getPool, createPool: createPool, editPool: editPool, deletePool: deletePool, getMembers: getMembers, getMember: getMember, editMember: editMember, getHealthMonitor: getHealthMonitor, deleteHealthMonitor: deleteHealthMonitor, createHealthMonitor: createHealthMonitor, editHealthMonitor: editHealthMonitor, updateMemberList: updateMemberList }; return service; /////////////// // Load Balancers /** * @name horizon.app.core.openstack-service-api.lbaasv2.getLoadBalancers * @description * Get a list of load balancers. * @param {boolean} full * The listing result is an object with property "items". Each item is * a load balancer. */ function getLoadBalancers(full) { var params = { full: full }; return apiService.get('/api/lbaas/loadbalancers/', { params: params }) .error(function () { toastService.add('error', gettext('Unable to retrieve load balancers.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.getLoadBalancer * @description * Get a single load balancer by ID * @param {string} id * @param {boolean} full * Specifies the id of the load balancer to request. */ function getLoadBalancer(id, full) { var params = { full: full }; return apiService.get('/api/lbaas/loadbalancers/' + id + '/', { params: params }) .error(function () { toastService.add('error', gettext('Unable to retrieve load balancer.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.deleteLoadBalancer * @description * Delete a single load balancer by ID * @param {string} id * @param {boolean} quiet * Specifies the id of the load balancer to delete. */ function deleteLoadBalancer(id, quiet) { var promise = apiService.delete('/api/lbaas/loadbalancers/' + id + '/'); return quiet ? promise : promise.error(function () { toastService.add('error', gettext('Unable to delete load balancer.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.createLoadBalancer * @description * Create a new load balancer * @param {object} spec * Specifies the data used to create the new load balancer. */ function createLoadBalancer(spec) { return apiService.post('/api/lbaas/loadbalancers/', spec) .error(function () { toastService.add('error', gettext('Unable to create load balancer.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.editLoadBalancer * @description * Edit a load balancer * @param {string} id * @param {object} spec * Specifies the data used to update the load balancer. */ function editLoadBalancer(id, spec) { return apiService.put('/api/lbaas/loadbalancers/' + id + '/', spec) .error(function () { toastService.add('error', gettext('Unable to update load balancer.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.getLoadBalancerStatusTree * @description * Get the status tree for a load balancer * @param {string} id * Specifies the id of the load balancer to request the status tree for. */ function getLoadBalancerStatusTree(id) { return apiService.get('/api/lbaas/loadbalancers/' + id + '/statuses/') .error(function () { toastService.add('error', gettext('Unable to retrieve load balancer status tree.')); }); } // Listeners /** * @name horizon.app.core.openstack-service-api.lbaasv2.getListeners * @description * Get the list of listeners. * If a loadbalancer ID is passed as a parameter, the returning list of * listeners will be filtered to include only those listeners under the * specified loadbalancer. * @param {string} id * Specifies the id of the loadbalancer to request listeners for. * * The listing result is an object with property "items". Each item is * a listener. */ function getListeners(id) { var params = id ? {params: {loadbalancerId: id}} : {}; return apiService.get('/api/lbaas/listeners/', params) .error(function () { toastService.add('error', gettext('Unable to retrieve listeners.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.getListener * @description * Get a single listener by ID. * @param {string} id * Specifies the id of the listener to request. * @param {boolean} includeChildResources * If truthy, all child resources below the listener will be included in the response. */ function getListener(id, includeChildResources) { var params = includeChildResources ? {params: {includeChildResources: includeChildResources}} : {}; return apiService.get('/api/lbaas/listeners/' + id + '/', params) .error(function () { toastService.add('error', gettext('Unable to retrieve listener.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.createListener * @description * Create a new listener * @param {object} spec * Specifies the data used to create the new listener. */ function createListener(spec) { return apiService.post('/api/lbaas/listeners/', spec) .error(function () { toastService.add('error', gettext('Unable to create listener.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.editListener * @description * Edit a listener * @param {string} id * Specifies the id of the listener to update. * @param {object} spec * Specifies the data used to update the listener. */ function editListener(id, spec) { return apiService.put('/api/lbaas/listeners/' + id + '/', spec) .error(function () { toastService.add('error', gettext('Unable to update listener.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.deleteListener * @description * Delete a single listener by ID * @param {string} id * @param {boolean} quiet * Specifies the id of the listener to delete. */ function deleteListener(id, quiet) { var promise = apiService.delete('/api/lbaas/listeners/' + id + '/'); return quiet ? promise : promise.error(function () { toastService.add('error', gettext('Unable to delete listener.')); }); } // Pools /** * @name horizon.app.core.openstack-service-api.lbaasv2.getPool * @description * Get a single Pool by ID. * @param {string} id * Specifies the id of the pool to request. * @param {boolean} includeChildResources * If truthy, all child resources below the pool will be included in the response. */ function getPool(id, includeChildResources) { var params = includeChildResources ? {params: {includeChildResources: includeChildResources}} : {}; return apiService.get('/api/lbaas/pools/' + id + '/', params) .error(function () { toastService.add('error', gettext('Unable to retrieve pool.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.createPool * @description * Create a new pool * @param {object} spec * Specifies the data used to create the new pool. */ function createPool(spec) { return apiService.post('/api/lbaas/pools/', spec) .error(function () { toastService.add('error', gettext('Unable to create pool.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.editPool * @description * Edit a pool * @param {string} id * Specifies the id of the pool to update. * @param {object} spec * Specifies the data used to update the pool. */ function editPool(id, spec) { return apiService.put('/api/lbaas/pools/' + id + '/', spec) .error(function () { toastService.add('error', gettext('Unable to update pool.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.deletePool * @description * Delete a single pool by ID * @param {string} id * @param {boolean} quiet * Specifies the id of the pool to delete. */ function deletePool(id, quiet) { var promise = apiService.delete('/api/lbaas/pools/' + id + '/'); return quiet ? promise : promise.error(function () { toastService.add('error', gettext('Unable to delete pool.')); }); } // Members /** * @name horizon.app.core.openstack-service-api.lbaasv2.getMembers * @description * Get a list of members. * @param {string} poolId * Specifies the id of the pool the members belong to. * * The listing result is an object with property "items". Each item is * a member. */ function getMembers(poolId) { return apiService.get('/api/lbaas/pools/' + poolId + '/members/') .error(function () { toastService.add('error', gettext('Unable to retrieve members.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.getMember * @description * Get a single pool Member by ID. * @param {string} poolId * Specifies the id of the pool the member belongs to. * @param {string} memberId * Specifies the id of the member to request. */ function getMember(poolId, memberId) { return apiService.get('/api/lbaas/pools/' + poolId + '/members/' + memberId + '/') .error(function () { toastService.add('error', gettext('Unable to retrieve member.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.editMember * @description * Edit a pool member. * @param {string} id * Specifies the id of the member to update. * @param {object} spec * Specifies the data used to update the member. */ function editMember(poolId, memberId, spec) { return apiService.put('/api/lbaas/pools/' + poolId + '/members/' + memberId + '/', spec) .error(function () { toastService.add('error', gettext('Unable to update member.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.updateMemberList * @description * Update the list of pool members by adding or removing the necessary members. * @param {string} poolId * Specifies the id of the pool the members belong to. * @param {object} spec * Specifies the data used to update the member list. */ function updateMemberList(poolId, spec) { return apiService.put('/api/lbaas/pools/' + poolId + '/members/', spec) .error(function () { toastService.add('error', gettext('Unable to update member list.')); }); } // Health Monitors /** * @name horizon.app.core.openstack-service-api.lbaasv2.getHealthMonitor * @description * Get a single pool health monitor by ID. * @param {string} monitorId * Specifies the id of the health monitor. */ function getHealthMonitor(monitorId) { return apiService.get('/api/lbaas/healthmonitors/' + monitorId + '/') .error(function () { toastService.add('error', gettext('Unable to retrieve health monitor.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.editHealthMonitor * @description * Edit a health monitor * @param {string} id * Specifies the id of the health monitor to update. * @param {object} spec * Specifies the data used to update the health monitor. */ function editHealthMonitor(id, spec) { return apiService.put('/api/lbaas/healthmonitors/' + id + '/', spec) .error(function () { toastService.add('error', gettext('Unable to update health monitor.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.deleteHealthMonitor * @description * Delete a single health monitor by ID * @param {string} id * @param {boolean} quiet * Specifies the id of the health monitor to delete. */ function deleteHealthMonitor(id, quiet) { var promise = apiService.delete('/api/lbaas/healthmonitors/' + id + '/'); return quiet ? promise : promise.error(function () { toastService.add('error', gettext('Unable to delete health monitor.')); }); } /** * @name horizon.app.core.openstack-service-api.lbaasv2.createHealthMonitor * @description * Create a new health monitor * @param {object} spec * Specifies the data used to create the new health monitor. */ function createHealthMonitor(spec) { return apiService.post('/api/lbaas/healthmonitors/', spec) .error(function () { toastService.add('error', gettext('Unable to create health monitor.')); }); } } }()); ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican0000666000175100017510000000436313245511613033771 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('Barbican API', function() { var testCall, service; var apiService = {}; var toastService = {}; beforeEach(module('horizon.mock.openstack-service-api', function($provide, initServices) { testCall = initServices($provide, apiService, toastService); })); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(inject(['horizon.app.core.openstack-service-api.barbican', function(barbicanAPI) { service = barbicanAPI; }])); it('defines the service', function() { expect(service).toBeDefined(); }); var tests = [ { func: "getCertificates", method: "get", path: "/api/barbican/certificates/", error: "Unable to retrieve SSL certificates." }, { func: "getSecrets", method: "get", path: "/api/barbican/secrets/", error: "Unable to retrieve secrets." } ]; // Iterate through the defined tests and apply as Jasmine specs. angular.forEach(tests, function(params) { it('defines the ' + params.func + ' call properly', function() { var callParams = [apiService, service, toastService, params]; testCall.apply(this, callParams); }); }); it('supresses the error if instructed for getCertificates', function() { spyOn(apiService, 'get').and.returnValue("promise"); expect(service.getCertificates(true)).toBe("promise"); }); it('supresses the error if instructed for getSecrets', function() { spyOn(apiService, 'get').and.returnValue("promise"); expect(service.getSecrets(true)).toBe("promise"); }); }); })(); ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.0000666000175100017510000002034713245511613033640 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 API', function() { var testCall, service; var apiService = {}; var toastService = {}; beforeEach(module('horizon.mock.openstack-service-api', function($provide, initServices) { testCall = initServices($provide, apiService, toastService); })); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(inject(['horizon.app.core.openstack-service-api.lbaasv2', function(lbaasv2API) { service = lbaasv2API; }])); it('defines the service', function() { expect(service).toBeDefined(); }); var tests = [ { func: 'getLoadBalancers', method: 'get', path: '/api/lbaas/loadbalancers/', error: 'Unable to retrieve load balancers.', testInput: [ true ], data: { params: { full: true } } }, { func: 'getLoadBalancer', method: 'get', path: '/api/lbaas/loadbalancers/1234/', error: 'Unable to retrieve load balancer.', testInput: [ '1234', true ], data: { params: { full: true } } }, { func: 'deleteLoadBalancer', method: 'delete', path: '/api/lbaas/loadbalancers/1234/', error: 'Unable to delete load balancer.', testInput: [ '1234' ] }, { func: 'getLoadBalancerStatusTree', method: 'get', path: '/api/lbaas/loadbalancers/1234/statuses/', error: 'Unable to retrieve load balancer status tree.', testInput: [ '1234' ] }, { func: 'getListeners', method: 'get', path: '/api/lbaas/listeners/', error: 'Unable to retrieve listeners.', testInput: [ '1234' ], data: { params: { loadbalancerId: '1234' } } }, { func: 'getListeners', method: 'get', path: '/api/lbaas/listeners/', data: {}, error: 'Unable to retrieve listeners.' }, { func: 'getListener', method: 'get', path: '/api/lbaas/listeners/1234/', data: { params: { includeChildResources: true } }, error: 'Unable to retrieve listener.', testInput: [ '1234', true ] }, { func: 'getListener', method: 'get', path: '/api/lbaas/listeners/1234/', data: {}, error: 'Unable to retrieve listener.', testInput: [ '1234', false ] }, { func: 'getPool', method: 'get', path: '/api/lbaas/pools/1234/', data: { params: { includeChildResources: true } }, error: 'Unable to retrieve pool.', testInput: [ '1234', true ] }, { func: 'getPool', method: 'get', path: '/api/lbaas/pools/1234/', data: {}, error: 'Unable to retrieve pool.', testInput: [ '1234', false ] }, { func: 'deletePool', method: 'delete', path: '/api/lbaas/pools/1234/', error: 'Unable to delete pool.', testInput: [ '1234' ] }, { func: 'getMembers', method: 'get', path: '/api/lbaas/pools/1234/members/', error: 'Unable to retrieve members.', testInput: [ '1234' ] }, { func: 'getMember', method: 'get', path: '/api/lbaas/pools/1234/members/5678/', error: 'Unable to retrieve member.', testInput: [ '1234', '5678' ] }, { func: 'editMember', method: 'put', path: '/api/lbaas/pools/1234/members/5678/', error: 'Unable to update member.', data: { weight: 2 }, testInput: [ '1234', '5678', { weight: 2 } ] }, { func: 'getHealthMonitor', method: 'get', path: '/api/lbaas/healthmonitors/1234/', error: 'Unable to retrieve health monitor.', testInput: [ '1234' ] }, { func: 'editHealthMonitor', method: 'put', path: '/api/lbaas/healthmonitors/1234/', error: 'Unable to update health monitor.', data: { name: 'healthmonitor-1' }, testInput: [ '1234', { name: 'healthmonitor-1' } ] }, { func: 'deleteHealthMonitor', method: 'delete', path: '/api/lbaas/healthmonitors/1234/', error: 'Unable to delete health monitor.', testInput: [ '1234' ] }, { func: 'createLoadBalancer', method: 'post', path: '/api/lbaas/loadbalancers/', error: 'Unable to create load balancer.', data: { name: 'loadbalancer-1' }, testInput: [ { name: 'loadbalancer-1' } ] }, { func: 'editLoadBalancer', method: 'put', path: '/api/lbaas/loadbalancers/1234/', error: 'Unable to update load balancer.', data: { name: 'loadbalancer-1' }, testInput: [ '1234', { name: 'loadbalancer-1' } ] }, { func: 'createListener', method: 'post', path: '/api/lbaas/listeners/', error: 'Unable to create listener.', data: { name: 'listener-1' }, testInput: [ { name: 'listener-1' } ] }, { func: 'editListener', method: 'put', path: '/api/lbaas/listeners/1234/', error: 'Unable to update listener.', data: { name: 'listener-1' }, testInput: [ '1234', { name: 'listener-1' } ] }, { func: 'deleteListener', method: 'delete', path: '/api/lbaas/listeners/1234/', error: 'Unable to delete listener.', testInput: [ '1234' ] }, { func: 'createPool', method: 'post', path: '/api/lbaas/pools/', error: 'Unable to create pool.', data: { name: 'pool-1' }, testInput: [ { name: 'pool-1' } ] }, { func: 'editPool', method: 'put', path: '/api/lbaas/pools/1234/', error: 'Unable to update pool.', data: { name: 'pool-1' }, testInput: [ '1234', { name: 'pool-1' } ] }, { func: 'createHealthMonitor', method: 'post', path: '/api/lbaas/healthmonitors/', error: 'Unable to create health monitor.', data: { name: 'healthmonitor-1' }, testInput: [ { name: 'healthmonitor-1' } ] }, { func: 'updateMemberList', method: 'put', path: '/api/lbaas/pools/1234/members/', error: 'Unable to update member list.', data: { name: 'member-1' }, testInput: [ '1234', { name: 'member-1' } ] } ]; // Iterate through the defined tests and apply as Jasmine specs. angular.forEach(tests, function(params) { it('defines the ' + params.func + ' call properly', function() { var callParams = [apiService, service, toastService, params]; testCall.apply(this, callParams); }); }); it('supresses the error if instructed for deleteLoadBalancer', function() { spyOn(apiService, 'delete').and.returnValue("promise"); expect(service.deleteLoadBalancer("whatever", true)).toBe("promise"); }); it('supresses the error if instructed for deleteListener', function() { spyOn(apiService, 'delete').and.returnValue("promise"); expect(service.deleteListener("whatever", true)).toBe("promise"); }); it('supresses the error if instructed for deletePool', function() { spyOn(apiService, 'delete').and.returnValue("promise"); expect(service.deletePool("whatever", true)).toBe("promise"); }); it('supresses the error if instructed for deleteHealthMonitor', function() { spyOn(apiService, 'delete').and.returnValue("promise"); expect(service.deleteHealthMonitor("whatever", true)).toBe("promise"); }); }); })(); ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican0000666000175100017510000000500413245511613033762 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.app.core.openstack-service-api') .factory('horizon.app.core.openstack-service-api.barbican', barbicanAPI); barbicanAPI.$inject = [ 'horizon.framework.util.http.service', 'horizon.framework.widgets.toast.service' ]; /** * @ngdoc service * @name horizon.app.core.openstack-service-api.barbican * @description Provides direct pass through to barbican with NO abstraction. * @param apiService The horizon core API service. * @param toastService The horizon toast service. * @returns The barbican service API. */ function barbicanAPI(apiService, toastService) { var service = { getCertificates: getCertificates, getSecrets: getSecrets }; return service; /////////////// // SSL Certificate Containers /** * @name horizon.app.core.openstack-service-api.barbican.getCertificates * @description * Get a list of SSL certificate containers. * * @param {boolean} quiet * The listing result is an object with property "items". Each item is * a certificate container. */ function getCertificates(quiet) { var promise = apiService.get('/api/barbican/certificates/'); return quiet ? promise : promise.error(function handleError() { toastService.add('error', gettext('Unable to retrieve SSL certificates.')); }); } // Secrets /** * @name horizon.app.core.openstack-service-api.barbican.getSecrets * @description * Get a list of secrets. * * @param {boolean} quiet * The listing result is an object with property "items". Each item is * a secret. */ function getSecrets(quiet) { var promise = apiService.get('/api/barbican/secrets/'); return quiet ? promise : promise.error(function handleError() { toastService.add('error', gettext('Unable to retrieve secrets.')); }); } } }()); neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/0000775000175100017510000000000013245512321026315 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/0000775000175100017510000000000013245512321027763 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/0000775000175100017510000000000013245512321031315 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/0000775000175100017510000000000013245512321033167 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000775000175100017510000000000013245512321034027 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.help.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000666000175100017510000000077713245511613034051 0ustar zuulzuul00000000000000

The load balancer occupies a neutron network port and has an IP address assigned from a subnet.

IP address: If an IP address is provided it must be a well-formed IPv4 or IPv6 address. The system will attempt to assign the provided IP address to the load balancer. If an IP address is not provided then one will be allocated for you.

Subnet: The network on which to allocate the load balancer's IP address.

././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000666000175100017510000000304713245511613034042 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2') .controller('LoadBalancerDetailsController', LoadBalancerDetailsController); LoadBalancerDetailsController.$inject = [ 'horizon.dashboard.project.lbaasv2.patterns', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc controller * @name LoadBalancerDetailsController * @description * The `LoadBalancerDetailsController` controller provides functions for * configuring the load balancers step of the LBaaS wizard. * @param patterns The LBaaS v2 patterns constant. * @param gettext The horizon gettext function for translation. * @returns undefined */ function LoadBalancerDetailsController(patterns, gettext) { var ctrl = this; // Error text for invalid fields ctrl.ipError = gettext('The IP address is not valid.'); // IP address validation pattern ctrl.ipPattern = [patterns.ipv4, patterns.ipv6].join('|'); } })(); ././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000666000175100017510000000375413245511613034047 0ustar zuulzuul00000000000000

Provide the details for the load balancer.

{$ ::ctrl.ipError $}
././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000666000175100017510000000236213245511613034041 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('Load Balancer Details Step', function() { beforeEach(module('horizon.framework.util.i18n')); beforeEach(module('horizon.dashboard.project.lbaasv2')); describe('LoadBalancerDetailsController', function() { var ctrl; beforeEach(inject(function($controller) { ctrl = $controller('LoadBalancerDetailsController'); })); it('should define error messages for invalid fields', function() { expect(ctrl.ipError).toBeDefined(); }); it('should define patterns for field validation', function() { expect(ctrl.ipPattern).toBeDefined(); }); }); }); })(); ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/modal.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moda0000666000175100017510000000566213245511613034050 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2') .factory('horizon.dashboard.project.lbaasv2.workflow.modal', modalService); modalService.$inject = [ '$uibModal', 'horizon.framework.widgets.toast.service' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.workflow.modal * * @description * Provides the service for opening the LBaaS create / edit modal. * * @param $uibModal The angular bootstrap $uibModal service. * @param toastService The horizon toast service. * @returns The modal service for the LBaaS workflow. */ function modalService($uibModal, toastService) { var service = { init: init }; return service; ////////////// /** * @ngdoc method * @name init * * @description * Initialize a new scope for an LBaaS workflow modal. * * @param args An object containing the following properties: * controller*: Controller to use for the wizard instance. * message*: String to display using the toast service when wizard completes. * allowed*: Function used to determine if the workflow action is allowed. * handle: Function to call after the modal closes, receives the result of wizard submit. * @returns An object with a single function 'open', used to open the modal. */ function init(args) { return { allowed: args.allowed, perform: open }; /** * @ngdoc method * @name open * * @description * Open the modal. * * @param item The row item from the table action. * @returns undefined */ function open(item) { var spec = { size: 'lg', backdrop: 'static', controller: 'ModalContainerController', template: '', windowClass: 'modal-dialog-wizard', resolve: { launchContext: function() { return item; } } }; $uibModal.open(spec).result.then(onModalClose); } function onModalClose(response) { toastService.add('success', args.message); if (args.handle) { args.handle(response); } } } } })(); ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/workflow.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/work0000666000175100017510000000640013245511613034101 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Workflow Service', function() { var workflowService; beforeEach(module('horizon.app.core')); beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets.toast')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function ($injector) { workflowService = $injector.get( 'horizon.dashboard.project.lbaasv2.workflow.workflow' ); })); it('should be defined', function () { expect(workflowService).toBeDefined(); }); it('should have a title property', function () { var workflow = workflowService('My Workflow'); expect(workflow.title).toBe('My Workflow'); }); it('should have default steps defined', function () { var workflow = workflowService('My Workflow'); expect(workflow.steps).toBeDefined(); expect(workflow.steps.length).toBe(5); var forms = [ 'loadBalancerDetailsForm', 'listenerDetailsForm', 'poolDetailsForm', 'memberDetailsForm', 'monitorDetailsForm' ]; forms.forEach(function(expectedForm, idx) { expect(workflow.steps[idx].formName).toBe(expectedForm); }); }); it('should have a step for ssl certificates', function () { var workflow = workflowService('My Workflow'); expect(workflow.certificatesStep).toBeDefined(); expect(workflow.certificatesStep.title).toBe('SSL Certificates'); }); it('can filter steps', function () { var workflow = workflowService('My Workflow', 'foo', ['listener', 'pool']); expect(workflow.steps).toBeDefined(); expect(workflow.steps.length).toBe(2); expect(workflow.steps[0].checkReadiness).not.toBeDefined(); var forms = [ 'listenerDetailsForm', 'poolDetailsForm' ]; forms.forEach(function(expectedForm, idx) { expect(workflow.steps[idx].formName).toBe(expectedForm); }); }); it('can wait for all steps to be ready', function () { var workflow = workflowService('My Workflow', 'foo', null, 'promise'); expect(workflow.steps[0].checkReadiness).toBeDefined(); expect(workflow.steps[0].checkReadiness()).toBe('promise'); }); it('can be extended', function () { var workflow = workflowService('My Workflow'); expect(workflow.append).toBeDefined(); expect(workflow.prepend).toBeDefined(); expect(workflow.after).toBeDefined(); expect(workflow.replace).toBeDefined(); expect(workflow.remove).toBeDefined(); expect(workflow.addController).toBeDefined(); }); }); })(); ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000775000175100017510000000000013245512321034045 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000666000175100017510000000372313245511613034061 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('SSL Certificates Step', function() { var certs = [{ id: '1', name: 'foo', expiration: '2015-03-26T21:10:45.417835' }]; beforeEach(module('horizon.framework.util.i18n')); beforeEach(module('horizon.dashboard.project.lbaasv2')); describe('CertificatesController', function() { var ctrl, scope; beforeEach(inject(function($controller) { scope = { model: { spec: { certificates: [] }, certificates: certs } }; ctrl = $controller('CertificatesController', { $scope: scope }); })); it('should define transfer table properties', function() { expect(ctrl.tableData).toBeDefined(); expect(ctrl.tableLimits).toBeDefined(); expect(ctrl.tableHelp).toBeDefined(); }); it('should have available certificates', function() { expect(ctrl.tableData.available).toBeDefined(); expect(ctrl.tableData.available.length).toBe(1); expect(ctrl.tableData.available[0].id).toBe('1'); }); it('should not have allocated members', function() { expect(ctrl.tableData.allocated).toEqual([]); }); it('should allow adding multiple certificates', function() { expect(ctrl.tableLimits.maxAllocation).toBe(-1); }); }); }); })(); ././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.help.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000666000175100017510000000141213245511613034052 0ustar zuulzuul00000000000000

If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL certificates must be selected. The first certificate will be the default.

Use the key-manager service to create any certificate containers before creating the listener. The following documentation provides information on how to create a certificate container:

././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000666000175100017510000000623413245511613034061 0ustar zuulzuul00000000000000

Select one or more SSL certificates for the listener.

Certificate Name Expiration Date
{$ ::trCtrl.helpText.noneAllocText $}
{$ ::row.name $} {$ row.expiration | date | noValue $}
Certificate Name Expiration Date
{$ ::trCtrl.helpText.noneAvailText $}
{$ ::row.name $} {$ row.expiration | date | noValue $}
././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000666000175100017510000000325713245511613034063 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2') .controller('CertificatesController', CertificatesController); CertificatesController.$inject = [ '$scope', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc controller * @name CertificatesController * @description * The `CertificatesController` controller provides functions for adding certificates to a * listener. * @param $scope The angular scope object. * @param gettext The horizon gettext function for translation. * @returns undefined */ function CertificatesController($scope, gettext) { var ctrl = this; ctrl.tableData = { available: $scope.model.certificates, allocated: $scope.model.spec.certificates, displayedAvailable: [], displayedAllocated: [] }; ctrl.tableLimits = { maxAllocation: -1 }; ctrl.tableHelp = { availHelpText: '', noneAllocText: gettext('Select certificates from the available certificates below'), noneAvailText: gettext('No available certificates') }; } })(); ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000775000175100017510000000000013245512321034030 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000666000175100017510000001406513245511613034045 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('Member Details Step', function() { var model; beforeEach(module('horizon.framework.util.i18n')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(function() { model = { spec: { members: [], pool: { protocol: 'HTTP' } }, members: [{ id: '1', name: 'foo', description: 'bar', weight: 1, port: 80, address: { ip: '1.2.3.4', subnet: '1' }, addresses: [{ ip: '1.2.3.4', subnet: '1' }, { ip: '2.3.4.5', subnet: '2' }] }], subnets: [{ id: '1', name: 'subnet-1' }] }; }); describe('MemberDetailsController', function() { var ctrl; beforeEach(inject(function($controller) { ctrl = $controller('MemberDetailsController', { $scope: { model: model } }); })); it('should define error messages for invalid fields', function() { expect(ctrl.portError).toBeDefined(); expect(ctrl.weightError).toBeDefined(); expect(ctrl.ipError).toBeDefined(); }); it('should define patterns for validation', function() { expect(ctrl.ipPattern).toBeDefined(); }); it('should define transfer table properties', function() { expect(ctrl.tableData).toBeDefined(); expect(ctrl.tableLimits).toBeDefined(); expect(ctrl.tableHelp).toBeDefined(); }); it('should have available members', function() { expect(ctrl.tableData.available).toBeDefined(); expect(ctrl.tableData.available.length).toBe(1); expect(ctrl.tableData.available[0].id).toBe('1'); }); it('should not have allocated members', function() { expect(ctrl.tableData.allocated).toEqual([]); }); it('should allow adding multiple members', function() { expect(ctrl.tableLimits.maxAllocation).toBe(-1); }); it('should properly format address popover target', function() { var target = ctrl.addressPopoverTarget(model.members[0]); expect(target).toBe('1.2.3.4...'); }); it('should allocate a new external member', function() { ctrl.allocateExternalMember(); expect(model.spec.members.length).toBe(1); expect(model.spec.members[0].id).toBe(0); expect(model.spec.members[0].address).toBeNull(); expect(model.spec.members[0].subnet).toBeNull(); }); it('should allocate a given member', function() { ctrl.allocateMember(model.members[0]); expect(model.spec.members.length).toBe(1); expect(model.spec.members[0].id).toBe(0); expect(model.spec.members[0].address).toEqual(model.members[0].address); expect(model.spec.members[0].subnet).toBeUndefined(); expect(model.spec.members[0].port).toEqual(model.members[0].port); }); it('should deallocate a given member', function() { ctrl.deallocateMember(model.spec.members[0]); expect(model.spec.members.length).toBe(0); }); it('should show subnet name for available instance', function() { var name = ctrl.getSubnetName(model.members[0]); expect(name).toBe('subnet-1'); }); }); describe('Member Details Step Template', function() { var $scope, $element, popoverContent; beforeEach(module('templates')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function($injector) { var $compile = $injector.get('$compile'); var $templateCache = $injector.get('$templateCache'); var basePath = $injector.get('horizon.dashboard.project.lbaasv2.basePath'); var popoverTemplates = $injector.get('horizon.dashboard.project.lbaasv2.popovers'); var markup = $templateCache.get(basePath + 'workflow/members/members.html'); $scope = $injector.get('$rootScope').$new(); $scope.model = model; $element = $compile(markup)($scope); var popoverScope = $injector.get('$rootScope').$new(); popoverScope.member = model.members[0]; popoverContent = $compile(popoverTemplates.ipAddresses)(popoverScope); })); it('should show IP addresses popover on hover', function() { var ctrl = $element.scope().ctrl; ctrl.tableData.displayedAvailable = model.members; $scope.$apply(); var popoverElement = $element.find('span.addresses-popover'); expect(popoverElement.length).toBe(1); $.fn.popover = angular.noop; spyOn($.fn, 'popover'); spyOn(ctrl, 'showAddressPopover').and.callThrough(); popoverElement.trigger('mouseover'); expect(ctrl.showAddressPopover).toHaveBeenCalledWith( jasmine.objectContaining({type: 'mouseover'}), model.members[0]); expect($.fn.popover.calls.count()).toBe(2); expect($.fn.popover.calls.argsFor(0)[0]).toEqual({ content: popoverContent, html: true, placement: 'top', title: 'IP Addresses (2)' }); expect($.fn.popover.calls.argsFor(1)[0]).toBe('show'); spyOn(ctrl, 'hideAddressPopover').and.callThrough(); popoverElement.trigger('mouseleave'); expect(ctrl.hideAddressPopover) .toHaveBeenCalledWith(jasmine.objectContaining({type: 'mouseleave'})); expect($.fn.popover.calls.count()).toBe(3); expect($.fn.popover.calls.argsFor(2)[0]).toBe('hide'); }); }); }); })(); ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000666000175100017510000001062413245511613034042 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2') .controller('MemberDetailsController', MemberDetailsController); MemberDetailsController.$inject = [ '$scope', '$compile', 'horizon.dashboard.project.lbaasv2.popovers', 'horizon.dashboard.project.lbaasv2.patterns', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc controller * @name MemberDetailsController * @description * The `MemberDetailsController` controller provides functions for adding members to a pool. * @param $scope The angular scope object. * @param $compile The angular compile service. * @param popoverTemplates LBaaS v2 popover templates constant. * @param patterns The LBaaS v2 patterns constant. * @param gettext The horizon gettext function for translation. * @returns undefined */ function MemberDetailsController($scope, $compile, popoverTemplates, patterns, gettext) { var ctrl = this; var memberCounter = 0; // Error text for invalid fields ctrl.portError = gettext('The port must be a number between 1 and 65535.'); ctrl.weightError = gettext('The weight must be a number between 1 and 256.'); ctrl.ipError = gettext('The IP address is not valid.'); // Instances transer table widget properties ctrl.tableData = { available: $scope.model.members, allocated: $scope.model.spec.members, displayedAvailable: [], displayedAllocated: [] }; ctrl.tableLimits = { maxAllocation: -1 }; ctrl.tableHelp = { availHelpText: '', noneAllocText: gettext('No members have been allocated'), noneAvailText: gettext('No available instances'), allocTitle: gettext('Allocated Members'), availTitle: gettext('Available Instances') }; // IP address validation pattern ctrl.ipPattern = [patterns.ipv4, patterns.ipv6].join('|'); // Functions to control the IP address popover ctrl.showAddressPopover = showAddressPopover; ctrl.hideAddressPopover = hideAddressPopover; ctrl.addressPopoverTarget = addressPopoverTarget; // Member management ctrl.allocateExternalMember = allocateExternalMember; ctrl.allocateMember = allocateMember; ctrl.deallocateMember = deallocateMember; ctrl.getSubnetName = getSubnetName; ////////// function showAddressPopover(event, member) { var element = angular.element(event.target); var scope = $scope.$new(true); scope.member = member; element.popover({ content: $compile(popoverTemplates.ipAddresses)(scope), html: true, placement: 'top', title: interpolate(gettext('IP Addresses (%(count)s)'), { count: member.addresses.length }, true) }); element.popover('show'); } function hideAddressPopover(event) { var element = angular.element(event.target); element.popover('hide'); } function addressPopoverTarget(member) { return interpolate(gettext('%(ip)s...'), { ip: member.address.ip }, true); } function allocateExternalMember() { var protocol = $scope.model.spec.pool.protocol; $scope.model.spec.members.push({ id: memberCounter++, address: null, subnet: null, port: { HTTP: 80 }[protocol], weight: 1 }); } function allocateMember(member) { var newMember = angular.extend(angular.copy(member), { id: memberCounter++ }); $scope.model.spec.members.push(newMember); } function deallocateMember(member) { var index = $scope.model.spec.members.indexOf(member); $scope.model.spec.members.splice(index, 1); } function getSubnetName(member) { return $scope.model.subnets.filter(function filterSubnet(subnet) { return subnet.id === member.address.subnet; })[0].name; } } })(); ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000666000175100017510000001721213245511613034042 0ustar zuulzuul00000000000000

Add members to the load balancer pool.

IP Address Subnet Port Weight
{$ ::trCtrl.helpText.noneAllocText $}
{$ row.address.ip $}
{$ ctrl.getSubnetName(row) $}
Remove
Add external member
Name IP Address
{$ ::trCtrl.helpText.noneAvailText $}
{$ ::row.name $} {$ row.address.ip $} {$ ctrl.addressPopoverTarget(row) $} Add
././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.help.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000666000175100017510000000206313245511613034040 0ustar zuulzuul00000000000000

Members are the actual IP addresses that will receive traffic from the load balancer. Each member must have a unique combination of IP address and port.

The Available Instances table contains existing compute instances that can be added as members of the pool. Use the "Add external member" button to add a member not found in the Available Instances table.

IP address: The IP address of the member to receive traffic from the load balancer. Must be a well-formed IPv4 or IPv6 address.

Subnet: The network which contains the IP address of the member.

Port: The port on which the member listens for traffic. Must be a number from 1 to 65535.

Weight: The weight of a member determines the portion of requests or connections it services compared to the other members of the pool. A higher weight means it will receive more traffic. Must be a number from 1 to 256.

././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/mode0000666000175100017510000005515213245511613034053 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function () { 'use strict'; var push = Array.prototype.push; angular .module('horizon.dashboard.project.lbaasv2') .factory('horizon.dashboard.project.lbaasv2.workflow.model', workflowModel); workflowModel.$inject = [ '$q', 'horizon.app.core.openstack-service-api.neutron', 'horizon.app.core.openstack-service-api.nova', 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.app.core.openstack-service-api.barbican', 'horizon.app.core.openstack-service-api.serviceCatalog', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc service * @name horizon.dashboard.project.lbaasv2.workflow.model * * @description * This is the M part of the MVC design pattern for the LBaaS wizard workflow. It is responsible * for providing data to the view of each step in the workflow and collecting the user's input * from the view. It is also the center point of communication between the UI and services API. * * @param $q The angular service for promises. * @param neutronAPI The neutron service API. * @param novaAPI The nova service API. * @param lbaasv2API The LBaaS V2 service API. * @param barbicanAPI The barbican service API. * @param serviceCatalog The keystone service catalog API. * @param gettext The horizon gettext function for translation. * @returns The model service for the create load balancer workflow. */ function workflowModel( $q, neutronAPI, novaAPI, lbaasv2API, barbicanAPI, serviceCatalog, gettext ) { var ports, keymanagerPromise; /** * @ngdoc model api object */ var model = { initializing: false, initialized: false, context: null, /** * @name spec * * @description * A dictionary like object containing specification collected from user * input. */ spec: null, visibleResources: [], subnets: [], members: [], listenerProtocols: ['HTTP', 'TCP', 'TERMINATED_HTTPS'], methods: ['LEAST_CONNECTIONS', 'ROUND_ROBIN', 'SOURCE_IP'], monitorTypes: ['HTTP', 'PING', 'TCP'], monitorMethods: ['GET', 'HEAD'], certificates: [], listenerPorts: [], /** * api methods for UI controllers */ initialize: initialize, submit: submit }; return model; /////////////// /** * @ngdoc method * @name workflowModel.initialize * @returns {promise} * * @description * Send request to get all data to initialize the model. * * @param resource Resource type being created / edited, one of 'loadbalancer', 'listener', * 'pool', 'monitor', or 'members'. * @param id ID of the resource being edited. */ function initialize(resource, id, loadBalancerId, parentResourceId) { var promise; model.certificatesError = false; model.context = { resource: resource, id: id, submit: null }; model.visibleResources = []; model.certificates = []; model.listenerPorts = []; model.spec = { loadbalancer_id: loadBalancerId, parentResourceId: parentResourceId, loadbalancer: { name: null, description: null, ip: null, subnet: null }, listener: { id: null, name: gettext('Listener 1'), description: null, protocol: null, port: null }, pool: { id: null, name: gettext('Pool 1'), description: null, protocol: null, method: null }, monitor: { id: null, type: null, interval: 5, retry: 3, timeout: 5, method: 'GET', status: '200', path: '/' }, members: [], certificates: [] }; if (!model.initializing) { model.initializing = true; promise = initializeResources(); } return promise; } function initializeResources() { var type = (model.context.id ? 'edit' : 'create') + model.context.resource; keymanagerPromise = serviceCatalog.ifTypeEnabled('key-manager'); if (type === 'createloadbalancer' || model.context.resource === 'listener') { keymanagerPromise.then(angular.noop, certificatesNotSupported); } var promise = { createloadbalancer: initCreateLoadBalancer, createlistener: initCreateListener, createpool: initCreatePool, createmonitor: initCreateMonitor, createmembers: initUpdateMemberList, editloadbalancer: initEditLoadBalancer, editlistener: initEditListener, editpool: initEditPool, editmonitor: initEditMonitor }[type](keymanagerPromise); return promise.then(onInitSuccess, onInitFail); } function onInitSuccess() { model.initializing = false; model.initialized = true; } function onInitFail() { model.initializing = false; model.initialized = false; } function initCreateLoadBalancer(keymanagerPromise) { model.context.submit = createLoadBalancer; return $q.all([ lbaasv2API.getLoadBalancers().then(onGetLoadBalancers), neutronAPI.getSubnets().then(onGetSubnets), neutronAPI.getPorts().then(onGetPorts), novaAPI.getServers().then(onGetServers), keymanagerPromise.then(prepareCertificates, angular.noop) ]).then(initMemberAddresses); } function initCreateListener(keymanagerPromise) { model.context.submit = createListener; return $q.all([ lbaasv2API.getListeners(model.spec.loadbalancer_id).then(onGetListeners), neutronAPI.getSubnets().then(onGetSubnets), neutronAPI.getPorts().then(onGetPorts), novaAPI.getServers().then(onGetServers), keymanagerPromise.then(prepareCertificates, angular.noop) ]).then(initMemberAddresses); } function initCreatePool() { model.context.submit = createPool; // We get the listener details here because we need to know the listener protocol // in order to default the new pool's protocol to match. return $q.all([ lbaasv2API.getListener(model.spec.parentResourceId).then(onGetListener), neutronAPI.getSubnets().then(onGetSubnets), neutronAPI.getPorts().then(onGetPorts), novaAPI.getServers().then(onGetServers) ]).then(initMemberAddresses); } function initCreateMonitor() { model.context.submit = createHealthMonitor; return $q.when(); } function initUpdateMemberList() { model.context.submit = updatePoolMemberList; return $q.all([ lbaasv2API.getPool(model.spec.parentResourceId).then(onGetPool), neutronAPI.getSubnets().then(onGetSubnets).then(getMembers).then(onGetMembers), neutronAPI.getPorts().then(onGetPorts), novaAPI.getServers().then(onGetServers) ]).then(initMemberAddresses); } function initEditLoadBalancer() { model.context.submit = editLoadBalancer; return $q.all([ lbaasv2API.getLoadBalancer(model.context.id).then(onGetLoadBalancer), neutronAPI.getSubnets().then(onGetSubnets) ]).then(initSubnet); } function initEditListener() { model.context.submit = editListener; return $q.all([ neutronAPI.getSubnets().then(onGetSubnets).then(getListener).then(onGetListener), neutronAPI.getPorts().then(onGetPorts), novaAPI.getServers().then(onGetServers) ]).then(initMemberAddresses); } function initEditPool() { model.context.submit = editPool; return $q.all([ neutronAPI.getSubnets().then(onGetSubnets).then(getPool).then(onGetPool), neutronAPI.getPorts().then(onGetPorts), novaAPI.getServers().then(onGetServers) ]).then(initMemberAddresses); } function initEditMonitor() { model.context.submit = editHealthMonitor; return lbaasv2API.getHealthMonitor(model.context.id).then(onGetHealthMonitor); } /** * @ngdoc method * @name workflowModel.submit * @returns {promise} * * @description * Send request for completing the wizard. * * @returns Response from the LBaaS V2 API. */ function submit() { var finalSpec = angular.copy(model.spec); cleanFinalSpecLoadBalancer(finalSpec); cleanFinalSpecListener(finalSpec); cleanFinalSpecPool(finalSpec); cleanFinalSpecMembers(finalSpec); cleanFinalSpecMonitor(finalSpec); removeNulls(finalSpec); return model.context.submit(finalSpec); } function createLoadBalancer(spec) { return lbaasv2API.createLoadBalancer(spec); } function createListener(spec) { return lbaasv2API.createListener(spec); } function createPool(spec) { return lbaasv2API.createPool(spec); } function createHealthMonitor(spec) { return lbaasv2API.createHealthMonitor(spec); } function editLoadBalancer(spec) { return lbaasv2API.editLoadBalancer(model.context.id, spec); } function editListener(spec) { return lbaasv2API.editListener(model.context.id, spec); } function editPool(spec) { return lbaasv2API.editPool(model.context.id, spec); } function editHealthMonitor(spec) { return lbaasv2API.editHealthMonitor(model.context.id, spec); } function updatePoolMemberList(spec) { return lbaasv2API.updateMemberList(model.spec.parentResourceId, spec); } function cleanFinalSpecLoadBalancer(finalSpec) { var context = model.context; // Load balancer requires subnet if (!finalSpec.loadbalancer.subnet) { delete finalSpec.loadbalancer; } else { finalSpec.loadbalancer.subnet = finalSpec.loadbalancer.subnet.id; } // Cannot edit the IP or subnet if (context.resource === 'loadbalancer' && context.id) { delete finalSpec.subnet; delete finalSpec.ip; } } function cleanFinalSpecListener(finalSpec) { if (!finalSpec.listener.protocol || !finalSpec.listener.port) { // Listener requires protocol and port delete finalSpec.listener; delete finalSpec.certificates; } else if (finalSpec.listener.protocol !== 'TERMINATED_HTTPS') { // Remove certificate containers if not using TERMINATED_HTTPS delete finalSpec.certificates; } else { var containers = []; angular.forEach(finalSpec.certificates, function(cert) { containers.push(cert.id); }); finalSpec.certificates = containers; } } function cleanFinalSpecPool(finalSpec) { // Pool requires method if (!finalSpec.pool.method) { delete finalSpec.pool; } else { // The pool protocol must be HTTP if the listener protocol is TERMINATED_HTTPS and // otherwise has to match it. var protocol = finalSpec.listener ? finalSpec.listener.protocol : finalSpec.pool.protocol; finalSpec.pool.protocol = protocol === 'TERMINATED_HTTPS' ? 'HTTP' : protocol; } } function cleanFinalSpecMembers(finalSpec) { if (finalSpec.members.length === 0) { delete finalSpec.members; return; } var members = []; angular.forEach(finalSpec.members, function cleanMember(member) { if (member.address && member.port) { var propsToRemove = ['name', 'description', 'addresses', 'allocatedMember']; propsToRemove.forEach(function deleteProperty(prop) { if (angular.isDefined(member[prop])) { delete member[prop]; } }); if (angular.isObject(member.address)) { member.subnet = member.address.subnet; member.address = member.address.ip; } else if (member.subnet) { member.subnet = member.subnet.id; } else { delete member.subnet; } members.push(member); } }); if (members.length > 0) { finalSpec.members = members; } else { delete finalSpec.members; } } function cleanFinalSpecMonitor(finalSpec) { // Monitor requires an interval, retry count, and timeout if (!angular.isNumber(finalSpec.monitor.interval) || !angular.isNumber(finalSpec.monitor.retry) || !angular.isNumber(finalSpec.monitor.timeout)) { delete finalSpec.monitor; return; } // Only include necessary monitor properties if (finalSpec.monitor.type !== 'HTTP') { delete finalSpec.monitor.method; delete finalSpec.monitor.status; delete finalSpec.monitor.path; } } function removeNulls(finalSpec) { angular.forEach(finalSpec, function deleteNullsForGroup(group, groupName) { angular.forEach(group, function deleteNullValue(value, key) { if (value === null) { delete finalSpec[groupName][key]; } }); }); } function onGetLoadBalancers(response) { var existingNames = {}; angular.forEach(response.data.items, function nameExists(lb) { existingNames[lb.name] = 1; }); var name; var index = response.data.items.length; do { index += 1; name = interpolate(gettext('Load Balancer %(index)s'), { index: index }, true); } while (name in existingNames); model.spec.loadbalancer.name = name; } function onGetListeners(response) { var existingNames = {}; angular.forEach(response.data.items, function nameExists(listener) { existingNames[listener.name] = 1; model.listenerPorts.push(listener.protocol_port); }); var name; var index = response.data.items.length; do { index += 1; name = interpolate(gettext('Listener %(index)s'), { index: index }, true); } while (name in existingNames); model.spec.listener.name = name; } function onGetSubnets(response) { model.subnets.length = 0; push.apply(model.subnets, response.data.items); } function onGetServers(response) { model.members.length = 0; var members = []; angular.forEach(response.data.items, function addMember(server) { // If the server is in a state where it does not have an IP address then we can't use it if (server.addresses && !angular.equals({}, server.addresses)) { members.push({ id: server.id, name: server.name, weight: 1 }); } }); push.apply(model.members, members); } function onGetPorts(response) { ports = response.data.items; } function onGetMembers(response) { setMembersSpec(response.data.items); } function initMemberAddresses() { angular.forEach(model.members, function initAddresses(member) { var memberPorts = ports.filter(function filterPortByDevice(port) { return port.device_id === member.id; }); member.addresses = []; angular.forEach(memberPorts, function addAddressesForPort(port) { angular.forEach(port.fixed_ips, function addAddress(ip) { member.addresses.push({ ip: ip.ip_address, subnet: ip.subnet_id }); }); }); member.address = member.addresses[0]; if (model.spec.pool.protocol) { member.port = {HTTP: 80}[model.spec.pool.protocol]; } }); } function getListener() { return lbaasv2API.getListener(model.context.id, true); } function getPool() { return lbaasv2API.getPool(model.context.id, true); } function getMembers() { return lbaasv2API.getMembers(model.spec.parentResourceId); } function onGetLoadBalancer(response) { var loadbalancer = response.data; setLoadBalancerSpec(loadbalancer); } function onGetListener(response) { var result = response.data; setListenerSpec(result.listener || result); if (result.listener) { model.visibleResources.push('listener'); model.spec.loadbalancer_id = result.listener.loadbalancers[0].id; if (result.listener.protocol === 'TERMINATED_HTTPS') { keymanagerPromise.then(prepareCertificates).then(function addAvailableCertificates() { result.listener.sni_container_refs.forEach(function addAvailableCertificate(ref) { model.certificates.filter(function matchCertificate(cert) { return cert.id === ref; }).forEach(function addCertificate(cert) { model.spec.certificates.push(cert); }); }); }); model.visibleResources.push('certificates'); } } if (result.pool) { setPoolSpec(result.pool); model.visibleResources.push('pool'); model.visibleResources.push('members'); if (result.members) { setMembersSpec(result.members); } if (result.monitor) { setMonitorSpec(result.monitor); model.visibleResources.push('monitor'); } } } function onGetPool(response) { var result = response.data; setPoolSpec(result.pool || result); if (result.pool) { model.visibleResources.push('pool'); model.visibleResources.push('members'); if (result.members) { setMembersSpec(result.members); } if (result.monitor) { setMonitorSpec(result.monitor); model.visibleResources.push('monitor'); } } } function setLoadBalancerSpec(loadbalancer) { var spec = model.spec.loadbalancer; spec.name = loadbalancer.name; spec.description = loadbalancer.description; spec.ip = loadbalancer.vip_address; spec.subnet = loadbalancer.vip_subnet_id; } function setListenerSpec(listener) { var spec = model.spec.listener; spec.id = listener.id; spec.name = listener.name; spec.description = listener.description; spec.protocol = listener.protocol; spec.port = listener.protocol_port; } function setPoolSpec(pool) { var spec = model.spec.pool; spec.id = pool.id; spec.name = pool.name; spec.description = pool.description; spec.protocol = pool.protocol; spec.method = pool.lb_algorithm; } function setMembersSpec(membersList) { model.spec.members.length = 0; var members = []; angular.forEach(membersList, function addMember(member) { members.push({ id: member.id, address: member.address, subnet: mapSubnetObj(member.subnet_id), port: member.protocol_port, weight: member.weight, allocatedMember: true }); }); push.apply(model.spec.members, members); } function setMonitorSpec(monitor) { var spec = model.spec.monitor; spec.id = monitor.id; spec.type = monitor.type; spec.interval = monitor.delay; spec.timeout = monitor.timeout; spec.retry = monitor.max_retries; spec.method = monitor.http_method; spec.status = monitor.expected_codes; spec.path = monitor.url_path; } function onGetHealthMonitor(response) { setMonitorSpec(response.data); } function prepareCertificates() { return $q.all([ barbicanAPI.getCertificates(true), barbicanAPI.getSecrets(true) ]).then(onGetCertificates, certificatesError); } function onGetCertificates(results) { // To use the TERMINATED_HTTPS protocol with a listener, the LBaaS v2 API wants a default // container ref and a list of containers that hold TLS secrets. In barbican the container // object has a list of references to the secrets it holds. This assumes that each // certificate container has exactly one certificate and private key. We fetch both the // certificate containers and the secrets so that we can display the secret names and // expirations dates. model.certificates.length = 0; var certificates = []; // Only accept containers that have both a certificate and private_key ref var containers = results[0].data.items.filter(function validateContainer(container) { container.refs = {}; container.secret_refs.forEach(function(ref) { container.refs[ref.name] = ref.secret_ref; }); return 'certificate' in container.refs && 'private_key' in container.refs; }); var secrets = {}; results[1].data.items.forEach(function addSecret(secret) { secrets[secret.secret_ref] = secret; }); containers.forEach(function addCertificateContainer(container) { var secret = secrets[container.refs.certificate]; certificates.push({ id: container.container_ref, name: secret.name || secret.secret_ref.split('/').reverse()[0], expiration: secret.expiration }); }); push.apply(model.certificates, certificates); } function initSubnet() { var subnet = model.subnets.filter(function filterSubnetsByLoadBalancer(s) { return s.id === model.spec.loadbalancer.subnet; })[0]; model.spec.loadbalancer.subnet = subnet; } function mapSubnetObj(subnetId) { var subnet = model.subnets.filter(function mapSubnet(subnet) { return subnet.id === subnetId; }); return subnet[0]; } function certificatesNotSupported() { // This function is called if the key-manager service is not available. In that case we // cannot support the TERMINATED_HTTPS listener protocol so we hide the option if creating // a new load balancer or listener. However for editing we still need it. if (!model.context.id) { model.listenerProtocols.splice(2, 1); } } function certificatesError() { // This function is called if there is an error fetching the certificate containers or // secrets. In that case we cannot support the TERMINATED_HTTPS listener protocol but we // want to make the user aware of the error. model.certificatesError = true; } } })(); ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000775000175100017510000000000013245512321034052 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000666000175100017510000000273013245511613034063 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('Monitor Details Step', function() { beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); describe('MonitorDetailsController', function() { var ctrl; beforeEach(inject(function($controller) { ctrl = $controller('MonitorDetailsController'); })); it('should define error messages for invalid fields', function() { expect(ctrl.intervalError).toBeDefined(); expect(ctrl.retryError).toBeDefined(); expect(ctrl.timeoutError).toBeDefined(); expect(ctrl.statusError).toBeDefined(); expect(ctrl.pathError).toBeDefined(); }); it('should define patterns for field validation', function() { expect(ctrl.statusPattern).toBeDefined(); expect(ctrl.urlPathPattern).toBeDefined(); }); }); }); })(); ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.help.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000666000175100017510000000235613245511613034067 0ustar zuulzuul00000000000000

The health monitor is used to determine the health of your pool members. Health checks routinely run against each member within the pool and the result of the health check is used to determine if the member receives new connections. Each pool can only have one health monitor.

Interval: The interval between health checks. Must be greater than or equal to the timeout.

Retries: The number of allowed connection failures before marking the member as inactive. Must be a number from 1 to 10.

Timeout: The time after which a health check times out. Must be a number greater than or equal to 0 and less than or equal to the interval.

HTTP method: The HTTP method used to perform the health check.

Expected status codes: The expected HTTP status codes to get from a successful health check. Must be a single number, a comma separated list of numbers, or a range (two numbers separated by a hyphen).

URL path: The target of the health check HTTP request to the member. Must be a valid URL path.

././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000666000175100017510000000373613245511613034072 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2') .controller('MonitorDetailsController', MonitorDetailsController); MonitorDetailsController.$inject = [ 'horizon.dashboard.project.lbaasv2.patterns', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc controller * @name MonitorDetailsController * @description * The `MonitorDetailsController` controller provides functions for * configuring the health monitor step of the LBaaS wizard. * @param patterns The LBaaS v2 patterns constant. * @param gettext The horizon gettext function for translation. * @returns undefined */ function MonitorDetailsController(patterns, gettext) { var ctrl = this; // Error text for invalid fields /* eslint-disable max-len */ ctrl.intervalError = gettext('The health check interval must be greater than or equal to the timeout.'); /* eslint-enable max-len */ ctrl.retryError = gettext('The max retry count must be a number between 1 and 10.'); ctrl.timeoutError = gettext('The timeout must be a number greater than or equal to 0.'); ctrl.statusError = gettext('The expected status code is not valid.'); ctrl.pathError = gettext('The URL path is not valid.'); // HTTP status codes validation pattern ctrl.statusPattern = patterns.httpStatusCodes; ctrl.urlPathPattern = patterns.urlPath; } })(); ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000666000175100017510000001130513245511613034061 0ustar zuulzuul00000000000000

Provide the details for the health monitor.

{$ ::ctrl.intervalError $}
{$ ::ctrl.retryError $}
{$ ::ctrl.timeoutError $}
{$ ::ctrl.statusError $}
{$ ::ctrl.pathError $}
././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/workflow.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/work0000666000175100017510000000717613245511613034114 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2') .factory('horizon.dashboard.project.lbaasv2.workflow.workflow', lbaasWorkflow); lbaasWorkflow.$inject = [ 'horizon.dashboard.project.lbaasv2.basePath', 'horizon.app.core.workflow.factory', 'horizon.framework.util.i18n.gettext' ]; function lbaasWorkflow(basePath, dashboardWorkflow, gettext) { var workflowSteps = [ { id: 'loadbalancer', title: gettext('Load Balancer Details'), templateUrl: basePath + 'workflow/loadbalancer/loadbalancer.html', helpUrl: basePath + 'workflow/loadbalancer/loadbalancer.help.html', formName: 'loadBalancerDetailsForm' }, { id: 'listener', title: gettext('Listener Details'), templateUrl: basePath + 'workflow/listener/listener.html', helpUrl: basePath + 'workflow/listener/listener.help.html', formName: 'listenerDetailsForm' }, { id: 'pool', title: gettext('Pool Details'), templateUrl: basePath + 'workflow/pool/pool.html', helpUrl: basePath + 'workflow/pool/pool.help.html', formName: 'poolDetailsForm' }, { id: 'members', title: gettext('Pool Members'), templateUrl: basePath + 'workflow/members/members.html', helpUrl: basePath + 'workflow/members/members.help.html', formName: 'memberDetailsForm' }, { id: 'monitor', title: gettext('Monitor Details'), templateUrl: basePath + 'workflow/monitor/monitor.html', helpUrl: basePath + 'workflow/monitor/monitor.help.html', formName: 'monitorDetailsForm' } ]; // This step is kept separate from the rest because it is only added to the workflow by // the Listener Details step if the TERMINATED_HTTPS protocol is selected. var certificatesStep = { id: 'certificates', title: gettext('SSL Certificates'), templateUrl: basePath + 'workflow/certificates/certificates.html', helpUrl: basePath + 'workflow/certificates/certificates.help.html', formName: 'certificateDetailsForm' }; return initWorkflow; function initWorkflow(title, icon, steps, promise) { var filteredSteps = steps ? workflowSteps.filter(function(step) { return steps.indexOf(step.id) > -1; }) : workflowSteps; // If a promise is provided then add a checkReadiness function to the first step so // that the workflow will not show until the promise is resolved. There must always // be at least one step in the workflow. if (promise) { filteredSteps[0] = angular.copy(filteredSteps[0]); filteredSteps[0].checkReadiness = function() { return promise; }; } return dashboardWorkflow({ title: title, btnText: { finish: title }, btnIcon: { finish: icon }, steps: filteredSteps, allSteps: workflowSteps, certificatesStep: certificatesStep }); } } })(); ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000775000175100017510000000000013245512321034063 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000666000175100017510000000522313245511613034074 0ustar zuulzuul00000000000000

Provide the details for the listener.

{$ ::ctrl.portNumberError $} {$ ::ctrl.portUniqueError $}
././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000666000175100017510000000762013245511613034077 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('Listener Details Step', function() { beforeEach(module('horizon.framework.util.i18n')); beforeEach(module('horizon.dashboard.project.lbaasv2')); describe('ListenerDetailsController', function() { var ctrl, workflow, listener, scope; beforeEach(inject(function($controller) { workflow = { steps: [{ id: 'listener' }], certificatesStep: { id: 'certificates' }, after: angular.noop, remove: angular.noop }; listener = { protocol: null, port: 80 }; scope = { model: { listenerPorts: [80], members: [{port: ''}, {port: ''}], spec: { listener: listener, members: [{port: ''}, {port: ''}] } }, workflow: workflow }; ctrl = $controller('ListenerDetailsController', { $scope: scope }); })); it('should define error messages for invalid fields', function() { expect(ctrl.portNumberError).toBeDefined(); expect(ctrl.portUniqueError).toBeDefined(); }); it('should show certificates step if selecting TERMINATED_HTTPS', function() { workflow.steps.push(workflow.certificatesStep); spyOn(workflow, 'after'); ctrl.protocolChange('TERMINATED_HTTPS'); expect(workflow.after).not.toHaveBeenCalled(); workflow.steps.splice(1, 1); ctrl.protocolChange('TERMINATED_HTTPS'); expect(workflow.after).toHaveBeenCalledWith('listener', workflow.certificatesStep); }); it('should hide certificates step if not selecting TERMINATED_HTTPS', function() { spyOn(workflow, 'remove'); ctrl.protocolChange('HTTP'); expect(workflow.remove).not.toHaveBeenCalled(); workflow.steps.push(workflow.certificatesStep); ctrl.protocolChange('HTTP'); expect(workflow.remove).toHaveBeenCalledWith('certificates'); }); it('should update port on protocol change to HTTP', function() { ctrl.protocolChange('HTTP'); expect(listener.port).toBe(81); }); it('should update port on protocol change to TERMINATED_HTTPS', function() { ctrl.protocolChange('TERMINATED_HTTPS'); expect(listener.port).toBe(443); }); it('should update port on protocol change to TCP', function() { ctrl.protocolChange('TCP'); expect(listener.port).toBeUndefined(); }); it('should update member ports on protocol change to TERMINATED_HTTPS', function() { ctrl.protocolChange('TERMINATED_HTTPS'); scope.model.members.concat(scope.model.spec.members).forEach(function(member) { expect(member.port).toBe(80); }); }); it('should update member ports on protocol change to HTTP', function() { ctrl.protocolChange('HTTP'); scope.model.members.concat(scope.model.spec.members).forEach(function(member) { expect(member.port).toBe(80); }); }); it('should update member ports on protocol change to TCP', function() { ctrl.protocolChange('TCP'); scope.model.members.concat(scope.model.spec.members).forEach(function(member) { expect(member.port).toBeUndefined(); }); }); }); }); })(); ././@LongLink0000000000000000000000000000017400000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.help.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000666000175100017510000000115413245511613034073 0ustar zuulzuul00000000000000

Each port that listens for traffic on a particular load balancer is configured separately and tied to the load balancer. Multiple listeners can be associated with the same load balancer but each must use a unique port.

Protocol: The protocol for which the front end listens. The TERMINATED_HTTPS protocol is only available if the key-manager service is enabled and you have authority to list certificate containers and secrets.

Port: The port on which the front end listens. Must be an integer from 1 to 65535.

././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000666000175100017510000000513313245511613034074 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2') .controller('ListenerDetailsController', ListenerDetailsController); ListenerDetailsController.$inject = [ '$scope', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc controller * @name ListenerDetailsController * @description * The `ListenerDetailsController` controller provides functions for * configuring the listener details step of the LBaaS wizard. * @param $scope The angular scope object. * @param gettext The horizon gettext function for translation. * @returns undefined */ function ListenerDetailsController($scope, gettext) { var ctrl = this; ctrl.protocolChange = protocolChange; // Error text for invalid fields ctrl.portNumberError = gettext('The port must be a number between 1 and 65535.'); ctrl.portUniqueError = gettext( 'The port must be unique among all listeners attached to this load balancer.'); //////////// function protocolChange(protocol) { var defaultPort = { HTTP: 80, TERMINATED_HTTPS: 443 }[protocol]; while (listenerPortExists(defaultPort)) { defaultPort += 1; } $scope.model.spec.listener.port = defaultPort; var members = $scope.model.members.concat($scope.model.spec.members); members.forEach(function setMemberPort(member) { member.port = { HTTP: 80, TERMINATED_HTTPS: 80 }[protocol]; }); var workflow = $scope.workflow; var certificates = workflow.steps.some(function checkCertificatesStep(step) { return step.id === 'certificates'; }); if (protocol === 'TERMINATED_HTTPS' && !certificates) { workflow.after('listener', workflow.certificatesStep); } else if (protocol !== 'TERMINATED_HTTPS' && certificates) { workflow.remove('certificates'); } } function listenerPortExists(port) { return $scope.model.listenerPorts.some(function(element) { return element === port; }); } } })(); ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool0000775000175100017510000000000013245512321034061 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool0000666000175100017510000000237513245511613034077 0ustar zuulzuul00000000000000

Provide the details for the pool.

././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.help.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool0000666000175100017510000000111313245511613034064 0ustar zuulzuul00000000000000

A pool represents a group of members over which the load balancing will be applied.

Method: The load balancer algorithm that distributes traffic to the pool members.

  • LEAST_CONNECTIONS: Allocates requests to the instance with the least number of active connections.
  • ROUND_ROBIN: Rotates requests evenly between multiple instances.
  • SOURCE_IP: Requests from a unique source IP address are consistently directed to the same instance.

././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/modal.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moda0000666000175100017510000000632413245511613034044 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Workflow Modal Service', function() { var modalService, modal, response; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets.toast')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { response = { data: { id: '1' } }; modal = { open: function() { return { result: { then: function(func) { func(response); } } }; } }; $provide.value('$uibModal', modal); })); beforeEach(inject(function ($injector) { modalService = $injector.get('horizon.dashboard.project.lbaasv2.workflow.modal'); })); it('should define an init function', function() { expect(modalService.init).toBeDefined(); }); describe('modalService "perform" function tests', function() { var toastService; beforeEach(inject(function ($injector) { toastService = $injector.get('horizon.framework.widgets.toast.service'); })); it('calls modal.open', function() { spyOn(modal, 'open').and.callThrough(); modalService.init({}).perform(); expect(modal.open).toHaveBeenCalled(); }); it('calls modal.open with expected values', function() { spyOn(modal, 'open').and.callThrough(); modalService.init({}).perform(); var args = modal.open.calls.argsFor(0)[0]; expect(args.backdrop).toBe('static'); expect(args.controller).toBeDefined(); expect(args.resolve).toBeDefined(); expect(args.resolve.launchContext).toBeDefined(); }); it('launchContext function returns argument passed to open function', function() { spyOn(modal, 'open').and.callThrough(); modalService.init({}).perform('foo'); var args = modal.open.calls.argsFor(0)[0]; expect(args.resolve.launchContext()).toBe('foo'); }); it('shows message upon success', function() { spyOn(toastService, 'add').and.callThrough(); modalService.init({ message: 'foo' }).perform(); expect(toastService.add).toHaveBeenCalledWith('success', 'foo'); }); it('handles response upon success', function() { spyOn(toastService, 'add').and.callThrough(); var args = { handle: angular.noop }; spyOn(args, 'handle'); modalService.init(args).perform(); expect(args.handle).toHaveBeenCalledWith(response); }); }); }); })(); ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/mode0000666000175100017510000022216413245511613034052 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Workflow Model Service', function() { var model, $q, scope, listenerResources, barbicanEnabled, certificatesError; var includeChildResources = true; beforeEach(module('horizon.framework.util.i18n')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(function() { listenerResources = { listener: { id: '1234', name: 'Listener 1', description: 'listener description', protocol: 'HTTP', protocol_port: 80, loadbalancers: [ { id: '1234' } ], sni_container_refs: ['container2'] }, pool: { id: '1234', name: 'Pool 1', protocol: 'HTTP', lb_algorithm: 'ROUND_ROBIN', description: 'pool description' }, members: [ { id: '1234', address: '1.2.3.4', subnet_id: 'subnet-1', protocol_port: 80, weight: 1 }, { id: '5678', address: '5.6.7.8', subnet_id: 'subnet-1', protocol_port: 80, weight: 1 } ], monitor: { id: '1234', type: 'HTTP', delay: 1, timeout: 1, max_retries: 1, http_method: 'POST', expected_codes: '200', url_path: '/test' } }; barbicanEnabled = true; certificatesError = false; }); beforeEach(module(function($provide) { $provide.value('horizon.app.core.openstack-service-api.lbaasv2', { getLoadBalancers: function() { var loadbalancers = [ { id: '1234', name: 'Load Balancer 1' }, { id: '5678', name: 'Load Balancer 2' }, { id: '9012', name: 'myLoadBalancer3' } ]; var deferred = $q.defer(); deferred.resolve({ data: { items: loadbalancers } }); return deferred.promise; }, getLoadBalancer: function() { var loadbalancer = { id: '1234', name: 'Load Balancer 1', vip_address: '1.2.3.4', vip_subnet_id: 'subnet-1', description: '' }; var deferred = $q.defer(); deferred.resolve({ data: loadbalancer }); return deferred.promise; }, getListeners: function() { var listeners = [ { id: '1234', name: 'Listener 1', protocol_port: 80 }, { id: '5678', name: 'Listener 2', protocol_port: 81 }, { id: '9012', name: 'myListener3', protocol_port: 82 } ]; var deferred = $q.defer(); deferred.resolve({ data: { items: listeners } }); return deferred.promise; }, getListener: function() { var deferred = $q.defer(); var listenerData; listenerData = includeChildResources ? listenerResources : listenerResources.listener; deferred.resolve({ data: listenerData }); return deferred.promise; }, getPool: function() { var poolResources = angular.copy(listenerResources); delete poolResources.listener; var deferred = $q.defer(); var poolData; poolData = includeChildResources ? poolResources : poolResources.pool; deferred.resolve({ data: poolData }); return deferred.promise; }, getMembers: function() { var members = [ { id: '1234', address: '1.2.3.4', subnet_id: 'subnet-1', protocol_port: 80, weight: 1 }, { id: '5678', address: '5.6.7.8', subnet_id: 'subnet-1', protocol_port: 80, weight: 1 }]; var deferred = $q.defer(); deferred.resolve({ data: { items: members } }); return deferred.promise; }, getHealthMonitor: function() { var monitor = { id: '1234', type: 'HTTP', delay: 1, timeout: 1, max_retries: 1, http_method: 'POST', expected_codes: '200', url_path: '/test' }; var deferred = $q.defer(); deferred.resolve({ data: monitor }); return deferred.promise; }, createLoadBalancer: function(spec) { return spec; }, editLoadBalancer: function(id, spec) { return spec; }, createListener: function(spec) { return spec; }, editListener: function(id, spec) { return spec; }, createPool: function(spec) { return spec; }, editPool: function(id, spec) { return spec; }, createHealthMonitor: function(spec) { return spec; }, editHealthMonitor: function(id, spec) { return spec; }, updateMemberList: function(id, spec) { return spec; } }); $provide.value('horizon.app.core.openstack-service-api.barbican', { getCertificates: function() { var containers = [ { container_ref: 'container1', secret_refs: [{name: 'certificate', secret_ref: 'secret1'}] }, { container_ref: 'container2', secret_refs: [{name: 'certificate', secret_ref: 'certificate1'}, {name: 'private_key', secret_ref: 'privatekey1'}] }, { container_ref: 'container3', secret_refs: [{name: 'certificate', secret_ref: 'certificate2'}, {name: 'private_key', secret_ref: 'privatekey2'}] } ]; var deferred = $q.defer(); if (certificatesError) { deferred.reject(); } else { deferred.resolve({ data: { items: containers } }); } return deferred.promise; }, getSecrets: function() { var secrets = [ { name: 'foo', expiration: '2016-03-26T21:10:45.417835', secret_ref: 'certificate1' },{ expiration: '2016-03-28T21:10:45.417835', secret_ref: 'certificate2' },{ secret_ref: 'privatekey1' },{ secret_ref: 'privatekey2' } ]; var deferred = $q.defer(); deferred.resolve({ data: { items: secrets } }); return deferred.promise; } }); $provide.value('horizon.app.core.openstack-service-api.neutron', { getSubnets: function() { var subnets = [ { id: 'subnet-1', name: 'subnet-1' }, { id: 'subnet-2', name: 'subnet-2' } ]; var deferred = $q.defer(); deferred.resolve({ data: { items: subnets } }); return deferred.promise; }, getPorts: function() { var ports = [ { device_id: '1', fixed_ips: [{ ip_address: '1.2.3.4', subnet_id: '1' }, { ip_address: '2.3.4.5', subnet_id: '2' }] }, { device_id: '2', fixed_ips: [{ ip_address: '3.4.5.6', subnet_id: '1' }, { ip_address: '4.5.6.7', subnet_id: '2' }] } ]; var deferred = $q.defer(); deferred.resolve({ data: { items: ports } }); return deferred.promise; } }); $provide.value('horizon.app.core.openstack-service-api.nova', { getServers: function() { var servers = [ { id: '1', name: 'server-1', addresses: { foo: 'bar' } }, { id: '2', name: 'server-2', addresses: { foo: 'bar' } }, { id: '3', name: 'server-3' }]; var deferred = $q.defer(); deferred.resolve({ data: { items: servers } }); return deferred.promise; } }); $provide.value('horizon.app.core.openstack-service-api.serviceCatalog', { ifTypeEnabled: function() { var deferred = $q.defer(); deferred[barbicanEnabled ? 'resolve' : 'reject'](); return deferred.promise; } }); })); beforeEach(inject(function ($injector) { model = $injector.get( 'horizon.dashboard.project.lbaasv2.workflow.model' ); $q = $injector.get('$q'); scope = $injector.get('$rootScope').$new(); })); describe('Initial model (pre-initialize)', function() { it('is defined', function() { expect(model).toBeDefined(); }); it('has initialization status parameters', function() { expect(model.initializing).toBeDefined(); expect(model.initialized).toBeDefined(); }); it('does not yet have a spec', function() { expect(model.spec).toBeNull(); }); it('has empty subnets array', function() { expect(model.subnets).toEqual([]); }); it('has empty members array', function() { expect(model.members).toEqual([]); }); it('has empty certificates array', function() { expect(model.certificates).toEqual([]); }); it('has empty listener ports array', function() { expect(model.listenerPorts).toEqual([]); }); it('has array of listener protocols', function() { expect(model.listenerProtocols).toEqual(['HTTP', 'TCP', 'TERMINATED_HTTPS']); }); it('has array of pool methods', function() { expect(model.methods).toEqual(['LEAST_CONNECTIONS', 'ROUND_ROBIN', 'SOURCE_IP']); }); it('has array of monitor types', function() { expect(model.monitorTypes).toEqual(['HTTP', 'PING', 'TCP']); }); it('has array of monitor methods', function() { expect(model.monitorMethods).toEqual(['GET', 'HEAD']); }); it('has an "initialize" function', function() { expect(model.initialize).toBeDefined(); }); it('has a "submit" function', function() { expect(model.submit).toBeDefined(); }); it('has a "context" object', function() { expect(model.context).toBeDefined(); }); }); describe('Post initialize model (create loadbalancer)', function() { beforeEach(function() { model.initialize('loadbalancer'); scope.$apply(); }); it('should initialize model properties', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(true); expect(model.subnets.length).toBe(2); expect(model.members.length).toBe(2); expect(model.certificates.length).toBe(2); expect(model.listenerPorts.length).toBe(0); expect(model.spec).toBeDefined(); expect(model.spec.loadbalancer_id).toBeUndefined(); expect(model.spec.loadbalancer).toBeDefined(); expect(model.spec.listener).toBeDefined(); expect(model.spec.pool).toBeDefined(); expect(model.spec.members).toEqual([]); expect(model.spec.certificates).toEqual([]); expect(model.spec.monitor).toBeDefined(); expect(model.certificatesError).toBe(false); }); it('should initialize names', function() { expect(model.spec.loadbalancer.name).toBe('Load Balancer 4'); expect(model.spec.listener.name).toBe('Listener 1'); expect(model.spec.pool.name).toBe('Pool 1'); }); it('should initialize context properties', function() { expect(model.context.resource).toBe('loadbalancer'); expect(model.context.id).toBeUndefined(); expect(model.context.submit).toBeDefined(); }); }); describe('Post initialize model (create listener)', function() { beforeEach(function() { model.initialize('listener', false, '1234'); scope.$apply(); }); it('should initialize model properties', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(true); expect(model.subnets.length).toBe(2); expect(model.members.length).toBe(2); expect(model.certificates.length).toBe(2); expect(model.listenerPorts.length).toBe(3); expect(model.spec).toBeDefined(); expect(model.spec.loadbalancer_id).toBe('1234'); expect(model.spec.loadbalancer).toBeDefined(); expect(model.spec.listener).toBeDefined(); expect(model.spec.pool).toBeDefined(); expect(model.spec.members).toEqual([]); expect(model.spec.certificates).toEqual([]); expect(model.spec.monitor).toBeDefined(); expect(model.certificatesError).toBe(false); }); it('should initialize names', function() { expect(model.spec.listener.name).toBe('Listener 4'); expect(model.spec.pool.name).toBe('Pool 1'); }); it('should initialize context properties', function() { expect(model.context.resource).toBe('listener'); expect(model.context.id).toBeFalsy(); expect(model.context.submit).toBeDefined(); }); }); describe('Post initialize model (create pool)', function() { beforeEach(function() { includeChildResources = false; model.initialize('pool', false, '1234', '5678'); scope.$apply(); }); it('should initialize model properties', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(true); expect(model.subnets.length).toBe(2); expect(model.members.length).toBe(2); expect(model.certificates.length).toBe(0); expect(model.listenerPorts.length).toBe(0); expect(model.spec).toBeDefined(); expect(model.spec.loadbalancer_id).toBe('1234'); expect(model.spec.parentResourceId).toBe('5678'); expect(model.spec.loadbalancer).toBeDefined(); expect(model.spec.listener).toBeDefined(); expect(model.spec.pool).toBeDefined(); expect(model.spec.members.length).toBe(0); expect(model.spec.certificates).toEqual([]); expect(model.spec.monitor).toBeDefined(); expect(model.certificatesError).toBe(false); }); it('should initialize names', function() { expect(model.spec.pool.name).toBe('Pool 1'); }); it('should initialize context properties', function() { expect(model.context.resource).toBe('pool'); expect(model.context.id).toBeFalsy(); expect(model.context.submit).toBeDefined(); }); }); describe('Post initialize model (create health monitor)', function() { beforeEach(function() { model.initialize('monitor', null, 'loadbalancer1', 'pool1'); scope.$apply(); }); it('should initialize model properties', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(true); expect(model.subnets.length).toBe(0); expect(model.members.length).toBe(0); expect(model.certificates.length).toBe(0); expect(model.listenerPorts.length).toBe(0); expect(model.spec.loadbalancer_id).toBe('loadbalancer1'); expect(model.spec.parentResourceId).toBe('pool1'); expect(model.spec.members.length).toBe(0); expect(model.spec.certificates).toEqual([]); expect(model.certificatesError).toBe(false); }); it('should initialize context properties', function() { expect(model.context.resource).toBe('monitor'); expect(model.context.id).toBeFalsy(); expect(model.context.submit.name).toBe('createHealthMonitor'); }); }); describe('Post initialize model (edit loadbalancer)', function() { beforeEach(function() { model.initialize('loadbalancer', '1234'); scope.$apply(); }); it('should initialize model properties', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(true); expect(model.subnets.length).toBe(2); expect(model.members.length).toBe(0); expect(model.certificates.length).toBe(0); expect(model.listenerPorts.length).toBe(0); expect(model.spec).toBeDefined(); expect(model.spec.loadbalancer_id).toBeUndefined(); expect(model.spec.loadbalancer).toBeDefined(); expect(model.spec.listener).toBeDefined(); expect(model.spec.pool).toBeDefined(); expect(model.spec.members).toEqual([]); expect(model.spec.certificates).toEqual([]); expect(model.spec.monitor).toBeDefined(); expect(model.certificatesError).toBe(false); }); it('should initialize loadbalancer model spec properties', function() { expect(model.spec.loadbalancer.name).toEqual('Load Balancer 1'); expect(model.spec.loadbalancer.description).toEqual(''); expect(model.spec.loadbalancer.ip).toEqual('1.2.3.4'); expect(model.spec.loadbalancer.subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' }); }); it('should not initialize listener model spec properties', function() { expect(model.spec.listener.id).toBeNull(); expect(model.spec.listener.name).toBe('Listener 1'); expect(model.spec.listener.description).toBeNull(); expect(model.spec.listener.protocol).toBeNull(); expect(model.spec.listener.port).toBeNull(); }); it('should not initialize pool model spec properties', function() { expect(model.spec.pool.id).toBeNull(); expect(model.spec.pool.name).toBe('Pool 1'); expect(model.spec.pool.description).toBeNull(); expect(model.spec.pool.protocol).toBeNull(); expect(model.spec.pool.method).toBeNull(); }); it('should initialize monitor model spec properties', function() { expect(model.spec.monitor.type).toBeNull(); expect(model.spec.monitor.interval).toBe(5); expect(model.spec.monitor.retry).toBe(3); expect(model.spec.monitor.timeout).toBe(5); expect(model.spec.monitor.method).toBe('GET'); expect(model.spec.monitor.status).toBe('200'); expect(model.spec.monitor.path).toBe('/'); }); it('should not initialize any members in the model spec', function() { expect(model.spec.members).toEqual([]); }); it('should initialize context', function() { expect(model.context.resource).toBe('loadbalancer'); expect(model.context.id).toBe('1234'); expect(model.context.submit).toBeDefined(); }); it('should initialize listener protocols', function() { expect(model.listenerProtocols.length).toBe(3); expect(model.listenerProtocols.indexOf('TERMINATED_HTTPS')).toBe(2); }); }); describe('Post initialize model (edit health monitor)', function() { beforeEach(function() { model.initialize('monitor', 'healthmonitor1'); scope.$apply(); }); it('should initialize model properties', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(true); expect(model.subnets.length).toBe(0); expect(model.members.length).toBe(0); expect(model.certificates.length).toBe(0); expect(model.listenerPorts.length).toBe(0); expect(model.spec.loadbalancer_id).toBeUndefined(); expect(model.spec.parentResourceId).toBeUndefined(); expect(model.spec.members.length).toBe(0); expect(model.spec.certificates).toEqual([]); expect(model.certificatesError).toBe(false); expect(model.spec.monitor.id).toBe('1234'); expect(model.spec.monitor.type).toBe('HTTP'); expect(model.spec.monitor.interval).toBe(1); expect(model.spec.monitor.timeout).toBe(1); expect(model.spec.monitor.retry).toBe(1); expect(model.spec.monitor.method).toBe('POST'); expect(model.spec.monitor.status).toBe('200'); expect(model.spec.monitor.path).toBe('/test'); }); it('should initialize context properties', function() { expect(model.context.resource).toBe('monitor'); expect(model.context.id).toBe('healthmonitor1'); expect(model.context.submit.name).toBe('editHealthMonitor'); }); }); describe('Post initialize model (without barbican)', function() { beforeEach(function() { barbicanEnabled = false; model.initialize('loadbalancer'); scope.$apply(); }); it('should initialize listener protocols', function() { expect(model.listenerProtocols.length).toBe(2); expect(model.listenerProtocols.indexOf('TERMINATED_HTTPS')).toBe(-1); }); }); describe('Post initialize model (certificates error)', function() { beforeEach(function() { certificatesError = true; model.initialize('loadbalancer'); scope.$apply(); }); it('should initialize listener protocols', function() { expect(model.certificates).toEqual([]); expect(model.certificatesError).toBe(true); }); }); describe('Post initialize model (edit listener)', function() { beforeEach(function() { includeChildResources = true; model.initialize('listener', '1234'); scope.$apply(); }); it('should initialize model properties', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(true); expect(model.subnets.length).toBe(2); expect(model.members.length).toEqual(2); expect(model.spec).toBeDefined(); expect(model.spec.loadbalancer_id).toBeDefined(); expect(model.spec.loadbalancer).toBeDefined(); expect(model.spec.listener).toBeDefined(); expect(model.spec.pool).toBeDefined(); expect(model.subnets.length).toBe(2); expect(model.spec.monitor).toBeDefined(); }); it('should initialize the loadbalancer_id property', function() { expect(model.spec.loadbalancer_id).toBe('1234'); }); it('should initialize all loadbalancer properties to null', function() { expect(model.spec.loadbalancer.name).toBeNull(); expect(model.spec.loadbalancer.description).toBeNull(); expect(model.spec.loadbalancer.ip).toBeNull(); expect(model.spec.loadbalancer.subnet).toBeNull(); }); it('should initialize all listener properties', function() { expect(model.spec.listener.id).toBe('1234'); expect(model.spec.listener.name).toBe('Listener 1'); expect(model.spec.listener.description).toBe('listener description'); expect(model.spec.listener.protocol).toBe('HTTP'); expect(model.spec.listener.port).toBe(80); }); it('should initialize all pool properties', function() { expect(model.spec.pool.id).toBe('1234'); expect(model.spec.pool.name).toBe('Pool 1'); expect(model.spec.pool.description).toBe('pool description'); expect(model.spec.pool.protocol).toBe('HTTP'); expect(model.spec.pool.method).toBe('ROUND_ROBIN'); }); it('should initialize all monitor properties', function() { expect(model.spec.monitor.id).toBe('1234'); expect(model.spec.monitor.type).toBe('HTTP'); expect(model.spec.monitor.interval).toBe(1); expect(model.spec.monitor.retry).toBe(1); expect(model.spec.monitor.timeout).toBe(1); expect(model.spec.monitor.method).toBe('POST'); expect(model.spec.monitor.status).toBe('200'); expect(model.spec.monitor.path).toBe('/test'); }); it('should initialize members and properties', function() { expect(model.spec.members[0].id).toBe('1234'); expect(model.spec.members[0].address).toBe('1.2.3.4'); expect(model.spec.members[0].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' }); expect(model.spec.members[0].port).toBe(80); expect(model.spec.members[0].weight).toBe(1); expect(model.spec.members[1].id).toBe('5678'); expect(model.spec.members[1].address).toBe('5.6.7.8'); expect(model.spec.members[1].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' }); expect(model.spec.members[1].port).toBe(80); expect(model.spec.members[1].weight).toBe(1); }); it('should initialize context', function() { expect(model.context.resource).toBe('listener'); expect(model.context.id).toBeDefined(); expect(model.context.submit).toBeDefined(); }); }); describe('Post initialize model (edit pool)', function() { beforeEach(function() { includeChildResources = true; model.initialize('pool', '1234', 'loadbalancerId'); scope.$apply(); }); it('should initialize model properties', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(true); expect(model.subnets.length).toBe(2); expect(model.members.length).toEqual(2); expect(model.spec).toBeDefined(); expect(model.spec.loadbalancer_id).toBeDefined(); expect(model.spec.loadbalancer).toBeDefined(); expect(model.spec.listener).toBeDefined(); expect(model.spec.pool).toBeDefined(); expect(model.subnets.length).toBe(2); expect(model.spec.monitor).toBeDefined(); }); it('should initialize the loadbalancer_id property', function() { expect(model.spec.loadbalancer_id).toBe('loadbalancerId'); }); it('should initialize all loadbalancer properties to null', function() { expect(model.spec.loadbalancer.name).toBeNull(); expect(model.spec.loadbalancer.description).toBeNull(); expect(model.spec.loadbalancer.ip).toBeNull(); expect(model.spec.loadbalancer.subnet).toBeNull(); }); it('should initialize all listener properties to null', function() { expect(model.spec.listener.id).toBeNull(); expect(model.spec.listener.name).toBe('Listener 1'); expect(model.spec.listener.description).toBeNull(); expect(model.spec.listener.protocol).toBeNull(); expect(model.spec.listener.port).toBeNull(); }); it('should initialize all pool properties', function() { expect(model.spec.pool.id).toBe('1234'); expect(model.spec.pool.name).toBe('Pool 1'); expect(model.spec.pool.description).toBe('pool description'); expect(model.spec.pool.protocol).toBe('HTTP'); expect(model.spec.pool.method).toBe('ROUND_ROBIN'); }); it('should initialize all monitor properties', function() { expect(model.spec.monitor.id).toBe('1234'); expect(model.spec.monitor.type).toBe('HTTP'); expect(model.spec.monitor.interval).toBe(1); expect(model.spec.monitor.retry).toBe(1); expect(model.spec.monitor.timeout).toBe(1); expect(model.spec.monitor.method).toBe('POST'); expect(model.spec.monitor.status).toBe('200'); expect(model.spec.monitor.path).toBe('/test'); }); it('should initialize members and properties', function() { expect(model.spec.members[0].id).toBe('1234'); expect(model.spec.members[0].address).toBe('1.2.3.4'); expect(model.spec.members[0].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' }); expect(model.spec.members[0].port).toBe(80); expect(model.spec.members[0].weight).toBe(1); expect(model.spec.members[1].id).toBe('5678'); expect(model.spec.members[1].address).toBe('5.6.7.8'); expect(model.spec.members[1].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' }); expect(model.spec.members[1].port).toBe(80); expect(model.spec.members[1].weight).toBe(1); }); it('should initialize context', function() { expect(model.context.resource).toBe('pool'); expect(model.context.id).toBeDefined(); expect(model.context.submit).toBeDefined(); }); }); describe('Post initialize model (update member list)', function() { beforeEach(function() { includeChildResources = false; model.initialize('members', false, 'loadbalancerId', 'poolId'); scope.$apply(); }); it('should initialize model properties', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(true); expect(model.subnets.length).toBe(2); expect(model.members.length).toEqual(2); expect(model.spec).toBeDefined(); expect(model.spec.loadbalancer_id).toBeDefined(); expect(model.spec.loadbalancer).toBeDefined(); expect(model.spec.listener).toBeDefined(); expect(model.spec.pool).toBeDefined(); expect(model.subnets.length).toBe(2); expect(model.spec.monitor).toBeDefined(); }); it('should initialize the loadbalancer_id property', function() { expect(model.spec.loadbalancer_id).toBe('loadbalancerId'); }); it('should initialize all loadbalancer properties to null', function() { expect(model.spec.loadbalancer.name).toBeNull(); expect(model.spec.loadbalancer.description).toBeNull(); expect(model.spec.loadbalancer.ip).toBeNull(); expect(model.spec.loadbalancer.subnet).toBeNull(); }); it('should initialize all listener properties to null', function() { expect(model.spec.listener.id).toBeNull(); expect(model.spec.listener.name).toBe('Listener 1'); expect(model.spec.listener.description).toBeNull(); expect(model.spec.listener.protocol).toBeNull(); expect(model.spec.listener.port).toBeNull(); }); it('should initialize all pool properties', function() { expect(model.spec.pool.id).toBe('1234'); expect(model.spec.pool.name).toBe('Pool 1'); expect(model.spec.pool.description).toBe('pool description'); expect(model.spec.pool.protocol).toBe('HTTP'); expect(model.spec.pool.method).toBe('ROUND_ROBIN'); }); it('should initialize all monitor properties to null', function() { expect(model.spec.monitor.id).toBeNull(); expect(model.spec.monitor.type).toBeNull(); expect(model.spec.monitor.interval).toBe(5); expect(model.spec.monitor.retry).toBe(3); expect(model.spec.monitor.timeout).toBe(5); expect(model.spec.monitor.method).toBe('GET'); expect(model.spec.monitor.status).toBe('200'); expect(model.spec.monitor.path).toBe('/'); }); it('should initialize members and properties', function() { expect(model.spec.members[0].id).toBe('1234'); expect(model.spec.members[0].address).toBe('1.2.3.4'); expect(model.spec.members[0].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' }); expect(model.spec.members[0].port).toBe(80); expect(model.spec.members[0].weight).toBe(1); expect(model.spec.members[1].id).toBe('5678'); expect(model.spec.members[1].address).toBe('5.6.7.8'); expect(model.spec.members[1].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' }); expect(model.spec.members[1].port).toBe(80); expect(model.spec.members[1].weight).toBe(1); }); it('should initialize context', function() { expect(model.context.resource).toBe('members'); expect(model.context.id).toBeFalsy(); expect(model.context.submit).toBeDefined(); }); }); describe('Post initialize model (edit listener TERMINATED_HTTPS)', function() { beforeEach(function() { includeChildResources = true; listenerResources.listener.protocol = 'TERMINATED_HTTPS'; model.initialize('listener', '1234'); scope.$apply(); }); it('should initialize certificates', function() { expect(model.certificates.length).toBe(2); expect(model.spec.certificates.length).toBe(1); expect(model.spec.certificates[0].id).toBe('container2'); }); }); describe('Post initialize model (edit listener TERMINATED_HTTPS no barbican)', function() { beforeEach(function() { listenerResources.listener.protocol = 'TERMINATED_HTTPS'; barbicanEnabled = false; model.initialize('listener', '1234'); scope.$apply(); }); it('should initialize certificates', function() { expect(model.certificates.length).toBe(0); expect(model.spec.certificates.length).toBe(0); expect(model.spec.listener.protocol).toBe('TERMINATED_HTTPS'); }); }); describe('Post initialize model - Initializing', function() { beforeEach(function() { model.initializing = true; model.initialize('loadbalancer'); scope.$apply(); }); // This is here to ensure that as people add/change spec properties, they don't forget // to implement tests for them. it('has the right number of properties', function() { expect(Object.keys(model.spec).length).toBe(8); expect(Object.keys(model.spec.loadbalancer).length).toBe(4); expect(Object.keys(model.spec.listener).length).toBe(5); expect(Object.keys(model.spec.pool).length).toBe(5); expect(Object.keys(model.spec.monitor).length).toBe(8); expect(model.spec.members).toEqual([]); }); it('sets load balancer ID to undefined', function() { expect(model.spec.loadbalancer_id).toBeUndefined(); }); it('sets parent resource ID to undefined', function() { expect(model.spec.parentResourceId).toBeUndefined(); }); it('sets load balancer name to null', function() { expect(model.spec.loadbalancer.name).toBeNull(); }); it('sets load balancer description to null', function() { expect(model.spec.loadbalancer.description).toBeNull(); }); it('sets load balancer ip address to null', function() { expect(model.spec.loadbalancer.ip).toBeNull(); }); it('sets load balancer subnet to null', function() { expect(model.spec.loadbalancer.subnet).toBeNull(); }); it('sets listener id to null', function() { expect(model.spec.listener.id).toBeNull(); }); it('sets listener name to reasonable default', function() { expect(model.spec.listener.name).toBe('Listener 1'); }); it('sets listener description to null', function() { expect(model.spec.listener.description).toBeNull(); }); it('sets listener protocol to null', function() { expect(model.spec.listener.protocol).toBeNull(); }); it('sets listener port to null', function() { expect(model.spec.listener.port).toBeNull(); }); it('sets pool id to null', function() { expect(model.spec.pool.id).toBeNull(); }); it('sets pool name to reasonable default', function() { expect(model.spec.pool.name).toBe('Pool 1'); }); it('sets pool description to null', function() { expect(model.spec.pool.description).toBeNull(); }); it('sets pool protocol to null', function() { expect(model.spec.pool.protocol).toBeNull(); }); it('sets pool method to null', function() { expect(model.spec.pool.method).toBeNull(); }); it('sets monitor id to null', function() { expect(model.spec.monitor.id).toBeNull(); }); it('sets monitor type to null', function() { expect(model.spec.monitor.type).toBeNull(); }); it('sets monitor interval to 5', function() { expect(model.spec.monitor.interval).toBe(5); }); it('sets monitor retry count to 3', function() { expect(model.spec.monitor.retry).toBe(3); }); it('sets monitor timeout to 5', function() { expect(model.spec.monitor.timeout).toBe(5); }); it('sets monitor method to default', function() { expect(model.spec.monitor.method).toBe('GET'); }); it('sets monitor status code to default', function() { expect(model.spec.monitor.status).toBe('200'); }); it('sets monitor URL path to default', function() { expect(model.spec.monitor.path).toBe('/'); }); }); describe('Initialization failure', function() { beforeEach(inject(function ($injector) { var neutronAPI = $injector.get('horizon.app.core.openstack-service-api.neutron'); neutronAPI.getSubnets = function() { var deferred = $q.defer(); deferred.reject('Error'); return deferred.promise; }; })); beforeEach(function() { model.initialize('loadbalancer'); scope.$apply(); }); it('should fail to be initialized on subnets error', function() { expect(model.initializing).toBe(false); expect(model.initialized).toBe(false); expect(model.spec.loadbalancer.name).toBe('Load Balancer 4'); expect(model.subnets).toEqual([]); }); }); describe('context (create loadbalancer)', function() { beforeEach(function() { model.initialize('loadbalancer'); scope.$apply(); }); it('should initialize context', function() { expect(model.context.resource).toBe('loadbalancer'); expect(model.context.id).toBeUndefined(); expect(model.context.submit.name).toBe('createLoadBalancer'); }); }); describe('context (edit loadbalancer)', function() { beforeEach(function() { model.initialize('loadbalancer', '1'); scope.$apply(); }); it('should initialize context', function() { expect(model.context.resource).toBe('loadbalancer'); expect(model.context.id).toBe('1'); expect(model.context.submit.name).toBe('editLoadBalancer'); }); }); describe('context (create listener)', function() { beforeEach(function() { model.initialize('listener', false, '1234'); scope.$apply(); }); it('should initialize context', function() { expect(model.context.resource).toBe('listener'); expect(model.context.id).toBeFalsy(); expect(model.context.submit.name).toBe('createListener'); }); }); describe('context (edit listener)', function() { beforeEach(function() { includeChildResources = true; model.initialize('listener', '1'); scope.$apply(); }); it('should initialize context', function() { expect(model.context.resource).toBe('listener'); expect(model.context.id).toBe('1'); expect(model.context.submit.name).toBe('editListener'); }); }); describe('context (create pool)', function() { beforeEach(function() { model.initialize('pool', false, '1234', '5678'); scope.$apply(); }); it('should initialize context', function() { expect(model.context.resource).toBe('pool'); expect(model.context.id).toBeFalsy(); expect(model.context.submit.name).toBe('createPool'); }); }); describe('context (edit pool)', function() { beforeEach(function() { includeChildResources = true; model.initialize('pool', 'poolId', 'loadbalancerId'); scope.$apply(); }); it('should initialize context', function() { expect(model.context.resource).toBe('pool'); expect(model.context.id).toBe('poolId'); expect(model.context.submit.name).toBe('editPool'); }); }); describe('context (update member list)', function() { beforeEach(function() { model.initialize('members', false, 'loadbalancerId', 'poolId'); scope.$apply(); }); it('should initialize context', function() { expect(model.context.resource).toBe('members'); expect(model.context.id).toBeFalsy(); expect(model.context.submit.name).toBe('updatePoolMemberList'); }); }); describe('Model submit function (create loadbalancer)', function() { beforeEach(function() { model.initialize('loadbalancer'); scope.$apply(); }); it('should set final spec properties', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'TCP'; model.spec.listener.port = 80; model.spec.pool.name = 'pool name'; model.spec.pool.description = 'pool description'; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.members = [{ address: { ip: '1.2.3.4', subnet: '1' }, addresses: [{ ip: '1.2.3.4', subnet: '1' }, { ip: '2.3.4.5', subnet: '2' }], id: '1', name: 'foo', port: 80, weight: 1 }, { id: 'external-member-0', address: '2.3.4.5', subnet: null, port: 80, weight: 1 }, { id: 'external-member-1', address: null, subnet: null, port: 80, weight: 1 }, { id: 'external-member-2', address: '3.4.5.6', subnet: { id: '1' }, port: 80, weight: 1 }]; model.spec.monitor.type = 'PING'; model.spec.monitor.interval = 1; model.spec.monitor.retry = 1; model.spec.monitor.timeout = 1; model.spec.certificates = [{ id: 'container1', name: 'foo', expiration: '2015-03-26T21:10:45.417835' }]; var finalSpec = model.submit(); expect(finalSpec.loadbalancer.name).toBe('Load Balancer 4'); expect(finalSpec.loadbalancer.description).toBeUndefined(); expect(finalSpec.loadbalancer.ip).toBe('1.2.3.4'); expect(finalSpec.loadbalancer.subnet).toBe(model.subnets[0].id); expect(finalSpec.listener.name).toBe('Listener 1'); expect(finalSpec.listener.description).toBeUndefined(); expect(finalSpec.listener.protocol).toBe('TCP'); expect(finalSpec.listener.port).toBe(80); expect(finalSpec.pool.name).toBe('pool name'); expect(finalSpec.pool.description).toBe('pool description'); expect(finalSpec.pool.protocol).toBe('TCP'); expect(finalSpec.pool.method).toBe('LEAST_CONNECTIONS'); expect(finalSpec.members.length).toBe(3); expect(finalSpec.members[0].address).toBe('1.2.3.4'); expect(finalSpec.members[0].subnet).toBe('1'); expect(finalSpec.members[0].port).toBe(80); expect(finalSpec.members[0].weight).toBe(1); expect(finalSpec.members[0].id).toBe('1'); expect(finalSpec.members[0].addresses).toBeUndefined(); expect(finalSpec.members[0].name).toBeUndefined(); expect(finalSpec.members[0].allocatedMember).toBeUndefined(); expect(finalSpec.members[1].id).toBe('external-member-0'); expect(finalSpec.members[1].address).toBe('2.3.4.5'); expect(finalSpec.members[1].subnet).toBeUndefined(); expect(finalSpec.members[1].port).toBe(80); expect(finalSpec.members[1].weight).toBe(1); expect(finalSpec.members[1].allocatedMember).toBeUndefined(); expect(finalSpec.members[2].id).toBe('external-member-2'); expect(finalSpec.members[2].address).toBe('3.4.5.6'); expect(finalSpec.members[2].subnet).toBe('1'); expect(finalSpec.members[2].port).toBe(80); expect(finalSpec.members[2].weight).toBe(1); expect(finalSpec.members[2].allocatedMember).toBeUndefined(); expect(finalSpec.monitor.type).toBe('PING'); expect(finalSpec.monitor.interval).toBe(1); expect(finalSpec.monitor.retry).toBe(1); expect(finalSpec.monitor.timeout).toBe(1); expect(finalSpec.certificates).toBeUndefined(); }); it('should set final spec certificates', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'TERMINATED_HTTPS'; model.spec.listener.port = 443; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.certificates = [{ id: 'container1', name: 'foo', expiration: '2015-03-26T21:10:45.417835' }]; var finalSpec = model.submit(); expect(finalSpec.loadbalancer.name).toBe('Load Balancer 4'); expect(finalSpec.loadbalancer.description).toBeUndefined(); expect(finalSpec.loadbalancer.ip).toBe('1.2.3.4'); expect(finalSpec.loadbalancer.subnet).toBe(model.subnets[0].id); expect(finalSpec.listener.name).toBe('Listener 1'); expect(finalSpec.listener.description).toBeUndefined(); expect(finalSpec.listener.protocol).toBe('TERMINATED_HTTPS'); expect(finalSpec.listener.port).toBe(443); expect(finalSpec.pool.protocol).toBe('HTTP'); expect(finalSpec.certificates).toEqual(['container1']); }); it('should delete load balancer if any required property is not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeUndefined(); }); it('should delete listener if any required property is not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeUndefined(); expect(finalSpec.pool).toBeUndefined(); }); it('should delete certificates if not using TERMINATED_HTTPS', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.certificates = [{id: '1'}]; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.certificates).toBeUndefined(); }); it('should delete pool if any required property is not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeUndefined(); }); it('should delete members if none selected', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.pool.method = 'LEAST_CONNECTIONS'; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeDefined(); expect(finalSpec.members).toBeUndefined(); }); it('should delete members if no members are valid', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.members = [{ id: 'foo', address: '2.3.4.5', weight: 1 }]; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeDefined(); expect(finalSpec.members).toBeUndefined(); }); it('should delete monitor if any required property not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.monitor.type = 'PING'; model.spec.monitor.interval = 1; model.spec.monitor.retry = 1; model.spec.monitor.timeout = null; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeDefined(); expect(finalSpec.members).toBeUndefined(); expect(finalSpec.monitor).toBeUndefined(); }); }); describe('Model submit function (edit loadbalancer)', function() { beforeEach(function() { model.initialize('loadbalancer', '1234'); scope.$apply(); }); it('should set final spec properties', function() { model.spec.loadbalancer.description = 'new description'; var finalSpec = model.submit(); expect(finalSpec.loadbalancer.name).toBe('Load Balancer 1'); expect(finalSpec.loadbalancer.description).toBe('new description'); expect(finalSpec.loadbalancer.ip).toBe('1.2.3.4'); expect(finalSpec.loadbalancer.subnet).toBe('subnet-1'); }); }); describe('Model submit function (create listener)', function() { beforeEach(function() { model.initialize('listener', false, '1234'); scope.$apply(); }); it('should set final spec properties', function() { model.spec.listener.protocol = 'TCP'; model.spec.listener.port = 80; model.spec.pool.name = 'pool name'; model.spec.pool.description = 'pool description'; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.members = [{ address: { ip: '1.2.3.4', subnet: '1' }, addresses: [{ ip: '1.2.3.4', subnet: '1' }, { ip: '2.3.4.5', subnet: '2' }], id: '1', name: 'foo', port: 80, weight: 1 }, { id: 'external-member-0', address: '2.3.4.5', subnet: null, port: 80, weight: 1 }, { id: 'external-member-1', address: null, subnet: null, port: 80, weight: 1 }, { id: 'external-member-2', address: '3.4.5.6', subnet: { id: '1' }, port: 80, weight: 1 }]; model.spec.monitor.type = 'PING'; model.spec.monitor.interval = 1; model.spec.monitor.retry = 1; model.spec.monitor.timeout = 1; model.spec.certificates = [{ id: 'container1', name: 'foo', expiration: '2015-03-26T21:10:45.417835' }]; var finalSpec = model.submit(); expect(finalSpec.listener.name).toBe('Listener 4'); expect(finalSpec.listener.description).toBeUndefined(); expect(finalSpec.listener.protocol).toBe('TCP'); expect(finalSpec.listener.port).toBe(80); expect(finalSpec.pool.name).toBe('pool name'); expect(finalSpec.pool.description).toBe('pool description'); expect(finalSpec.pool.protocol).toBe('TCP'); expect(finalSpec.pool.method).toBe('LEAST_CONNECTIONS'); expect(finalSpec.members.length).toBe(3); expect(finalSpec.members[0].address).toBe('1.2.3.4'); expect(finalSpec.members[0].subnet).toBe('1'); expect(finalSpec.members[0].port).toBe(80); expect(finalSpec.members[0].weight).toBe(1); expect(finalSpec.members[0].id).toBe('1'); expect(finalSpec.members[0].addresses).toBeUndefined(); expect(finalSpec.members[0].name).toBeUndefined(); expect(finalSpec.members[0].allocatedMember).toBeUndefined(); expect(finalSpec.members[1].id).toBe('external-member-0'); expect(finalSpec.members[1].address).toBe('2.3.4.5'); expect(finalSpec.members[1].subnet).toBeUndefined(); expect(finalSpec.members[1].port).toBe(80); expect(finalSpec.members[1].weight).toBe(1); expect(finalSpec.members[1].allocatedMember).toBeUndefined(); expect(finalSpec.members[2].id).toBe('external-member-2'); expect(finalSpec.members[2].address).toBe('3.4.5.6'); expect(finalSpec.members[2].subnet).toBe('1'); expect(finalSpec.members[2].port).toBe(80); expect(finalSpec.members[2].weight).toBe(1); expect(finalSpec.members[2].allocatedMember).toBeUndefined(); expect(finalSpec.monitor.type).toBe('PING'); expect(finalSpec.monitor.interval).toBe(1); expect(finalSpec.monitor.retry).toBe(1); expect(finalSpec.monitor.timeout).toBe(1); expect(finalSpec.certificates).toBeUndefined(); }); it('should set final spec certificates', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'TERMINATED_HTTPS'; model.spec.listener.port = 443; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.certificates = [{ id: 'container1', name: 'foo', expiration: '2015-03-26T21:10:45.417835' }]; var finalSpec = model.submit(); expect(finalSpec.listener.name).toBe('Listener 4'); expect(finalSpec.listener.description).toBeUndefined(); expect(finalSpec.listener.protocol).toBe('TERMINATED_HTTPS'); expect(finalSpec.listener.port).toBe(443); expect(finalSpec.pool.protocol).toBe('HTTP'); expect(finalSpec.certificates).toEqual(['container1']); }); it('should delete listener if any required property is not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeUndefined(); expect(finalSpec.pool).toBeUndefined(); }); it('should delete certificates if not using TERMINATED_HTTPS', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.certificates = [{id: '1'}]; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.certificates).toBeUndefined(); }); it('should delete pool if any required property is not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeUndefined(); }); it('should delete members if none selected', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.pool.method = 'LEAST_CONNECTIONS'; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeDefined(); expect(finalSpec.members).toBeUndefined(); }); it('should delete members if no members are valid', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.members = [{ id: 'foo', address: '2.3.4.5', weight: 1 }]; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeDefined(); expect(finalSpec.members).toBeUndefined(); }); it('should delete monitor if any required property not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.monitor.type = 'PING'; model.spec.monitor.interval = 1; model.spec.monitor.retry = 1; model.spec.monitor.timeout = null; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeDefined(); expect(finalSpec.members).toBeUndefined(); expect(finalSpec.monitor).toBeUndefined(); }); }); describe('Model submit function (create pool)', function() { beforeEach(function() { includeChildResources = false; model.initialize('pool', false, '1234', '5678'); scope.$apply(); }); it('should set final spec properties', function() { model.spec.listener.protocol = 'TCP'; model.spec.pool.name = 'pool name'; model.spec.pool.description = 'pool description'; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.members = [{ address: { ip: '1.2.3.4', subnet: '1' }, addresses: [{ ip: '1.2.3.4', subnet: '1' }, { ip: '2.3.4.5', subnet: '2' }], id: '1', name: 'foo', port: 80, weight: 1 }, { id: 'external-member-0', address: '2.3.4.5', subnet: null, port: 80, weight: 1 }, { id: 'external-member-1', address: null, subnet: null, port: 80, weight: 1 }, { id: 'external-member-2', address: '3.4.5.6', subnet: { id: '1' }, port: 80, weight: 1 }]; model.spec.monitor.type = 'PING'; model.spec.monitor.interval = 1; model.spec.monitor.retry = 1; model.spec.monitor.timeout = 1; model.spec.certificates = [{ id: 'container1', name: 'foo', expiration: '2015-03-26T21:10:45.417835' }]; var finalSpec = model.submit(); expect(finalSpec.pool.name).toBe('pool name'); expect(finalSpec.pool.description).toBe('pool description'); expect(finalSpec.pool.protocol).toBe('TCP'); expect(finalSpec.pool.method).toBe('LEAST_CONNECTIONS'); expect(finalSpec.members.length).toBe(3); expect(finalSpec.members[0].address).toBe('1.2.3.4'); expect(finalSpec.members[0].subnet).toBe('1'); expect(finalSpec.members[0].port).toBe(80); expect(finalSpec.members[0].weight).toBe(1); expect(finalSpec.members[0].id).toBe('1'); expect(finalSpec.members[0].addresses).toBeUndefined(); expect(finalSpec.members[0].name).toBeUndefined(); expect(finalSpec.members[0].allocatedMember).toBeUndefined(); expect(finalSpec.members[1].id).toBe('external-member-0'); expect(finalSpec.members[1].address).toBe('2.3.4.5'); expect(finalSpec.members[1].subnet).toBeUndefined(); expect(finalSpec.members[1].port).toBe(80); expect(finalSpec.members[1].weight).toBe(1); expect(finalSpec.members[1].allocatedMember).toBeUndefined(); expect(finalSpec.members[2].id).toBe('external-member-2'); expect(finalSpec.members[2].address).toBe('3.4.5.6'); expect(finalSpec.members[2].subnet).toBe('1'); expect(finalSpec.members[2].port).toBe(80); expect(finalSpec.members[2].weight).toBe(1); expect(finalSpec.members[2].allocatedMember).toBeUndefined(); expect(finalSpec.monitor.type).toBe('PING'); expect(finalSpec.monitor.interval).toBe(1); expect(finalSpec.monitor.retry).toBe(1); expect(finalSpec.monitor.timeout).toBe(1); expect(finalSpec.certificates).toBeUndefined(); }); it('should delete listener if any required property is not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = ''; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeUndefined(); expect(finalSpec.pool).toBeUndefined(); }); it('should delete certificates if not using TERMINATED_HTTPS', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.certificates = [{id: '1'}]; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.certificates).toBeUndefined(); }); it('should delete pool if any required property is not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeUndefined(); }); it('should delete members if none selected', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.pool.method = 'LEAST_CONNECTIONS'; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeDefined(); expect(finalSpec.members).toBeUndefined(); }); it('should delete members if no members are valid', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.members = [{ id: 'foo', address: '2.3.4.5', weight: 1 }]; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeDefined(); expect(finalSpec.members).toBeUndefined(); }); it('should delete monitor if any required property not set', function() { model.spec.loadbalancer.ip = '1.2.3.4'; model.spec.loadbalancer.subnet = model.subnets[0]; model.spec.listener.protocol = 'HTTP'; model.spec.listener.port = 80; model.spec.pool.method = 'LEAST_CONNECTIONS'; model.spec.monitor.type = 'PING'; model.spec.monitor.interval = 1; model.spec.monitor.retry = 1; model.spec.monitor.timeout = null; var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeDefined(); expect(finalSpec.listener).toBeDefined(); expect(finalSpec.pool).toBeDefined(); expect(finalSpec.members).toBeUndefined(); expect(finalSpec.monitor).toBeUndefined(); }); }); describe('Model submit function (create health monitor)', function() { beforeEach(function() { model.initialize('monitor', null, 'loadbalancer1', 'pool1'); scope.$apply(); }); it('should set final spec properties', function() { model.spec.monitor.type = 'HTTP'; var finalSpec = model.submit(); expect(finalSpec.loadbalancer_id).toBe('loadbalancer1'); expect(finalSpec.parentResourceId).toBe('pool1'); expect(finalSpec.loadbalancer).toBeUndefined(); expect(finalSpec.listener).toBeUndefined(); expect(finalSpec.pool).toBeUndefined(); expect(finalSpec.members).toBeUndefined(); expect(finalSpec.certificates).toBeUndefined(); expect(finalSpec.monitor.type).toBe('HTTP'); expect(finalSpec.monitor.interval).toBe(5); expect(finalSpec.monitor.retry).toBe(3); expect(finalSpec.monitor.timeout).toBe(5); expect(finalSpec.monitor.method).toBe('GET'); expect(finalSpec.monitor.status).toBe('200'); expect(finalSpec.monitor.path).toBe('/'); }); }); describe('Model submit function (edit listener)', function() { beforeEach(function() { includeChildResources = true; model.initialize('listener', '1234'); scope.$apply(); }); it('should set final spec properties', function() { var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeUndefined(); expect(finalSpec.listener.name).toBe('Listener 1'); expect(finalSpec.listener.description).toBe('listener description'); expect(finalSpec.listener.protocol).toBe('HTTP'); expect(finalSpec.listener.port).toBe(80); expect(finalSpec.pool.name).toBe('Pool 1'); expect(finalSpec.pool.description).toBe('pool description'); expect(finalSpec.pool.protocol).toBe('HTTP'); expect(finalSpec.pool.method).toBe('ROUND_ROBIN'); expect(finalSpec.members.length).toBe(2); expect(finalSpec.members[0].id).toBe('1234'); expect(finalSpec.members[0].address).toBe('1.2.3.4'); expect(finalSpec.members[0].subnet).toBe('subnet-1'); expect(finalSpec.members[0].port).toBe(80); expect(finalSpec.members[0].weight).toBe(1); expect(finalSpec.members[1].id).toBe('5678'); expect(finalSpec.members[1].address).toBe('5.6.7.8'); expect(finalSpec.members[1].subnet).toBe('subnet-1'); expect(finalSpec.members[1].port).toBe(80); expect(finalSpec.members[1].weight).toBe(1); expect(finalSpec.monitor.type).toBe('HTTP'); expect(finalSpec.monitor.interval).toBe(1); expect(finalSpec.monitor.retry).toBe(1); expect(finalSpec.monitor.timeout).toBe(1); }); }); describe('Model submit function (edit pool)', function() { beforeEach(function() { includeChildResources = true; model.initialize('pool', 'poolId', 'loadbalancerId'); scope.$apply(); }); it('should set final spec properties', function() { var finalSpec = model.submit(); expect(finalSpec.loadbalancer).toBeUndefined(); expect(finalSpec.listener).toBeUndefined(); expect(finalSpec.pool.name).toBe('Pool 1'); expect(finalSpec.pool.description).toBe('pool description'); expect(finalSpec.pool.protocol).toBe('HTTP'); expect(finalSpec.pool.method).toBe('ROUND_ROBIN'); expect(finalSpec.members.length).toBe(2); expect(finalSpec.members[0].id).toBe('1234'); expect(finalSpec.members[0].address).toBe('1.2.3.4'); expect(finalSpec.members[0].subnet).toBe('subnet-1'); expect(finalSpec.members[0].port).toBe(80); expect(finalSpec.members[0].weight).toBe(1); expect(finalSpec.members[1].id).toBe('5678'); expect(finalSpec.members[1].address).toBe('5.6.7.8'); expect(finalSpec.members[1].subnet).toBe('subnet-1'); expect(finalSpec.members[1].port).toBe(80); expect(finalSpec.members[1].weight).toBe(1); expect(finalSpec.monitor.type).toBe('HTTP'); expect(finalSpec.monitor.interval).toBe(1); expect(finalSpec.monitor.retry).toBe(1); expect(finalSpec.monitor.timeout).toBe(1); }); }); describe('Model submit function (update member list)', function() { beforeEach(function() { includeChildResources = false; model.initialize('members', false, 'loadbalancerId', 'poolId'); scope.$apply(); }); it('should set final spec properties', function() { var finalSpec = model.submit(); expect(finalSpec.loadbalancer_id).toBe('loadbalancerId'); expect(finalSpec.parentResourceId).toBe('poolId'); expect(finalSpec.loadbalancer).toBeUndefined(); expect(finalSpec.listener).toBeUndefined(); expect(finalSpec.pool.name).toBe('Pool 1'); expect(finalSpec.pool.description).toBe('pool description'); expect(finalSpec.pool.protocol).toBe('HTTP'); expect(finalSpec.pool.method).toBe('ROUND_ROBIN'); expect(finalSpec.members.length).toBe(2); expect(finalSpec.members[0].id).toBe('1234'); expect(finalSpec.members[0].address).toBe('1.2.3.4'); expect(finalSpec.members[0].subnet).toBe('subnet-1'); expect(finalSpec.members[0].port).toBe(80); expect(finalSpec.members[0].weight).toBe(1); expect(finalSpec.members[1].id).toBe('5678'); expect(finalSpec.members[1].address).toBe('5.6.7.8'); expect(finalSpec.members[1].subnet).toBe('subnet-1'); expect(finalSpec.members[1].port).toBe(80); expect(finalSpec.members[1].weight).toBe(1); expect(finalSpec.monitor.interval).toBe(5); expect(finalSpec.monitor.retry).toBe(3); expect(finalSpec.monitor.timeout).toBe(5); }); }); describe('Model visible resources (edit pool, no pool in response)', function() { beforeEach(function() { includeChildResources = true; delete listenerResources.pool; model.initialize('pool', 'poolId', 'loadbalancerId'); scope.$apply(); }); it('should only show pool and monitor details', function() { expect(model.visibleResources).toEqual([]); }); }); describe('Model visible resources (edit pool, no existing members)', function() { beforeEach(function() { includeChildResources = true; delete listenerResources.listener; delete listenerResources.members; model.initialize('pool', 'poolId', 'loadbalancerId'); scope.$apply(); }); it('should only show pool and monitor details', function() { expect(model.visibleResources).toEqual(['pool', 'members', 'monitor']); }); }); describe('Model visible resources (edit pool, no monitor)', function() { beforeEach(function() { includeChildResources = true; delete listenerResources.listener; delete listenerResources.monitor; model.initialize('pool', 'poolId', 'loadbalancerId'); scope.$apply(); }); it('should only show pool and monitor details', function() { expect(model.visibleResources).toEqual(['pool', 'members']); }); }); describe('Model submit function (edit health monitor)', function() { beforeEach(function() { model.initialize('monitor', 'healthmonitor1'); scope.$apply(); }); it('should set final spec properties', function() { model.spec.monitor.interval = 10; model.spec.monitor.retry = 6; model.spec.monitor.timeout = 8; model.spec.monitor.method = 'GET'; model.spec.monitor.status = '200-204'; model.spec.monitor.path = '/foo/bar'; var finalSpec = model.submit(); expect(finalSpec.loadbalancer_id).toBeUndefined(); expect(finalSpec.parentResourceId).toBeUndefined(); expect(finalSpec.loadbalancer).toBeUndefined(); expect(finalSpec.listener).toBeUndefined(); expect(finalSpec.pool).toBeUndefined(); expect(finalSpec.members).toBeUndefined(); expect(finalSpec.certificates).toBeUndefined(); expect(finalSpec.monitor.type).toBe('HTTP'); expect(finalSpec.monitor.interval).toBe(10); expect(finalSpec.monitor.retry).toBe(6); expect(finalSpec.monitor.timeout).toBe(8); expect(finalSpec.monitor.method).toBe('GET'); expect(finalSpec.monitor.status).toBe('200-204'); expect(finalSpec.monitor.path).toBe('/foo/bar'); }); }); describe('Model visible resources (edit listener, no pool)', function() { beforeEach(function() { delete listenerResources.pool; model.initialize('listener', '1234'); scope.$apply(); }); it('should only show listener details', function() { expect(model.visibleResources).toEqual(['listener']); }); }); describe('Model visible resources (edit listener, no monitor or existing members)', function() { beforeEach(function() { delete listenerResources.members; delete listenerResources.monitor; model.initialize('listener', '1234'); scope.$apply(); }); it('should only show listener, pool, and member details', function() { expect(model.visibleResources).toEqual(['listener', 'pool', 'members']); }); }); }); })(); ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.modul0000666000175100017510000001012413245511613033714 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function () { 'use strict'; /** * @ngdoc overview * @name horizon.dashboard.project.lbaasv2 * @description * The LBaaS v2 dashboard's top level module. */ angular .module('horizon.dashboard.project.lbaasv2', [ 'ngRoute', 'horizon.dashboard.project.lbaasv2.loadbalancers', 'horizon.dashboard.project.lbaasv2.listeners', 'horizon.dashboard.project.lbaasv2.pools', 'horizon.dashboard.project.lbaasv2.members', 'horizon.dashboard.project.lbaasv2.healthmonitors' ]) .config(config) .constant('horizon.dashboard.project.lbaasv2.patterns', { /* eslint-disable max-len */ ipv4: '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$', ipv6: '^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?$', /* eslint-enable max-len */ // HTTP status codes - a single number, comma separated numbers, or a range of numbers. httpStatusCodes: /^\d+((\s*-\s*\d+)|(\s*,\s*\d+)+)?$/, // URL path - must start with "/" and can include anything after that urlPath: /^((\/)|(\/[^/]+)+)$/ }) .constant('horizon.dashboard.project.lbaasv2.popovers', { ipAddresses: '
  • {$ addr.ip $}
' }); config.$inject = [ '$provide', '$windowProvider', '$routeProvider' ]; function config($provide, $windowProvider, $routeProvider) { var basePath = $windowProvider.$get().STATIC_URL + 'dashboard/project/lbaasv2/'; $provide.constant('horizon.dashboard.project.lbaasv2.basePath', basePath); var loadbalancers = '/project/ngloadbalancersv2'; var listener = loadbalancers + '/:loadbalancerId/listeners/:listenerId'; var pool = listener + '/pools/:poolId'; var member = pool + '/members/:memberId'; var healthmonitor = pool + '/healthmonitors/:healthmonitorId'; $routeProvider .when(loadbalancers, { templateUrl: basePath + 'loadbalancers/table.html' }) .when(loadbalancers + '/:loadbalancerId', { templateUrl: basePath + 'loadbalancers/detail.html' }) .when(listener, { templateUrl: basePath + 'listeners/detail.html' }) .when(pool, { templateUrl: basePath + 'pools/detail.html' }) .when(member, { templateUrl: basePath + 'members/detail.html' }) .when(healthmonitor, { templateUrl: basePath + 'healthmonitors/detail.html' }); } }()); neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/0000775000175100017510000000000013245512321032747 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000775000175100017510000000000013245512321033767 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/batch-actions.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000377513245511613034012 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Members Table Batch Actions Service', function() { var actions; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { var response = { data: { id: '1' } }; var modal = { open: function() { return { result: { then: function(func) { func(response); } } }; } }; $provide.value('$uibModal', modal); })); beforeEach(inject(function ($injector) { var batchActionsService = $injector.get( 'horizon.dashboard.project.lbaasv2.members.actions.batchActions'); actions = batchActionsService.actions(); })); it('should define correct table batch actions', function() { expect(actions.length).toBe(1); expect(actions[0].template.text).toBe('Add/Remove Pool Members'); }); it('should have the "allowed" and "perform" functions', function() { actions.forEach(function(action) { expect(action.service.allowed).toBeDefined(); expect(action.service.perform).toBeDefined(); }); }); }); })(); ././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/row-actions.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000345113245511613034001 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Members Row Actions Service', function() { var actions; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function ($injector) { var rowActionsService = $injector.get( 'horizon.dashboard.project.lbaasv2.members.actions.rowActions'); actions = rowActionsService.init('1', '2').actions(); var loadbalancerService = $injector.get( 'horizon.dashboard.project.lbaasv2.loadbalancers.service'); spyOn(loadbalancerService, 'isActionable').and.returnValue(true); })); it('should define correct table row actions', function() { expect(actions.length).toBe(1); expect(actions[0].template.text).toBe('Update Weight'); }); it('should have the "allowed" and "perform" functions', function() { actions.forEach(function(action) { expect(action.service.allowed).toBeDefined(); expect(action.service.perform).toBeDefined(); }); }); }); })(); ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/row-actions.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000401613245511613033777 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.members') .factory('horizon.dashboard.project.lbaasv2.members.actions.rowActions', rowActions); rowActions.$inject = [ 'horizon.framework.util.i18n.gettext', 'horizon.dashboard.project.lbaasv2.loadbalancers.service', 'horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.members.actions.rowActions * * @description * Provides the service for the pool members row actions. * * @param gettext The horizon gettext function for translation. * @param loadBalancersService The LBaaS v2 load balancers service. * @param editWeight The LBaaS v2 pool member edit weight service. * @returns Members row actions service object. */ function rowActions(gettext, loadBalancersService, editWeight) { var loadBalancerIsActionable, poolId; var service = { actions: actions, init: init }; return service; /////////////// function init(loadbalancerId, _poolId_) { loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId); poolId = _poolId_; return service; } function actions() { return [{ service: editWeight.init(poolId, loadBalancerIsActionable), template: { text: gettext('Update Weight') } }]; } } })(); ././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/batch-actions.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000416213245511613034001 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.members') .factory('horizon.dashboard.project.lbaasv2.members.actions.batchActions', tableBatchActions); tableBatchActions.$inject = [ 'horizon.framework.util.i18n.gettext', 'horizon.dashboard.project.lbaasv2.loadbalancers.service', 'horizon.dashboard.project.lbaasv2.members.actions.update-member-list' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.pools.actions.batchActions * * @description * Provides the service for the Members table batch actions. * * @param gettext The horizon gettext function for translation. * @param loadBalancersService The LBaaS v2 load balancers service. * @param updateMemberListService The LBaaS v2 update member list service. * @returns Members table batch actions service object. */ function tableBatchActions( gettext, loadBalancersService, updateMemberListService ) { var loadBalancerIsActionable, loadBalancerId; var service = { actions: actions, init: init }; return service; /////////////// function init(_loadBalancerId_) { loadBalancerId = _loadBalancerId_; loadBalancerIsActionable = loadBalancersService.isActionable(loadBalancerId); return service; } function actions() { return [{ service: updateMemberListService.init(loadBalancerIsActionable).update, template: { text: gettext('Add/Remove Pool Members') } }]; } } })(); ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000775000175100017510000000000013245512321033767 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/wizard.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000275613245511613034010 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.members') .controller('UpdateMemberListWizardController', UpdateMemberListWizardController); UpdateMemberListWizardController.$inject = [ '$scope', '$routeParams', 'horizon.dashboard.project.lbaasv2.workflow.model', 'horizon.dashboard.project.lbaasv2.workflow.workflow', 'horizon.framework.util.i18n.gettext' ]; function UpdateMemberListWizardController($scope, $routeParams, model, workflowService, gettext) { var loadbalancerId = $routeParams.loadbalancerId; var poolId = $routeParams.poolId; var scope = $scope; scope.model = model; scope.submit = scope.model.submit; scope.workflow = workflowService( gettext('Add/Remove Pool Members'), 'fa fa-pencil', ['members'] ); scope.model.initialize('members', false, loadbalancerId, poolId); } })(); ././@LongLink0000000000000000000000000000022600000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/update-member-list.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000635413245511613034006 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Update Member List Action Service', function() { var scope, $q, $route, policy, init, updateMemberListService, defer; function allowed() { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = updateMemberListService.update.allowed(); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_member_list']]}); return allowed; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { var response = { data: { id: '9012' } }; var modal = { open: function() { return { result: { then: function(func) { func(response); } } }; } }; $provide.value('$uibModal', modal); })); beforeEach(inject(function ($injector) { scope = $injector.get('$rootScope').$new(); $q = $injector.get('$q'); policy = $injector.get('horizon.app.core.openstack-service-api.policy'); $route = $injector.get('$route'); updateMemberListService = $injector.get( 'horizon.dashboard.project.lbaasv2.members.actions.update-member-list'); init = updateMemberListService.init; defer = $q.defer(); })); it('should define the correct service properties', function() { expect(updateMemberListService.init).toBeDefined(); expect(updateMemberListService.update).toBeDefined(); }); it('should have the "allowed" and "perform" functions', function() { expect(updateMemberListService.update.allowed).toBeDefined(); expect(updateMemberListService.update.perform).toBeDefined(); }); it('should allow editing a pool under an ACTIVE load balancer', function() { defer.resolve(); init(defer.promise); expect(allowed()).toBe(true); }); it('should not allow editing a pool under an NON-ACTIVE load balancer', function() { defer.reject(); init(defer.promise); expect(allowed()).toBe(false); }); it('should redirect after edit', function() { spyOn($route, 'reload').and.callThrough(); updateMemberListService.update.perform(); expect($route.reload).toHaveBeenCalled(); }); }); })(); ././@LongLink0000000000000000000000000000022100000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/update-member-list.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000446413245511613034006 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.members') .factory('horizon.dashboard.project.lbaasv2.members.actions.update-member-list', updateMemberListService); updateMemberListService.$inject = [ '$q', '$route', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.i18n.gettext' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.listeners.actions.updateMemberListService * @description * Provides the service for updating the list of pool members. * @param $q The angular service for promises. * @param $route The angular $route service. * @param workflowModal The LBaaS workflow modal service. * @param policy The horizon policy service. * @param gettext The horizon gettext function for translation. * @returns The load balancers members update member list service. */ function updateMemberListService( $q, $route, workflowModal, policy, gettext ) { var statePromise; var updateList = workflowModal.init({ controller: 'UpdateMemberListWizardController', message: gettext('The pool members have been updated.'), handle: onUpdate, allowed: allowed }); var service = { init: init, update: updateList }; return service; ////////////// function init(_statePromise_) { statePromise = _statePromise_; return service; } function allowed(/*item*/) { return $q.all([ statePromise, policy.ifAllowed({ rules: [['neutron', 'update_member_list']] }) ]); } function onUpdate(/*response*/) { $route.reload(); } } })(); ././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/wizard.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000450013245511613033775 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Update Member List Wizard Controller', function() { var ctrl, workflowSpy, scope; var model = { submit: function() { return 'updated'; }, initialize: angular.noop }; var workflow = 'foo'; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function ($provide) { workflowSpy = jasmine.createSpy('workflow').and.returnValue(workflow); $provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model); $provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflowSpy); })); beforeEach(inject(function ($controller, $injector) { scope = $injector.get('$rootScope').$new(); spyOn(model, 'initialize').and.callThrough(); ctrl = $controller('UpdateMemberListWizardController', { $scope: scope, $routeParams: {loadbalancerId: 'loadbalancerId', poolId: 'poolId'}}); })); it('defines the controller', function() { expect(ctrl).toBeDefined(); }); it('calls initialize on the given model', function() { expect(model.initialize).toHaveBeenCalledWith('members', false, 'loadbalancerId', 'poolId'); }); it('sets scope.workflow to the given workflow', function() { expect(scope.workflow).toBe(workflow); }); it('initializes workflow with correct properties', function() { expect(workflowSpy).toHaveBeenCalledWith('Add/Remove Pool Members', 'fa fa-pencil', ['members']); }); it('defines scope.submit', function() { expect(scope.submit).toBe(model.submit); expect(scope.submit()).toBe('updated'); }); }); })(); ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000775000175100017510000000000013245512321033767 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000627113245511613034004 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.members') .factory('horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service', modalService); modalService.$inject = [ '$q', '$uibModal', '$route', 'horizon.dashboard.project.lbaasv2.basePath', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.widgets.toast.service', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service * * @description * Provides the service for the pool member Edit Weight action. * * @param $q The angular service for promises. * @param $uibModal The angular bootstrap $uibModal service. * @param $route The angular $route service. * @param basePath The LBaaS v2 module base path. * @param policy The horizon policy service. * @param toastService The horizon toast service. * @param gettext The horizon gettext function for translation. * * @returns The Edit Weight modal service. */ function modalService( $q, $uibModal, $route, basePath, policy, toastService, gettext ) { var poolId, statePromise; var service = { perform: open, allowed: allowed, init: init }; return service; //////////// function init(_poolId_, _statePromise_) { poolId = _poolId_; statePromise = _statePromise_; return service; } function allowed(/*item*/) { return $q.all([ statePromise, // This rule is made up and should therefore always pass. At some point there will // likely be a valid rule similar to this that we will want to use. policy.ifAllowed({ rules: [['neutron', 'pool_member_update']] }) ]); } /** * @ngdoc method * @name open * * @description * Open the modal. * * @param item The row item from the table action. * @returns undefined */ function open(item) { var spec = { backdrop: 'static', controller: 'EditWeightModalController as modal', templateUrl: basePath + 'members/actions/edit-weight/modal.html', resolve: { poolId: function() { return poolId; }, member: function() { return item; } } }; $uibModal.open(spec).result.then(onModalClose); } function onModalClose() { toastService.add('success', gettext('Pool member weight has been updated.')); $route.reload(); } } })(); ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000276413245511613034007 0ustar zuulzuul00000000000000 ././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000421713245511613034002 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.members') .controller('EditWeightModalController', EditWeightModalController); EditWeightModalController.$inject = [ '$uibModalInstance', 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.framework.util.i18n.gettext', // Dependencies injected with resolve by $uibModal.open 'poolId', 'member' ]; /** * @ngdoc controller * @name EditWeightModalController * @description * Controller used by the modal service for editing the weight of a pool member. * * @param $uibModalInstance The angular bootstrap $uibModalInstance service. * @param api The LBaaS v2 API service. * @param gettext The horizon gettext function for translation. * @param poolId The pool ID. * @param member The pool member to update. * * @returns The Edit Weight modal controller. */ function EditWeightModalController($uibModalInstance, api, gettext, poolId, member) { var ctrl = this; ctrl.weight = member.weight; ctrl.cancel = cancel; ctrl.save = save; ctrl.saving = false; ctrl.weightError = gettext('The weight must be a number between 1 and 256.'); function save() { ctrl.saving = true; return api.editMember(poolId, member.id, { weight: ctrl.weight }) .then(onSuccess, onFailure); } function cancel() { $uibModalInstance.dismiss('cancel'); } function onSuccess() { $uibModalInstance.close(); } function onFailure() { ctrl.saving = false; } } })(); ././@LongLink0000000000000000000000000000021100000000000011207 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000675113245511613034007 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Member Edit Weight Service', function() { var service, policy, $scope, $route, $uibModal, toast; var member = { id: 'member1' }; var fakePromise = function(response) { return { then: function(func) { return func(response); } }; }; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = service.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); $scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'pool_member_update']]}); return allowed; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { $provide.value('$uibModal', { open: function() { return { result: fakePromise() }; } }); })); beforeEach(inject(function ($injector) { policy = $injector.get('horizon.app.core.openstack-service-api.policy'); toast = $injector.get('horizon.framework.widgets.toast.service'); $scope = $injector.get('$rootScope').$new(); $route = $injector.get('$route'); $uibModal = $injector.get('$uibModal'); service = $injector.get( 'horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service'); service.init('pool1', fakePromise()); })); it('should have the "allowed" and "perform" functions', function() { expect(service.allowed).toBeDefined(); expect(service.perform).toBeDefined(); }); it('should check policy to allow the action', function() { expect(allowed(member)).toBe(true); }); it('should open the modal', function() { spyOn($uibModal, 'open').and.callThrough(); service.perform(member); $scope.$apply(); expect($uibModal.open.calls.count()).toBe(1); }); it('should resolve data for passing into the modal', function() { spyOn($uibModal, 'open').and.callThrough(); service.perform(member); $scope.$apply(); var resolve = $uibModal.open.calls.argsFor(0)[0].resolve; expect(resolve).toBeDefined(); expect(resolve.poolId()).toBe('pool1'); expect(resolve.member()).toBe(member); }); it('should show message and reload page upon closing modal', function() { spyOn(toast, 'add'); spyOn($route, 'reload'); service.perform(member); $scope.$apply(); expect(toast.add).toHaveBeenCalledWith('success', 'Pool member weight has been updated.'); expect($route.reload).toHaveBeenCalled(); }); }); })(); ././@LongLink0000000000000000000000000000021400000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666000175100017510000000575013245511613034005 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Member Edit Weight Controller', function() { var ctrl, api, $controller, $uibModalInstance, $scope, $q; var fail = false; function makePromise(reject) { var def = $q.defer(); def[reject ? 'reject' : 'resolve'](); return def.promise; } beforeEach(module('horizon.framework.util.i18n')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { $provide.value('$uibModalInstance', { close: angular.noop, dismiss: angular.noop }); $provide.value('poolId', 'pool1'); $provide.value('member', { id: 'member1', weight: 1 }); $provide.value('horizon.app.core.openstack-service-api.lbaasv2', { editMember: function() { return makePromise(fail); } }); })); beforeEach(inject(function ($injector) { api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); $controller = $injector.get('$controller'); $uibModalInstance = $injector.get('$uibModalInstance'); $scope = $injector.get('$rootScope').$new(); $q = $injector.get('$q'); ctrl = $controller('EditWeightModalController'); })); it('should define controller properties', function() { expect(ctrl.cancel).toBeDefined(); expect(ctrl.save).toBeDefined(); expect(ctrl.saving).toBe(false); expect(ctrl.weight).toBe(1); expect(ctrl.weightError).toBe('The weight must be a number between 1 and 256.'); }); it('should edit member weight', function() { spyOn(api, 'editMember').and.callThrough(); spyOn($uibModalInstance, 'close'); ctrl.save(); $scope.$apply(); expect(ctrl.saving).toBe(true); expect(api.editMember).toHaveBeenCalledWith('pool1', 'member1', { weight: 1 }); expect($uibModalInstance.close).toHaveBeenCalled(); }); it('should dismiss modal if cancel clicked', function() { spyOn($uibModalInstance, 'dismiss'); ctrl.cancel(); expect($uibModalInstance.dismiss).toHaveBeenCalledWith('cancel'); }); it('should not dismiss modal if save fails', function() { fail = true; spyOn($uibModalInstance, 'dismiss'); ctrl.save(); $scope.$apply(); expect($uibModalInstance.dismiss).not.toHaveBeenCalled(); expect(ctrl.saving).toBe(false); }); }); })(); ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table0000666000175100017510000000656613245511613034003 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * Copyright 2017 Walmart. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Members Table Controller', function() { var controller, lbaasv2API, membersService, scope; var items = [{ foo: 'bar' }]; var apiFail = false; function fakeAPI() { return { then: function(success, fail) { if (apiFail && fail) { fail(); } else { success({ data: { items: items } }); } } }; } /////////////////////// beforeEach(module('horizon.framework.widgets.toast')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { $provide.value('$uibModal', {}); })); beforeEach(inject(function($injector) { lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); membersService = $injector.get('horizon.dashboard.project.lbaasv2.members.service'); controller = $injector.get('$controller'); spyOn(lbaasv2API, 'getMembers').and.callFake(fakeAPI); spyOn(membersService, 'associateMemberStatuses'); })); function createController() { return controller('MembersTableController', { $scope: scope, $routeParams: { loadbalancerId: 'loadbaancerId', listenerId: 'listenerId', poolId: 'poolId' }}); } it('should initialize the controller properties correctly', function() { var ctrl = createController(); expect(ctrl.items).toEqual([]); expect(ctrl.src).toEqual(items); expect(ctrl.loading).toBe(false); expect(ctrl.error).toBe(false); expect(ctrl.checked).toEqual({}); expect(ctrl.loadbalancerId).toBeDefined(); expect(ctrl.listenerId).toBeDefined(); expect(ctrl.poolId).toBeDefined(); expect(ctrl.rowActions).toBeDefined(); expect(ctrl.batchActions).toBeDefined(); expect(ctrl.operatingStatus).toBeDefined(); expect(ctrl.provisioningStatus).toBeDefined(); }); it('should invoke lbaasv2 apis', function() { var ctrl = createController(); expect(lbaasv2API.getMembers).toHaveBeenCalled(); expect(ctrl.src.length).toBe(1); }); it('should invoke the "associateMemberStatuses" method', function() { var ctrl = createController(); expect(membersService.associateMemberStatuses).toHaveBeenCalledWith( ctrl.loadbalancerId, ctrl.listenerId, ctrl.poolId, ctrl.src); }); it('should show error if loading fails', function() { apiFail = true; var ctrl = createController(); expect(ctrl.src.length).toBe(0); expect(ctrl.error).toBe(true); }); }); })(); ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detail.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detai0000666000175100017510000001050513245511613033766 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Member Detail Controller', function() { var $controller, lbaasv2API, membersService, apiFail, qAllFail, actions; function fakePromise(data, reject) { return { then: function(success, fail) { if (reject) { fail(); } else { success({ data: data }); } return fakePromise(); } }; } function fakeAPI() { return fakePromise('foo', apiFail); } function loadbalancerAPI() { return fakePromise({ provisioning_status: 'ACTIVE' }); } function qAll() { return fakePromise(null, qAllFail); } function createController() { return $controller('MemberDetailController', { $routeParams: { loadbalancerId: 'loadbalancerId', listenerId: 'listenerId', poolId: 'poolId', memberId: 'memberId' } }); } /////////////////////// beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.widgets.toast')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { apiFail = false; qAllFail = false; $provide.value('$q', { all: qAll }); $provide.value('$uibModal', {}); $provide.value('horizon.dashboard.project.lbaasv2.members.actions.rowActions', { init: function() { return { actions: 'member-actions' }; } }); })); beforeEach(inject(function($injector) { lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); actions = $injector.get('horizon.dashboard.project.lbaasv2.members.actions.rowActions'); membersService = $injector.get('horizon.dashboard.project.lbaasv2.members.service'); spyOn(lbaasv2API, 'getMember').and.callFake(fakeAPI); spyOn(lbaasv2API, 'getPool').and.callFake(fakeAPI); spyOn(lbaasv2API, 'getListener').and.callFake(fakeAPI); spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI); spyOn(actions, 'init').and.callThrough(); spyOn(membersService, 'associateMemberStatuses'); $controller = $injector.get('$controller'); })); it('should invoke lbaasv2 apis', function() { var ctrl = createController(); expect(lbaasv2API.getMember).toHaveBeenCalledWith('poolId','memberId'); expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId'); expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId'); expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId'); expect(ctrl.loadbalancerId).toBeDefined(); expect(ctrl.listenerId).toBeDefined(); expect(ctrl.poolId).toBeDefined(); expect(ctrl.operatingStatus).toBeDefined(); expect(ctrl.provisioningStatus).toBeDefined(); expect(ctrl.actions).toBe('member-actions'); expect(actions.init).toHaveBeenCalledWith('loadbalancerId', 'poolId'); }); it('should invoke the "associateMemberStatuses" method', function() { var ctrl = createController(); expect(membersService.associateMemberStatuses).toHaveBeenCalledWith( ctrl.loadbalancerId, ctrl.listenerId, ctrl.poolId, [ctrl.member]); }); it('should throw error on API fail', function() { apiFail = true; var init = function() { createController(); }; expect(init).toThrow(); }); it('should set error state if any APIs fail', function() { qAllFail = true; var ctrl = createController(); expect(ctrl.loading).toBe(false); expect(ctrl.error).toBe(true); }); }); })(); ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table0000666000175100017510000000647413245511613034001 0ustar zuulzuul00000000000000
ID IP Address Protocol Port Operating Status Provisioning Status Weight Actions
{$ ::item.id $} {$ ::item.address $} {$ ::item.protocol_port $} {$ ::item.operating_status | decode:table.operatingStatus $} {$ ::item.provisioning_status | decode:table.provisioningStatus $} {$ item.weight $}
././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/members.module.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/membe0000666000175100017510000000146413245511613033771 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Members Module', function() { it('should exist', function() { expect(angular.module('horizon.dashboard.project.lbaasv2.members')).toBeDefined(); }); }); })(); ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detail.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detai0000666000175100017510000000376113245511613033774 0ustar zuulzuul00000000000000
Address
{$ ::ctrl.member.address $}
Protocol Port
{$ ::ctrl.member.protocol_port $}
Weight
{$ ctrl.member.weight $}
Operating Status
{$ ctrl.member.operating_status | decode:ctrl.operatingStatus $}
Provisioning Status
{$ ctrl.member.provisioning_status | decode:ctrl.provisioningStatus $}
Admin State Up
{$ ctrl.member.admin_state_up | yesno $}
Member ID
{$ ::ctrl.member.id $}
Tenant ID
{$ ::ctrl.member.tenant_id $}
././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/members.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/membe0000666000175100017510000000634413245511613033773 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.members') .factory('horizon.dashboard.project.lbaasv2.members.service', membersService); membersService.$inject = [ 'horizon.app.core.openstack-service-api.lbaasv2' ]; /** * @ngdoc service * @name horizon.dashboard.project.lbaasv2.members.service * @description General service for LBaaS v2 members. * @param api The LBaaS V2 service API. * @returns The members service. */ function membersService(api) { var service = { associateMemberStatuses: associateMemberStatuses }; return service; //////////// /** * @ngdoc method * @name horizon.dashboard.project.lbaasv2.members.service.associateMemberStatuses * @description Associates the list of specified members with their corresponding statuses * that are retrieved from the load balancer status tree. * @param loadBalancerId The load balancer ID. * @param listenerId The listener ID that the members belong to. * @param poolId The pool ID that the members belong to. * @param members The list of members to associate with their corresponding health statuses. * @returns None */ function associateMemberStatuses(loadBalancerId, listenerId, poolId, members) { api.getLoadBalancerStatusTree(loadBalancerId).then(function(response) { // Collect the member status data for all specified members var memberStatusData = []; var listeners = response.data.statuses.loadbalancer.listeners; for (var listenerIndex = 0; listenerIndex < listeners.length; listenerIndex++) { var listener = listeners[listenerIndex]; if (listener.id === listenerId) { var pools = listener.pools; for (var poolIndex = 0; poolIndex < pools.length; poolIndex++) { var pool = pools[poolIndex]; if (pool.id === poolId) { memberStatusData = pool.members; break; } } break; } } // Attach the status properties to each member object members.forEach(mapStatusToMember); function mapStatusToMember(member) { for (var memberIndex = 0; memberIndex < memberStatusData.length; memberIndex++) { var memberWithStatuses = memberStatusData[memberIndex]; if (memberWithStatuses.id === member.id) { member.operating_status = memberWithStatuses.operating_status; member.provisioning_status = memberWithStatuses.provisioning_status; break; } } } }); } } }()); ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/members.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/membe0000666000175100017510000000660313245511613033771 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Members Service', function() { var service, $q, scope; beforeEach(module('horizon.framework.widgets.toast')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { $provide.value('horizon.app.core.openstack-service-api.lbaasv2', { getLoadBalancerStatusTree: function() { var deferred = $q.defer(); var response = { data: { statuses: { loadbalancer: { id: 'loadbalancer1', listeners: [ { id: 'listener0', pools: [] }, { id: 'listener1', pools: [ { id: 'pool0', members: [] }, { id: 'pool1', members: [ { id: 'member1', operating_status: 'ONLINE', provisioning_status: 'ACTIVE' }, { id: 'member2', operating_status: 'OFFLINE', provisioning_status: 'INACTIVE' } ] } ] } ] } } } }; deferred.resolve(response); return deferred.promise; } }); })); beforeEach(inject(function ($injector) { service = $injector.get('horizon.dashboard.project.lbaasv2.members.service'); $q = $injector.get('$q'); scope = $injector.get('$rootScope').$new(); })); it('should define service attributes', function() { expect(service.associateMemberStatuses).toBeDefined(); }); it('should correctly associate member health statuses', function() { var members = [ { id: 'member1' }, { id: 'member2' } ]; service.associateMemberStatuses('loadbalancer1', 'listener1', 'pool1', members); scope.$apply(); expect(members.length).toBe(2); expect(members[0].operating_status).toBe('ONLINE'); expect(members[0].provisioning_status).toBe('ACTIVE'); expect(members[1].operating_status).toBe('OFFLINE'); expect(members[1].provisioning_status).toBe('INACTIVE'); }); }); })(); ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/members.module.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/membe0000666000175100017510000000165713245511613033775 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; /** * @ngdoc overview * @ngname horizon.dashboard.project.lbaasv2.members * * @description * Provides the services and widgets required to support and display the project members * for the load balancers v2 panel. */ angular .module('horizon.dashboard.project.lbaasv2.members', []); })(); ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detail.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detai0000666000175100017510000000701213245511613033765 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.members') .controller('MemberDetailController', MemberDetailController); MemberDetailController.$inject = [ 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.dashboard.project.lbaasv2.members.actions.rowActions', '$routeParams', '$q', 'horizon.dashboard.project.lbaasv2.loadbalancers.service', 'horizon.dashboard.project.lbaasv2.members.service' ]; /** * @ngdoc controller * @name MemberDetailController * * @description * Controller for the LBaaS v2 member detail page. * * @param api The LBaaS v2 API service. * @param rowActions The pool members row actions service. * @param $routeParams The angular $routeParams service. * @param $q The angular service for promises. * @param loadBalancersService The LBaaS v2 load balancers service. * @param membersService The LBaaS v2 members service. * @returns undefined */ function MemberDetailController( api, rowActions, $routeParams, $q, loadBalancersService, membersService ) { var ctrl = this; ctrl.loading = true; ctrl.error = false; ctrl.actions = rowActions.init($routeParams.loadbalancerId, $routeParams.poolId).actions; ctrl.loadbalancerId = $routeParams.loadbalancerId; ctrl.listenerId = $routeParams.listenerId; ctrl.poolId = $routeParams.poolId; ctrl.operatingStatus = loadBalancersService.operatingStatus; ctrl.provisioningStatus = loadBalancersService.provisioningStatus; init(); //////////////////////////////// function init() { ctrl.member = null; ctrl.pool = null; ctrl.listener = null; ctrl.loadbalancer = null; ctrl.loading = true; ctrl.error = false; $q.all([ api.getMember($routeParams.poolId, $routeParams.memberId) .then(success('member'), fail('member')), api.getPool($routeParams.poolId) .then(success('pool'), fail('pool')), api.getListener($routeParams.listenerId) .then(success('listener'), fail('listener')), api.getLoadBalancer($routeParams.loadbalancerId) .then(success('loadbalancer'), fail('loadbalancer')) ]).then(postInit, initError); } function success(property) { return angular.bind(null, function setProp(property, response) { ctrl[property] = response.data; if (property === 'member') { membersService.associateMemberStatuses( ctrl.loadbalancerId, ctrl.listenerId, ctrl.poolId, [ctrl.member]); } }, property); } function fail(property) { return angular.bind(null, function setProp(property, error) { ctrl[property] = null; throw error; }, property); } function postInit() { ctrl.loading = false; } function initError() { ctrl.loading = false; ctrl.error = true; } } })(); ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table0000666000175100017510000000562213245511613033773 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.members') .controller('MembersTableController', MembersTableController); MembersTableController.$inject = [ 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.dashboard.project.lbaasv2.members.actions.rowActions', 'horizon.dashboard.project.lbaasv2.members.actions.batchActions', '$routeParams', 'horizon.dashboard.project.lbaasv2.loadbalancers.service', 'horizon.dashboard.project.lbaasv2.members.service' ]; /** * @ngdoc controller * @name MembersTableController * * @description * Controller for the LBaaS v2 members table. Serves as the focal point for table actions. * * @param api The LBaaS V2 service API. * @param rowActions The pool members row actions service. * @param batchActions The members batch actions service. * @param $routeParams The angular $routeParams service. * @param loadBalancersService The LBaaS v2 load balancers service. * @param membersService The LBaaS v2 members service. * @returns undefined */ function MembersTableController( api, rowActions, batchActions, $routeParams, loadBalancersService, membersService ) { var ctrl = this; ctrl.items = []; ctrl.src = []; ctrl.loading = true; ctrl.error = false; ctrl.checked = {}; ctrl.loadbalancerId = $routeParams.loadbalancerId; ctrl.listenerId = $routeParams.listenerId; ctrl.poolId = $routeParams.poolId; ctrl.rowActions = rowActions.init(ctrl.loadbalancerId, ctrl.poolId); ctrl.batchActions = batchActions.init(ctrl.loadbalancerId); ctrl.operatingStatus = loadBalancersService.operatingStatus; ctrl.provisioningStatus = loadBalancersService.provisioningStatus; init(); //////////////////////////////// function init() { ctrl.src = []; ctrl.loading = true; ctrl.error = false; api.getMembers(ctrl.poolId).then(success, fail); } function success(response) { ctrl.src = response.data.items; ctrl.loading = false; membersService.associateMemberStatuses( ctrl.loadbalancerId, ctrl.listenerId, ctrl.poolId, ctrl.src); } function fail(/*response*/) { ctrl.src = []; ctrl.loading = false; ctrl.error = true; } } })(); ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000775000175100017510000000000013245512321034030 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000775000175100017510000000000013245512321034030 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021300000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000541013245511613034037 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Load Balancers Table Batch Actions Service', function() { var $location, actions, policy; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { var response = { data: { id: '1' } }; var modal = { open: function() { return { result: { then: function(func) { func(response); } } }; } }; $provide.value('$uibModal', modal); })); beforeEach(inject(function ($injector) { $location = $injector.get('$location'); policy = $injector.get('horizon.app.core.openstack-service-api.policy'); var batchActionsService = $injector.get( 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions'); actions = batchActionsService.actions(); })); it('should define correct table batch actions', function() { expect(actions.length).toBe(2); expect(actions[0].template.text).toBe('Create Load Balancer'); expect(actions[1].template.text).toBe('Delete Load Balancers'); }); it('should have the "allowed" and "perform" functions', function() { actions.forEach(function(action) { expect(action.service.allowed).toBeDefined(); expect(action.service.perform).toBeDefined(); }); }); it('should check policy to allow creating a load balancer', function() { spyOn(policy, 'ifAllowed').and.returnValue(true); var allowed = actions[0].service.allowed(); expect(allowed).toBe(true); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'create_loadbalancer']]}); }); it('should redirect after create', function() { spyOn($location, 'path').and.callThrough(); actions[0].service.perform(); expect($location.path).toHaveBeenCalledWith('project/ngloadbalancersv2/1'); }); }); })(); ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/edit/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000775000175100017510000000000013245512321034030 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/edit/wizard.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000314513245511613034042 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .controller('EditLoadBalancerWizardController', EditLoadBalancerWizardController); EditLoadBalancerWizardController.$inject = [ '$scope', 'horizon.dashboard.project.lbaasv2.workflow.model', 'horizon.dashboard.project.lbaasv2.workflow.workflow', 'horizon.framework.util.i18n.gettext' ]; function EditLoadBalancerWizardController($scope, model, workflowService, gettext) { var scope = $scope; // Note: We set these attributes on the $scope so that the scope inheritance used all through // the wizard continues to work. Using local var to appease eslint angular/ng_controller_as. scope.model = model; scope.submit = scope.model.submit; scope.workflow = workflowService(gettext('Update Load Balancer'), 'fa fa-pencil', ['loadbalancer']); scope.model.initialize('loadbalancer', scope.launchContext.id); } })(); ././@LongLink0000000000000000000000000000021400000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/edit/wizard.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000424213245511613034041 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Edit Load Balancer Wizard Controller', function() { var ctrl, workflowSpy; var model = { submit: function() { return 'updated'; }, initialize: angular.noop }; var workflow = 'foo'; var scope = { launchContext: { id: '1' } }; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function ($provide) { workflowSpy = jasmine.createSpy('workflow').and.returnValue(workflow); $provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model); $provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflowSpy); })); beforeEach(inject(function ($controller) { spyOn(model, 'initialize'); ctrl = $controller('EditLoadBalancerWizardController', { $scope: scope }); })); it('defines the controller', function() { expect(ctrl).toBeDefined(); }); it('calls initialize on the given model', function() { expect(model.initialize).toHaveBeenCalledWith('loadbalancer', '1'); }); it('sets scope.workflow to the given workflow', function() { expect(scope.workflow).toBe(workflow); }); it('initializes workflow with correct properties', function() { expect(workflowSpy).toHaveBeenCalledWith('Update Load Balancer', 'fa fa-pencil', ['loadbalancer']); }); it('defines scope.submit', function() { expect(scope.submit).toBe(model.submit); expect(scope.submit()).toBe('updated'); }); }); })(); ././@LongLink0000000000000000000000000000021100000000000011207 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/row-actions.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000645213245511613034046 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Load Balancers Table Row Actions Service', function() { var rowActionsService, scope, $route, actions, policy; function canEdit(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = actions[0].service.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_loadbalancer']]}); return allowed; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { var response = { data: { id: '1' } }; var modal = { open: function() { return { result: { then: function(func) { func(response); } } }; } }; $provide.value('$uibModal', modal); })); beforeEach(inject(function ($injector) { scope = $injector.get('$rootScope').$new(); $route = $injector.get('$route'); policy = $injector.get('horizon.app.core.openstack-service-api.policy'); rowActionsService = $injector.get( 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions'); actions = rowActionsService.actions(); })); it('should define correct table row actions', function() { expect(actions.length).toBe(4); expect(actions[0].template.text).toBe('Edit'); expect(actions[1].template.text).toBe('Associate Floating IP'); expect(actions[2].template.text).toBe('Disassociate Floating IP'); expect(actions[3].template.text).toBe('Delete Load Balancer'); }); it('should allow editing an ACTIVE load balancer', function() { expect(canEdit({provisioning_status: 'ACTIVE'})).toBe(true); }); it('should not allow editing a non-ACTIVE load balancer', function() { expect(canEdit({provisioning_status: 'PENDING_UPDATE'})).toBe(false); }); it('should have the "allowed" and "perform" functions', function() { actions.forEach(function(action) { expect(action.service.allowed).toBeDefined(); expect(action.service.perform).toBeDefined(); }); }); it('should reload table after edit', function() { spyOn($route, 'reload').and.callThrough(); actions[0].service.perform(); expect($route.reload).toHaveBeenCalled(); }); }); })(); ././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/row-actions.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000715713245511613034051 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions', tableRowActions); tableRowActions.$inject = [ '$q', '$route', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete', 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip.modal.service', 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip.modal.service', 'horizon.app.core.openstack-service-api.policy', 'horizon.app.core.openstack-service-api.network', 'horizon.framework.util.q.extensions', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions * * @description * Provides the service for the Load Balancers table row actions. * * @param $q The angular service for promises. * @param $route The angular $route service. * @param workflowModal The LBaaS workflow modal service. * @param deleteService The load balancer delete service. * @param associateIp The associate floating IP modal service. * @param disassociateIp The disassociate floating IP modal service. * @param policy The horizon policy service. * @param network The horizon network API service. * @param qExtensions Horizon extensions to the $q service. * @param gettext The horizon gettext function for translation. * @returns Load balancers table row actions service object. */ function tableRowActions( $q, $route, workflowModal, deleteService, associateIp, disassociateIp, policy, network, qExtensions, gettext ) { var edit = workflowModal.init({ controller: 'EditLoadBalancerWizardController', message: gettext('The load balancer has been updated.'), handle: onEdit, allowed: canEdit }); var service = { actions: actions }; return service; /////////////// function actions() { return [{ service: edit, template: { text: gettext('Edit') } },{ service: associateIp, template: { text: gettext('Associate Floating IP') } },{ service: disassociateIp, template: { text: gettext('Disassociate Floating IP') } },{ service: deleteService, template: { text: gettext('Delete Load Balancer'), type: 'delete' } }]; } function canEdit(item) { return $q.all([ qExtensions.booleanAsPromise(item.provisioning_status === 'ACTIVE'), // This rule is made up and should therefore always pass. At some point there will // likely be a valid rule similar to this that we will want to use. policy.ifAllowed({ rules: [['neutron', 'update_loadbalancer']] }) ]); } function onEdit(/*response*/) { $route.reload(); } } })(); ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/disassociate-ip/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000775000175100017510000000000013245512321034030 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021600000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/disassociate-ip/modal.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000654013245511613034044 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .factory( 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip.modal.service', modalService); modalService.$inject = [ '$q', '$route', 'horizon.framework.widgets.modal.deleteModalService', 'horizon.app.core.openstack-service-api.network', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.q.extensions', 'horizon.framework.util.i18n.gettext' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip.modal.service * @description * Brings up the disassociate floating IP confirmation modal dialog. * On submit, dsiassociates the floating IP address from the load balancer. * On cancel, does nothing. * @param $q The angular service for promises. * @param $route The angular $route service. * @param deleteModal The horizon delete modal service. * @param network The horizon network API service. * @param policy The horizon policy service. * @param qExtensions Horizon extensions to the $q service. * @param gettext The horizon gettext function for translation. * @returns The load balancers table row delete service. */ function modalService($q, $route, deleteModal, network, policy, qExtensions, gettext) { var loadbalancer; var context = { labels: { title: gettext('Confirm Disassociate Floating IP Address'), /* eslint-disable max-len */ message: gettext('You are about to disassociate the floating IP address from load balancer "%s". Please confirm.'), /* eslint-enable max-len */ submit: gettext('Disassociate'), success: gettext('Disassociated floating IP address from load balancer: %s.'), error: gettext('Unable to disassociate floating IP address from load balancer: %s.') }, deleteEntity: disassociate }; var service = { perform: perform, allowed: allowed }; return service; ////////////// function perform(item) { loadbalancer = item; deleteModal.open({ $emit: actionComplete }, [item], context); } function allowed(item) { return $q.all([ qExtensions.booleanAsPromise(item.floating_ip && !!item.floating_ip.ip), // This rule is made up and should therefore always pass. At some point there will // likely be a valid rule similar to this that we will want to use. policy.ifAllowed({ rules: [['neutron', 'loadbalancer_disassociate_floating_ip']] }) ]); } function disassociate() { return network.disassociateFloatingIp(loadbalancer.floating_ip.id); } function actionComplete() { $route.reload(); } } })(); ././@LongLink0000000000000000000000000000022300000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/disassociate-ip/modal.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000001027413245511613034043 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Load Balancers Table Disassociate IP Service', function() { var service, policy, modal, network, $scope, $route, item; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = service.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); $scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith( {rules: [['neutron', 'loadbalancer_disassociate_floating_ip']]}); return allowed; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(function() { item = { id: '1', name: 'First', floating_ip: { id: 'ip1', ip: '1' } }; }); beforeEach(module(function($provide) { var fakePromise = { then: function(func) { func(); } }; $provide.value('$uibModal', { open: function() { return { result: fakePromise }; } }); $provide.value('horizon.app.core.openstack-service-api.network', { disassociateFloatingIp: function() { return fakePromise; } }); })); beforeEach(inject(function ($injector) { policy = $injector.get('horizon.app.core.openstack-service-api.policy'); network = $injector.get('horizon.app.core.openstack-service-api.network'); modal = $injector.get('horizon.framework.widgets.modal.deleteModalService'); $scope = $injector.get('$rootScope').$new(); $route = $injector.get('$route'); service = $injector.get( 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip.modal.service'); })); it('should have the "allowed" and "perform" functions', function() { expect(service.allowed).toBeDefined(); expect(service.perform).toBeDefined(); }); it('should check policy to allow action', function() { expect(allowed(item)).toBe(true); }); it('should not allow action if floating IP not associated', function() { delete item.floating_ip.ip; expect(allowed(item)).toBe(false); }); it('should open the delete modal', function() { spyOn(modal, 'open'); service.perform(item); $scope.$apply(); expect(modal.open.calls.count()).toBe(1); var args = modal.open.calls.argsFor(0); expect(args.length).toBe(3); expect(args[0]).toEqual({ $emit: jasmine.any(Function) }); expect(args[1]).toEqual([jasmine.objectContaining({ id: '1' })]); expect(args[2]).toEqual(jasmine.objectContaining({ labels: jasmine.any(Object), deleteEntity: jasmine.any(Function) })); expect(args[2].labels.title).toBe('Confirm Disassociate Floating IP Address'); }); it('should pass function to modal that disassociates the IP address', function() { spyOn(modal, 'open').and.callThrough(); spyOn(network, 'disassociateFloatingIp').and.callThrough(); service.perform(item); $scope.$apply(); expect(network.disassociateFloatingIp.calls.count()).toBe(1); expect(network.disassociateFloatingIp).toHaveBeenCalledWith('ip1'); }); it('should reload page after action completes', function() { spyOn($route, 'reload'); service.perform(item); $scope.$apply(); expect($route.reload).toHaveBeenCalled(); }); }); })(); ././@LongLink0000000000000000000000000000020600000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000553013245511613034042 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions', tableBatchActions); tableBatchActions.$inject = [ '$location', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.dashboard.project.lbaasv2.basePath', 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions * * @description * Provides the service for the Load Balancers table batch actions. * * @param $location The angular $location service. * @param workflowModal The LBaaS workflow modal service. * @param basePath The lbaasv2 module base path. * @param deleteService The load balancer delete service. * @param policy The horizon policy service. * @param gettext The horizon gettext function for translation. * @returns Load balancers table batch actions service object. */ function tableBatchActions($location, workflowModal, basePath, deleteService, policy, gettext) { var create = workflowModal.init({ controller: 'CreateLoadBalancerWizardController', message: gettext('A new load balancer is being created.'), handle: onCreate, allowed: canCreate }); var service = { actions: actions }; return service; /////////////// function actions() { return [{ service: create, template: { type: 'create', text: gettext('Create Load Balancer') } }, { service: deleteService, template: { type: 'delete-selected', text: gettext('Delete Load Balancers') } }]; } function canCreate() { // This rule is made up and should therefore always pass. I assume at some point there // will be a valid rule similar to this that we will want to use. return policy.ifAllowed({ rules: [['neutron', 'create_loadbalancer']] }); } function onCreate(response) { $location.path('project/ngloadbalancersv2/' + response.data.id); } } })(); ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000775000175100017510000000000013245512321034030 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021100000000000011207 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000300113245511613034031 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .controller('CreateLoadBalancerWizardController', CreateLoadBalancerWizardController); CreateLoadBalancerWizardController.$inject = [ '$scope', 'horizon.dashboard.project.lbaasv2.workflow.model', 'horizon.dashboard.project.lbaasv2.workflow.workflow', 'horizon.framework.util.i18n.gettext' ]; function CreateLoadBalancerWizardController($scope, model, workflowService, gettext) { var scope = $scope; // Note: We set these attributes on the $scope so that the scope inheritance used all through // the wizard continues to work. Using local var to appease eslint angular/ng_controller_as. scope.model = model; scope.submit = scope.model.submit; scope.workflow = workflowService(gettext('Create Load Balancer'), 'fa fa-cloud-download'); scope.model.initialize('loadbalancer'); } })(); ././@LongLink0000000000000000000000000000021600000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000354613245511613034047 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Create Load Balancer Wizard Controller', function() { var ctrl; var model = { submit: function() { return 'created'; }, initialize: angular.noop }; var workflow = function() { return 'foo'; }; var scope = {}; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function ($provide) { $provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model); $provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflow); })); beforeEach(inject(function ($controller) { spyOn(model, 'initialize'); ctrl = $controller('CreateLoadBalancerWizardController', { $scope: scope }); })); it('defines the controller', function() { expect(ctrl).toBeDefined(); }); it('calls initialize on the given model', function() { expect(model.initialize).toHaveBeenCalled(); }); it('sets scope.workflow to the given workflow', function() { expect(scope.workflow).toBe('foo'); }); it('defines scope.submit', function() { expect(scope.submit).toBeDefined(); expect(scope.submit()).toBe('created'); }); }); })(); ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/delete/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000775000175100017510000000000013245512321034030 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000022200000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/delete/delete.action.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000001465213245511613034047 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Load Balancers Table Row Delete Service', function() { var service, policy, modal, lbaasv2Api, $scope, $route, $location, $q, toast, items, path; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = service.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); $scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'delete_loadbalancer']]}); return allowed; } function makePromise(reject) { var def = $q.defer(); def[reject ? 'reject' : 'resolve'](); return def.promise; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(function() { items = [{ id: '1', name: 'First', provisioning_status: 'ACTIVE' }, { id: '2', name: 'Second', provisioning_status: 'ACTIVE' }]; }); beforeEach(module(function($provide) { $provide.value('$uibModal', { open: function() { return { result: makePromise() }; } }); $provide.value('horizon.app.core.openstack-service-api.lbaasv2', { deleteLoadBalancer: function() { return makePromise(); } }); $provide.value('$location', { path: function() { return path; } }); })); beforeEach(inject(function ($injector) { policy = $injector.get('horizon.app.core.openstack-service-api.policy'); lbaasv2Api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); modal = $injector.get('horizon.framework.widgets.modal.deleteModalService'); $scope = $injector.get('$rootScope').$new(); $route = $injector.get('$route'); $location = $injector.get('$location'); $q = $injector.get('$q'); toast = $injector.get('horizon.framework.widgets.toast.service'); service = $injector.get('horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete'); })); it('should have the "allowed" and "perform" functions', function() { expect(service.allowed).toBeDefined(); expect(service.perform).toBeDefined(); }); it('should check policy to allow deleting a load balancer (single)', function() { expect(allowed(items[0])).toBe(true); }); it('should check policy to allow deleting a load balancer (batch)', function() { expect(allowed()).toBe(true); }); it('should not allow deleting load balancers if state check fails (single)', function() { items[0].provisioning_status = 'PENDING_UPDATE'; expect(allowed(items[0])).toBe(false); }); it('should allow batch delete even if state check fails (batch)', function() { items[0].provisioning_status = 'PENDING_UPDATE'; expect(allowed()).toBe(true); }); it('should open the delete modal', function() { spyOn(modal, 'open'); service.perform(items[0]); $scope.$apply(); expect(modal.open.calls.count()).toBe(1); var args = modal.open.calls.argsFor(0); expect(args.length).toBe(3); expect(args[0]).toEqual({ $emit: jasmine.any(Function) }); expect(args[1]).toEqual([jasmine.objectContaining({ id: '1' })]); expect(args[2]).toEqual(jasmine.objectContaining({ labels: jasmine.any(Object), deleteEntity: jasmine.any(Function) })); expect(args[2].labels.title).toBe('Confirm Delete Load Balancers'); }); it('should pass function to modal that deletes load balancers', function() { spyOn(modal, 'open').and.callThrough(); spyOn(lbaasv2Api, 'deleteLoadBalancer').and.callThrough(); service.perform(items[0]); $scope.$apply(); expect(lbaasv2Api.deleteLoadBalancer.calls.count()).toBe(1); expect(lbaasv2Api.deleteLoadBalancer).toHaveBeenCalledWith('1', true); }); it('should show message if any selected items do not allow for delete (batch)', function() { spyOn(modal, 'open'); spyOn(toast, 'add'); items[0].provisioning_status = 'PENDING_UPDATE'; items[1].provisioning_status = 'PENDING_DELETE'; service.perform(items); $scope.$apply(); expect(modal.open).not.toHaveBeenCalled(); expect(toast.add).toHaveBeenCalledWith('error', 'The following load balancers are pending and cannot be deleted: First, Second.'); }); it('should show message if any items fail to be deleted', function() { spyOn(modal, 'open').and.callThrough(); spyOn(lbaasv2Api, 'deleteLoadBalancer').and.returnValue(makePromise(true)); spyOn(toast, 'add'); items.splice(1, 1); service.perform(items); $scope.$apply(); expect(modal.open).toHaveBeenCalled(); expect(lbaasv2Api.deleteLoadBalancer.calls.count()).toBe(1); expect(toast.add).toHaveBeenCalledWith('error', 'The following load balancers could not ' + 'be deleted, possibly due to existing listeners: First.'); }); it('should reload table after delete', function() { path = 'project/ngloadbalancersv2'; spyOn($route, 'reload'); service.perform(items); $scope.$apply(); expect($route.reload).toHaveBeenCalled(); }); it('should return to table after delete if on detail page', function() { path = 'project/ngloadbalancersv2/1'; spyOn($location, 'path'); spyOn(toast, 'add'); service.perform(items[0]); $scope.$apply(); expect($location.path).toHaveBeenCalledWith('project/ngloadbalancersv2'); expect(toast.add).toHaveBeenCalledWith('success', 'Deleted load balancers: First.'); }); }); })(); ././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/delete/delete.action.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000001222213245511613034036 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete', deleteService); deleteService.$inject = [ '$q', '$location', '$route', 'horizon.framework.widgets.modal.deleteModalService', 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.widgets.toast.service', 'horizon.framework.util.q.extensions', 'horizon.framework.util.i18n.gettext' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.loadbalancers.actions.deleteService * @description * Brings up the delete load balancers confirmation modal dialog. * On submit, deletes selected load balancers. * On cancel, does nothing. * @param $q The angular service for promises. * @param $location The angular $location service. * @param $route The angular $route service. * @param deleteModal The horizon delete modal service. * @param api The LBaaS v2 API service. * @param policy The horizon policy service. * @param toast The horizon message service. * @param qExtensions Horizon extensions to the $q service. * @param gettext The horizon gettext function for translation. * @returns The load balancers table delete service. */ function deleteService( $q, $location, $route, deleteModal, api, policy, toast, qExtensions, gettext ) { // If a batch delete, then this message is displayed for any selected load balancers not in // ACTIVE or ERROR state. var notAllowedMessage = gettext('The following load balancers are pending and cannot be ' + 'deleted: %s.'); var context = { labels: { title: gettext('Confirm Delete Load Balancers'), message: gettext('You have selected "%s". Please confirm your selection. Deleted load ' + 'balancers are not recoverable.'), submit: gettext('Delete Load Balancers'), success: gettext('Deleted load balancers: %s.'), error: gettext('The following load balancers could not be deleted, possibly due to ' + 'existing listeners: %s.') }, deleteEntity: deleteItem, successEvent: 'success', failedEvent: 'error' }; var service = { perform: perform, allowed: allowed }; return service; ////////////// function perform(items) { if (angular.isArray(items)) { qExtensions.allSettled(items.map(checkPermission)).then(afterCheck); } else { deleteModal.open({ $emit: actionComplete }, [items], context); } } function allowed(item) { // This rule is made up and should therefore always pass. I assume at some point there // will be a valid rule similar to this that we will want to use. var promises = [policy.ifAllowed({ rules: [['neutron', 'delete_loadbalancer']] })]; if (item) { var status = item.provisioning_status; promises.push(qExtensions.booleanAsPromise(status === 'ACTIVE' || status === 'ERROR')); } return $q.all(promises); } function canBeDeleted(item) { var status = item.provisioning_status; return qExtensions.booleanAsPromise(status === 'ACTIVE' || status === 'ERROR'); } function checkPermission(item) { return { promise: canBeDeleted(item), context: item }; } function afterCheck(result) { if (result.fail.length > 0) { toast.add('error', getMessage(notAllowedMessage, result.fail)); } if (result.pass.length > 0) { deleteModal.open({ $emit: actionComplete }, result.pass.map(getEntity), context); } } function deleteItem(id) { return api.deleteLoadBalancer(id, true); } function getMessage(message, entities) { return interpolate(message, [entities.map(getName).join(", ")]); } function getName(result) { return getEntity(result).name; } function getEntity(result) { return result.context; } function actionComplete(eventType) { if (eventType === context.failedEvent) { // Action failed, reload the page $route.reload(); } else { // If the user is on the load balancers table then just reload the page, otherwise they // are on the details page and we return to the table. if (/\/ngloadbalancersv2(\/)?$/.test($location.path())) { $route.reload(); } else { $location.path('project/ngloadbalancersv2'); } } } } })(); ././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000775000175100017510000000000013245512321034030 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021300000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000717413245511613034050 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip.modal.service', modalService); modalService.$inject = [ '$q', '$uibModal', '$route', 'horizon.dashboard.project.lbaasv2.basePath', 'horizon.app.core.openstack-service-api.policy', 'horizon.app.core.openstack-service-api.network', 'horizon.framework.util.q.extensions', 'horizon.framework.widgets.toast.service', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip.modal.service * * @description * Provides the service for the Load Balancer Associate Floating IP action. * * @param $q The angular service for promises. * @param $uibModal The angular bootstrap $uibModal service. * @param $route The angular $route service. * @param basePath The LBaaS v2 module base path. * @param policy The horizon policy service. * @param network The horizon network API service. * @param qExtensions Horizon extensions to the $q service. * @param toastService The horizon toast service. * @param gettext The horizon gettext function for translation. * * @returns The Associate Floating IP modal service. */ function modalService( $q, $uibModal, $route, basePath, policy, network, qExtensions, toastService, gettext ) { var service = { perform: open, allowed: allowed }; return service; //////////// function allowed(item) { return $q.all([ qExtensions.booleanAsPromise(item.floating_ip && !item.floating_ip.ip), // This rule is made up and should therefore always pass. At some point there will // likely be a valid rule similar to this that we will want to use. policy.ifAllowed({ rules: [['neutron', 'loadbalancer_associate_floating_ip']] }) ]); } /** * @ngdoc method * @name open * * @description * Open the modal. * * @param item The row item from the table action. * @returns undefined */ function open(item) { var spec = { backdrop: 'static', controller: 'AssociateFloatingIpModalController as modal', templateUrl: basePath + 'loadbalancers/actions/associate-ip/modal.html', resolve: { loadbalancer: function() { return item; }, floatingIps: function() { return network.getFloatingIps().then(getResponseItems); }, floatingIpPools: function() { return network.getFloatingIpPools().then(getResponseItems); } } }; $uibModal.open(spec).result.then(onModalClose); } function onModalClose() { toastService.add('success', gettext('Associating floating IP with load balancer.')); $route.reload(); } function getResponseItems(response) { return response.data.items; } } })(); ././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000254313245511613034043 0ustar zuulzuul00000000000000 ././@LongLink0000000000000000000000000000021600000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000702713245511613034045 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .controller('AssociateFloatingIpModalController', AssociateFloatingIpModalController); AssociateFloatingIpModalController.$inject = [ '$uibModalInstance', 'horizon.app.core.openstack-service-api.network', 'horizon.framework.util.i18n.gettext', // Dependencies injected with resolve by $uibModal.open 'loadbalancer', 'floatingIps', 'floatingIpPools' ]; /** * @ngdoc controller * @name AssociateFloatingIpModalController * @description * Controller used by the modal service for associating a floating IP address to a * load balancer. * * @param $uibModalInstance The angular bootstrap $uibModalInstance service. * @param api The horizon network API service. * @param gettext The horizon gettext function for translation. * @param loadbalancer The load balancer to associate the floating IP with. * @param floatingIps List of available floating IP addresses. * @param floatingIpPools List of available floating IP pools. * * @returns The Associate Floating IP modal controller. */ function AssociateFloatingIpModalController( $uibModalInstance, api, gettext, loadbalancer, floatingIps, floatingIpPools ) { var ctrl = this; var port = loadbalancer.vip_port_id + '_' + loadbalancer.vip_address; ctrl.cancel = cancel; ctrl.save = save; ctrl.saving = false; ctrl.options = initOptions(); ctrl.selected = ctrl.options.length === 1 ? ctrl.options[0] : null; function save() { ctrl.saving = true; if (ctrl.selected.type === 'pool') { allocateIpAddress(ctrl.selected.id); } else { associateIpAddress(ctrl.selected.id); } } function cancel() { $uibModalInstance.dismiss('cancel'); } function onSuccess() { $uibModalInstance.close(); } function onFailure() { ctrl.saving = false; } function initOptions() { var options = []; floatingIps.forEach(function addFloatingIp(ip) { // Only show floating IPs that are not already associated with a fixed IP if (!ip.fixed_ip) { options.push({ id: ip.id, name: ip.ip || ip.id, type: 'ip', group: gettext('Floating IP addresses') }); } }); floatingIpPools.forEach(function addFloatingIpPool(pool) { options.push({ id: pool.id, name: pool.name || pool.id, type: 'pool', group: gettext('Floating IP pools') }); }); return options; } function allocateIpAddress(poolId) { return api.allocateFloatingIp(poolId).then(getId).then(associateIpAddress); } function associateIpAddress(addressId) { return api.associateFloatingIp(addressId, port).then(onSuccess, onFailure); } function getId(response) { return response.data.id; } } })(); ././@LongLink0000000000000000000000000000022000000000000011207 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000001035013245511613034036 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Load Balancers Table Associate IP Service', function() { var service, policy, $scope, $route, item, $uibModal, toast; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = service.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); $scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith( {rules: [['neutron', 'loadbalancer_associate_floating_ip']]}); return allowed; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(function() { item = { id: '1', name: 'First', floating_ip: {} }; }); beforeEach(module(function($provide) { var fakePromise = function(response) { return { then: function(func) { return func(response); } }; }; $provide.value('$uibModal', { open: function() { return { result: fakePromise() }; } }); $provide.value('horizon.app.core.openstack-service-api.network', { getFloatingIps: function() { return fakePromise({ data: { items: 'foo' } }); }, getFloatingIpPools: function() { return fakePromise({ data: { items: 'bar' } }); } }); })); beforeEach(inject(function ($injector) { policy = $injector.get('horizon.app.core.openstack-service-api.policy'); toast = $injector.get('horizon.framework.widgets.toast.service'); $scope = $injector.get('$rootScope').$new(); $route = $injector.get('$route'); $uibModal = $injector.get('$uibModal'); service = $injector.get( 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip.modal.service'); })); it('should have the "allowed" and "perform" functions', function() { expect(service.allowed).toBeDefined(); expect(service.perform).toBeDefined(); }); it('should check policy to allow the action', function() { expect(allowed(item)).toBe(true); }); it('should not allow action if floating IP already associated', function() { item.floating_ip.ip = 'foo'; expect(allowed(item)).toBe(false); }); it('should open the modal', function() { spyOn($uibModal, 'open').and.callThrough(); service.perform(item); $scope.$apply(); expect($uibModal.open.calls.count()).toBe(1); }); it('should resolve data for passing into the modal', function() { spyOn($uibModal, 'open').and.callThrough(); service.perform(item); $scope.$apply(); var resolve = $uibModal.open.calls.argsFor(0)[0].resolve; expect(resolve).toBeDefined(); expect(resolve.loadbalancer).toBeDefined(); expect(resolve.loadbalancer()).toEqual(item); expect(resolve.floatingIps).toBeDefined(); expect(resolve.floatingIps()).toBe('foo'); expect(resolve.floatingIpPools).toBeDefined(); expect(resolve.floatingIpPools()).toBe('bar'); }); it('should show message and reload page upon closing modal', function() { spyOn(toast, 'add'); spyOn($route, 'reload'); service.perform(item); $scope.$apply(); expect(toast.add).toHaveBeenCalledWith('success', 'Associating floating IP with load balancer.'); expect($route.reload).toHaveBeenCalled(); }); }); })(); ././@LongLink0000000000000000000000000000022300000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000001266513245511613034051 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Load Balancers Table Associate IP Controller', function() { var ctrl, network, floatingIps, floatingIpPools, $controller, $uibModalInstance; var associateFail = false; beforeEach(module('horizon.framework.util.i18n')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(function() { floatingIps = [{ id: 'ip1', ip: '1', fixed_ip: '1' }, { id: 'ip2', ip: '2' }]; floatingIpPools = [{ id: 'pool1', name: 'pool' }]; }); beforeEach(module(function($provide) { var fakePromise = function(response, returnPromise) { return { then: function(success, fail) { if (fail && associateFail) { return fail(); } var res = success(response); return returnPromise ? fakePromise(res) : res; } }; }; $provide.value('$uibModalInstance', { close: angular.noop, dismiss: angular.noop }); $provide.value('loadbalancer', { vip_port_id: 'port', vip_address: 'address' }); $provide.value('floatingIps', floatingIps); $provide.value('floatingIpPools', floatingIpPools); $provide.value('horizon.app.core.openstack-service-api.network', { allocateFloatingIp: function() { return fakePromise({ data: { id: 'foo' } }, true); }, associateFloatingIp: function() { return fakePromise(); } }); })); beforeEach(inject(function ($injector) { network = $injector.get('horizon.app.core.openstack-service-api.network'); $controller = $injector.get('$controller'); $uibModalInstance = $injector.get('$uibModalInstance'); })); it('should define controller properties', function() { ctrl = $controller('AssociateFloatingIpModalController'); expect(ctrl.cancel).toBeDefined(); expect(ctrl.save).toBeDefined(); expect(ctrl.saving).toBe(false); }); it('should initialize options', function() { ctrl = $controller('AssociateFloatingIpModalController'); expect(ctrl.options.length).toBe(2); expect(ctrl.options[0].id).toBe('ip2'); expect(ctrl.options[1].id).toBe('pool1'); }); it('should use ids instead of ip or name if not provided', function() { delete floatingIps[1].ip; delete floatingIpPools[0].name; ctrl = $controller('AssociateFloatingIpModalController'); expect(ctrl.options.length).toBe(2); expect(ctrl.options[0].name).toBe('ip2'); expect(ctrl.options[1].name).toBe('pool1'); }); it('should initialize selected option when only one option', function() { floatingIps[1].fixed_ip = '2'; ctrl = $controller('AssociateFloatingIpModalController'); expect(ctrl.options.length).toBe(1); expect(ctrl.selected).toBe(ctrl.options[0]); }); it('should not initialize selected option when more than one option', function() { ctrl = $controller('AssociateFloatingIpModalController'); expect(ctrl.options.length).toBe(2); expect(ctrl.selected).toBeNull(); }); it('should associate floating IP if floating IP selected', function() { ctrl = $controller('AssociateFloatingIpModalController'); ctrl.selected = ctrl.options[0]; spyOn(network, 'associateFloatingIp').and.callThrough(); spyOn($uibModalInstance, 'close'); ctrl.save(); expect(ctrl.saving).toBe(true); expect(network.associateFloatingIp).toHaveBeenCalledWith('ip2', 'port_address'); expect($uibModalInstance.close).toHaveBeenCalled(); }); it('should allocate floating IP if floating IP pool selected', function() { ctrl = $controller('AssociateFloatingIpModalController'); ctrl.selected = ctrl.options[1]; spyOn(network, 'allocateFloatingIp').and.callThrough(); spyOn(network, 'associateFloatingIp').and.callThrough(); spyOn($uibModalInstance, 'close'); ctrl.save(); expect(ctrl.saving).toBe(true); expect(network.allocateFloatingIp).toHaveBeenCalledWith('pool1'); expect(network.associateFloatingIp).toHaveBeenCalledWith('foo', 'port_address'); expect($uibModalInstance.close).toHaveBeenCalled(); }); it('should dismiss modal if cancel clicked', function() { ctrl = $controller('AssociateFloatingIpModalController'); spyOn($uibModalInstance, 'dismiss'); ctrl.cancel(); expect($uibModalInstance.dismiss).toHaveBeenCalledWith('cancel'); }); it('should not dismiss modal if save fails', function() { ctrl = $controller('AssociateFloatingIpModalController'); ctrl.selected = ctrl.options[0]; associateFail = true; spyOn($uibModalInstance, 'dismiss'); ctrl.save(); expect($uibModalInstance.dismiss).not.toHaveBeenCalled(); expect(ctrl.saving).toBe(false); }); }); })(); ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000527613245511613034051 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Load Balancers Table Controller', function() { var controller, lbaasv2API, scope; var items = [{ foo: 'bar' }]; var apiFail = false; function fakeAPI() { return { then: function(success, fail) { if (apiFail && fail) { fail(); } else { success({ data: { items: items } }); } } }; } /////////////////////// beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { $provide.value('$uibModal', {}); })); beforeEach(inject(function($injector) { lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); controller = $injector.get('$controller'); scope = $injector.get('$rootScope').$new(); spyOn(lbaasv2API, 'getLoadBalancers').and.callFake(fakeAPI); })); function createController() { return controller('LoadBalancersTableController', { $scope: scope }); } it('should initialize correctly', function() { var ctrl = createController(); expect(ctrl.items).toEqual([]); expect(ctrl.src).toEqual(items); expect(ctrl.loading).toBe(false); expect(ctrl.error).toBe(false); expect(ctrl.checked).toEqual({}); expect(ctrl.batchActions).toBeDefined(); expect(ctrl.rowActions).toBeDefined(); expect(ctrl.operatingStatus).toBeDefined(); expect(ctrl.provisioningStatus).toBeDefined(); }); it('should invoke lbaasv2 apis', function() { var ctrl = createController(); expect(lbaasv2API.getLoadBalancers).toHaveBeenCalled(); expect(ctrl.src.length).toBe(1); }); it('should show error if loading fails', function() { apiFail = true; var ctrl = createController(); expect(ctrl.src.length).toBe(0); expect(ctrl.error).toBe(true); }); }); })(); ././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000531513245511613034043 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Load Balancer Detail Controller', function() { var lbaasv2API, $scope, $window, $controller, apiFail; function fakeAPI() { return { then: function(success, fail) { if (apiFail && fail) { fail(); } else { success({ id: '1234' }); } } }; } function createController() { return $controller('LoadBalancerDetailController', { $scope: $scope, $window: $window, $routeParams: { loadbalancerId: '1234' } }); } /////////////////////// beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { apiFail = false; $provide.value('$uibModal', {}); })); beforeEach(inject(function($injector) { lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(fakeAPI); $scope = $injector.get('$rootScope').$new(); $window = {}; $controller = $injector.get('$controller'); })); it('should invoke lbaasv2 apis', function() { createController(); expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('1234', true); }); it('should save changes to listeners tab active state', function() { var ctrl = createController(); expect($window.listenersTabActive).toBeUndefined(); expect(ctrl.listenersTabActive).toBeUndefined(); ctrl.listenersTabActive = true; $scope.$apply(); expect($window.listenersTabActive).toBe(true); ctrl.listenersTabActive = false; $scope.$apply(); expect($window.listenersTabActive).toBe(false); }); it('should set error state', function() { apiFail = true; var ctrl = createController(); expect(ctrl.loading).toBe(false); expect(ctrl.error).toBe(true); }); }); })(); ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000001305313245511613034041 0ustar zuulzuul00000000000000
Name Description Operating Status Provisioning Status IP Address Listeners Actions
{$ ::(item.name || item.id) $} {$ ::item.description | noValue $} {$ ::item.operating_status | decode:table.operatingStatus $} {$ ::item.provisioning_status | decode:table.provisioningStatus $} {$ ::item.vip_address $} {$ item.listeners.length $}
IP Address
{$ ::item.vip_address $}
Listeners
{$ item.listeners.length $}
Provider
{$ ::item.provider $}
Floating IP Address
{$ item.floating_ip.ip || 'None' | translate $}
Admin State Up
{$ ::item.admin_state_up | yesno $}
ID
{$ ::item.id $}
Subnet ID
{$ ::item.vip_subnet_id $}
Port ID
{$ ::item.vip_port_id $}
././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000521313245511613034040 0ustar zuulzuul00000000000000
Provider
{$ ::ctrl.loadbalancer.provider $}
Admin State Up
{$ ctrl.loadbalancer.admin_state_up | yesno $}
Floating IP Address
{$ ctrl.loadbalancer.floating_ip.ip | noValue:('None' | translate) $}
Load Balancer ID
{$ ::ctrl.loadbalancer.id $}
Subnet ID
{$ ::ctrl.loadbalancer.vip_subnet_id $}
Port ID
{$ ::ctrl.loadbalancer.vip_port_id $}
././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000504113245511613034037 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .factory('horizon.dashboard.project.lbaasv2.loadbalancers.service', loadBalancersService); loadBalancersService.$inject = [ '$q', 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc service * @name horizon.dashboard.project.lbaasv2.loadbalancers.service * @description General service for LBaaS v2 load balancers. * @param $q The angular service for promises. * @param api The LBaaS V2 service API. * @param gettext The horizon gettext function for translation. * @returns The load balancers service. */ function loadBalancersService($q, api, gettext) { var operatingStatus = { ONLINE: gettext('Online'), OFFLINE: gettext('Offline'), DEGRADED: gettext('Degraded'), ERROR: gettext('Error') }; var provisioningStatus = { ACTIVE: gettext('Active'), INACTIVE: gettext('Inactive'), PENDING_CREATE: gettext('Pending Create'), PENDING_UPDATE: gettext('Pending Update'), PENDING_DELETE: gettext('Pending Delete'), ERROR: gettext('Error') }; var service = { operatingStatus: operatingStatus, provisioningStatus: provisioningStatus, isActionable: isActionable }; return service; //////////// /** * @ngdoc method * @name horizon.dashboard.project.lbaasv2.loadbalancers.service.isActionable * @description Returns a promise that is resolved if the load balancer is in a state that * allows for it or child resources to be updated or deleted. * @param id The load balancer id. * @returns {Promise} */ function isActionable(id) { return api.getLoadBalancer(id).then(function onLoad(response) { if (['ACTIVE', 'ERROR'].indexOf(response.data.provisioning_status) < 0) { return $q.reject(); } }); } } }()); ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000150113245511613034034 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Load Balancers Module', function() { it('should exist', function() { expect(angular.module('horizon.dashboard.project.lbaasv2.loadbalancers')).toBeDefined(); }); }); })(); ././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000436013245511613034042 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Load Balancers Service', function() { var service, $q, $scope; beforeEach(module('horizon.framework.widgets.toast')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { $provide.value('horizon.app.core.openstack-service-api.lbaasv2', { getLoadBalancer: function(index) { var loadbalancers = [{ provisioning_status: 'ACTIVE' }, { provisioning_status: 'PENDING_UPDATE' }]; var deferred = $q.defer(); deferred.resolve({ data: loadbalancers[index] }); return deferred.promise; } }); })); beforeEach(inject(function ($injector) { $q = $injector.get('$q'); $scope = $injector.get('$rootScope').$new(); service = $injector.get('horizon.dashboard.project.lbaasv2.loadbalancers.service'); })); it('should define value mappings', function() { expect(service.operatingStatus).toBeDefined(); expect(service.provisioningStatus).toBeDefined(); }); it('should allow checking status of load balancer', function() { var active = null; service.isActionable(0).then(function() { active = true; }); $scope.$apply(); expect(active).toBe(true); active = null; service.isActionable(1).then(angular.noop, function() { active = false; }); $scope.$apply(); expect(active).toBe(false); }); }); })(); ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000540413245511613034042 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .controller('LoadBalancerDetailController', LoadBalancerDetailController); LoadBalancerDetailController.$inject = [ 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions', 'horizon.dashboard.project.lbaasv2.loadbalancers.service', '$routeParams', '$window', '$scope' ]; /** * @ngdoc controller * @name LoadBalancerDetailController * * @description * Controller for the LBaaS v2 load balancers detail page. * * @param api The LBaaS v2 API service. * @param rowActions The load balancer row actions service. * @param loadBalancersService The LBaaS v2 load balancers service. * @param $routeParams The angular $routeParams service. * @param $window Angular's reference to the browser window object. * @param $scope The angular scope object. * @returns undefined */ function LoadBalancerDetailController( api, rowActions, loadBalancersService, $routeParams, $window, $scope ) { var ctrl = this; ctrl.loading = true; ctrl.error = false; ctrl.actions = rowActions.actions; ctrl.operatingStatus = loadBalancersService.operatingStatus; ctrl.provisioningStatus = loadBalancersService.provisioningStatus; ctrl.listenersTabActive = $window.listenersTabActive; init(); //////////////////////////////// function init() { ctrl.loadbalancer = null; ctrl.loading = true; ctrl.error = false; api.getLoadBalancer($routeParams.loadbalancerId, true).then(success, fail); } function success(response) { ctrl.loadbalancer = response.data; ctrl.loading = false; } function fail(/*response*/) { ctrl.loadbalancer = null; ctrl.loading = false; ctrl.error = true; } // Save the active state of the listeners tab in the global window object so it can stay // active after reloading the route following an action. $scope.$watch(function() { return ctrl.listenersTabActive; }, function(active) { $window.listenersTabActive = active; }); } })(); ././@LongLink0000000000000000000000000000017500000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000165313245511613034044 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; /** * @ngdoc overview * @ngname horizon.dashboard.project.lbaasv2.loadbalancers * * @description * Provides the services and widgets required to support and display the project load * balancers v2 panel. */ angular .module('horizon.dashboard.project.lbaasv2.loadbalancers', []); })(); ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers0000666000175100017510000000455313245511613034046 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .controller('LoadBalancersTableController', LoadBalancersTableController); LoadBalancersTableController.$inject = [ 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions', 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions', 'horizon.dashboard.project.lbaasv2.loadbalancers.service' ]; /** * @ngdoc controller * @name LoadBalancersTableController * * @description * Controller for the LBaaS v2 load balancers table. Serves as the focal point for table actions. * * @param api The LBaaS V2 service API. * @param batchActions The load balancer batch actions service. * @param rowActions The load balancer row actions service. * @param loadBalancersService The LBaaS v2 load balancers service. * @returns undefined */ function LoadBalancersTableController(api, batchActions, rowActions, loadBalancersService) { var ctrl = this; ctrl.items = []; ctrl.src = []; ctrl.loading = true; ctrl.error = false; ctrl.checked = {}; ctrl.batchActions = batchActions; ctrl.rowActions = rowActions; ctrl.operatingStatus = loadBalancersService.operatingStatus; ctrl.provisioningStatus = loadBalancersService.provisioningStatus; init(); //////////////////////////////// function init() { ctrl.src = []; ctrl.loading = true; api.getLoadBalancers(true).then(success, fail); } function success(response) { ctrl.src = response.data.items; ctrl.loading = false; } function fail(/*response*/) { ctrl.src = []; ctrl.error = true; ctrl.loading = false; } } })(); neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.scss0000666000175100017510000000455713245511613033564 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ /* Load Balancer Wizard */ .lbaas-wizard { /* Field widths for editable inputs in the members table */ table { .member-weight, .member-port { width: 6em; } .member-address { width: 18em; } } /* The IP addresses list displayed when hovering over the IP address in the available instances table, and any lists in the help panels. */ .addresses-popover + .popover, #help-panel { ul { list-style-type: disc; padding-left: 10px; } } /* Pool Members tab */ [ng-form="memberDetailsForm"] { .transfer-section:first-child { /* Remove the borders around the last row in the top table that has the "Add external member" action in it. */ .table-rsp.table-detail tbody tr:nth-last-child(2):not(.expanded) td, .table-rsp.table-detail tbody tr:last-child:not(.spacer-row) td { border-bottom: none; } /* Remove the striped background on the last row in the top table that has the "Add external member" action in it. */ .table-rsp.table-detail.table-striped tbody tr:last-child > td { background: none; } td { /* So the input fields fit better in the table row */ .form-group { margin-bottom: 0px; } } } .transfer-section:last-child { /* Hide the badge on the bottom table with the instance count. */ .transfer-heading .badge { display: none; } } } } /* Progress indicator while data is loading */ [table-status], detail-status { .progress { margin: 0px auto; width: 25%; height: $line-height-computed; .progress-bar { width: 100%; } } } detail-status { .progress { margin-top: 25vh; } .error-actions { text-align: center; margin-top: 10px; } }././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.modul0000666000175100017510000001120413245511613033714 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Module', function () { it('should be defined', function () { expect(angular.module('horizon.dashboard.project.lbaasv2')).toBeDefined(); }); }); describe('LBaaS v2 Module Base Path', function () { var basePath, staticUrl; beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function ($injector) { basePath = $injector.get('horizon.dashboard.project.lbaasv2.basePath'); staticUrl = $injector.get('$window').STATIC_URL; })); it('should be defined', function () { expect(basePath).toBeDefined(); }); it('should be correct', function () { expect(basePath).toEqual(staticUrl + 'dashboard/project/lbaasv2/'); }); }); describe('LBaaS v2 Module Constants', function () { var patterns, popovers; beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function ($injector) { patterns = $injector.get('horizon.dashboard.project.lbaasv2.patterns'); popovers = $injector.get('horizon.dashboard.project.lbaasv2.popovers'); })); it('should define patterns', function () { expect(patterns).toBeDefined(); }); it('should define expected patterns', function () { expect(Object.keys(patterns).length).toBe(4); var keys = ['ipv4', 'ipv6', 'httpStatusCodes', 'urlPath']; angular.forEach(keys, function(key) { expect(patterns[key]).toBeDefined(); }); }); it('should define correct pattern for health monitor status codes', function () { expect(Object.keys(patterns).length).toBe(4); var regex = patterns.httpStatusCodes; expect(regex.test('200')).toBe(true); expect(regex.test('200-204')).toBe(true); expect(regex.test('200,203,204')).toBe(true); expect(regex.test('foo')).toBe(false); expect(regex.test('200,202-204')).toBe(false); }); it('should define popovers', function () { expect(popovers).toBeDefined(); }); it('should define expected popover templates', function () { expect(Object.keys(popovers).length).toBe(1); var keys = ['ipAddresses']; angular.forEach(keys, function(key) { expect(popovers[key]).toBeDefined(); }); }); }); describe('LBaaS v2 Module Config', function () { var $routeProvider, basePath; beforeEach(function() { // Create a dummy module so that we can test $routeProvider calls in our actual // config block. angular.module('configTest', []) .config(function(_$routeProvider_, $windowProvider) { $routeProvider = _$routeProvider_; basePath = $windowProvider.$get().STATIC_URL + 'dashboard/project/lbaasv2/'; spyOn($routeProvider, 'when').and.callThrough(); }); module('ngRoute'); module('configTest'); module('horizon.dashboard.project.lbaasv2'); inject(); }); it('should route URLs', function () { var loadbalancers = '/project/ngloadbalancersv2'; var listener = loadbalancers + '/:loadbalancerId/listeners/:listenerId'; var pool = listener + '/pools/:poolId'; var member = pool + '/members/:memberId'; var healthmonitor = pool + '/healthmonitors/:healthmonitorId'; var routes = [[ loadbalancers, { templateUrl: basePath + 'loadbalancers/table.html' } ], [ loadbalancers + '/:loadbalancerId', { templateUrl: basePath + 'loadbalancers/detail.html' } ], [ listener, { templateUrl: basePath + 'listeners/detail.html' } ], [ pool, { templateUrl: basePath + 'pools/detail.html' } ], [ member, { templateUrl: basePath + 'members/detail.html' } ], [ healthmonitor, { templateUrl: basePath + 'healthmonitors/detail.html' } ]]; expect($routeProvider.when.calls.count()).toBe(6); angular.forEach($routeProvider.when.calls.all(), function(call, i) { expect(call.args).toEqual(routes[i]); }); }); }); })(); neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/0000775000175100017510000000000013245512321032763 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table0000775000175100017510000000000013245512321033773 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table/table-status.directive.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table0000666000175100017510000000312713245511613034005 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2') .directive('tableStatus', tableStatus); tableStatus.$inject = [ 'horizon.dashboard.project.lbaasv2.basePath' ]; /** * @ngdoc directive * @name horizon.dashboard.project.lbaasv2:tableStatus * @description * The `tableStatus` directive provides a status indicator while loading a table. The table * should have loading and error properties that give the status of the table, and an items * array that holds the items being displayed in the table. The column count can be provided * to fit the status row to an exact number of columns. * @restrict A * * @example * ``` * * ``` */ function tableStatus(basePath) { var directive = { restrict: 'A', templateUrl: basePath + 'widgets/table/table-status.html', scope: { table: '=', columnCount: '=?' } }; return directive; } }()); ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table/table-status.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table0000666000175100017510000000123413245511613034002 0ustar zuulzuul00000000000000 No items to display.
Loading An error occurred. Please try again later.
././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table/table-status.directive.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table0000666000175100017510000000712713245511613034011 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; function digestMarkup(scope, compile, markup) { var element = angular.element(markup); compile(element)(scope); scope.$apply(); return element; } describe('tableStatus directive', function() { var $scope, $compile, markup, table; beforeEach(module('templates')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function($injector) { $compile = $injector.get('$compile'); $scope = $injector.get('$rootScope').$new(); table = { loading: true, error: false, items: [] }; $scope.table = table; markup = ''; })); it('initially shows loading status', function() { var element = digestMarkup($scope, $compile, markup); expect(element).toBeDefined(); expect(element.children().length).toBe(1); expect(element.children().first().hasClass('no-rows-help')).toBe(false); expect(element.find('.progress-bar').hasClass('progress-bar-striped')).toBe(true); expect(element.find('.progress-bar').hasClass('progress-bar-danger')).toBe(false); expect(element.find('.progress-bar > span').length).toBe(1); expect(element.find('.progress-bar > span').hasClass('sr-only')).toBe(true); }); it('indicates error status on error', function() { var element = digestMarkup($scope, $compile, markup); expect(element).toBeDefined(); table.loading = false; table.error = true; $scope.$apply(); expect(element.children().length).toBe(1); expect(element.children().first().hasClass('no-rows-help')).toBe(false); expect(element.find('.progress-bar').hasClass('progress-bar-striped')).toBe(false); expect(element.find('.progress-bar').hasClass('progress-bar-danger')).toBe(true); expect(element.find('.progress-bar > span').length).toBe(1); expect(element.find('.progress-bar > span').hasClass('sr-only')).toBe(false); expect(element.find('.progress-bar > span').text().trim()) .toBe('An error occurred. Please try again later.'); }); it('indicates no rows when there are no rows to display', function() { var element = digestMarkup($scope, $compile, markup); expect(element).toBeDefined(); table.loading = false; table.error = false; $scope.$apply(); expect(element.children().length).toBe(1); expect(element.children().first().hasClass('no-rows-help')).toBe(true); expect(element.find('.progress').length).toBe(0); expect(element.find('span').length).toBe(1); expect(element.find('span').text().trim()).toBe('No items to display.'); }); it('goes away when done loading and there are rows to display', function() { var element = digestMarkup($scope, $compile, markup); expect(element).toBeDefined(); table.loading = false; table.error = false; table.items = ['foo']; $scope.$apply(); expect(element.children().length).toBe(0); }); }); }()); ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detail/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detai0000775000175100017510000000000013245512321033772 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020600000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detail/detail-status.directive.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detai0000666000175100017510000000613513245511613034006 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; function digestMarkup(scope, compile, markup) { var element = angular.element(markup); compile(element)(scope); scope.$apply(); return element; } describe('detailStatus directive', function() { var $scope, $compile, markup, ctrl; beforeEach(module('templates')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function($injector) { $compile = $injector.get('$compile'); $scope = $injector.get('$rootScope').$new(); ctrl = { loading: true, error: false }; $scope.ctrl = ctrl; markup = ''; })); it('initially shows loading status', function() { var element = digestMarkup($scope, $compile, markup); expect(element).toBeDefined(); expect(element.children().length).toBe(1); expect(element.find('.progress-bar').hasClass('progress-bar-striped')).toBe(true); expect(element.find('.progress-bar').hasClass('progress-bar-danger')).toBe(false); expect(element.find('.progress-bar > span').length).toBe(1); expect(element.find('.progress-bar > span').hasClass('sr-only')).toBe(true); expect(element.find('.progress-bar > span').text().trim()).toBe('Loading'); expect(element.find('.message').length).toBe(0); }); it('indicates error status on error', function() { var element = digestMarkup($scope, $compile, markup); expect(element).toBeDefined(); ctrl.loading = false; ctrl.error = true; $scope.$apply(); expect(element.children().length).toBe(1); expect(element.find('.progress-bar').hasClass('progress-bar-striped')).toBe(false); expect(element.find('.progress-bar').hasClass('progress-bar-danger')).toBe(true); expect(element.find('.progress-bar > span').length).toBe(1); expect(element.find('.progress-bar > span').hasClass('sr-only')).toBe(false); expect(element.find('.progress-bar > span').text().trim()) .toBe('An error occurred. Please try again later.'); expect(element.find('.error-actions').length).toBe(1); expect(element.find('.error-actions > a').text().trim()).toBe('Back'); }); it('goes away when done loading', function() { var element = digestMarkup($scope, $compile, markup); expect(element).toBeDefined(); ctrl.loading = false; ctrl.error = false; $scope.$apply(); expect(element.children().length).toBe(0); }); }); }()); ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detail/detail-status.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detai0000666000175100017510000000076213245511613034006 0ustar zuulzuul00000000000000
Loading An error occurred. Please try again later.
././@LongLink0000000000000000000000000000020100000000000011206 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detail/detail-status.directive.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detai0000666000175100017510000000276513245511613034013 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2') .directive('detailStatus', detailStatus); detailStatus.$inject = [ 'horizon.dashboard.project.lbaasv2.basePath' ]; /** * @ngdoc directive * @name horizon.dashboard.project.lbaasv2:detailStatus * @description * The `detailStatus` directive provides a status indicator while loading detail pages. It will * show a loading indicator while the page is loading and an error indicator if there is an * error loading the page. * @restrict E * * @example * ``` * * ``` */ function detailStatus(basePath) { var directive = { restrict: 'E', templateUrl: basePath + 'widgets/detail/detail-status.html', scope: { loading: '=', error: '=' } }; return directive; } }()); ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000775000175100017510000000000013245512321034113 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000775000175100017510000000000013245512321034113 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/edit/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000775000175100017510000000000013245512321034113 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/edit/wizard.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000257213245511613034130 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.healthmonitors') .controller('EditHealthMonitorWizardController', EditHealthMonitorWizardController); EditHealthMonitorWizardController.$inject = [ '$scope', 'horizon.dashboard.project.lbaasv2.workflow.model', 'horizon.dashboard.project.lbaasv2.workflow.workflow', 'horizon.framework.util.i18n.gettext' ]; function EditHealthMonitorWizardController($scope, model, workflowService, gettext) { var scope = $scope; scope.model = model; scope.submit = scope.model.submit; scope.workflow = workflowService( gettext('Update Health Monitor'), 'fa fa-cloud-download', ['monitor'] ); scope.model.initialize('monitor', scope.launchContext.id); } })(); ././@LongLink0000000000000000000000000000021700000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/edit/edit.action.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000626113245511613034127 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Edit Health Monitor Action Service', function() { var scope, $q, $route, policy, init, service, loadBalancerState; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = service.edit.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith( {rules: [['neutron', 'update_health_monitor']]}); return allowed; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { $provide.value('$uibModal', { open: function() { return { result: { then: function(func) { func({ data: { id: 'healthmonitor1' } }); } } }; } }); })); beforeEach(inject(function ($injector) { scope = $injector.get('$rootScope').$new(); $q = $injector.get('$q'); policy = $injector.get('horizon.app.core.openstack-service-api.policy'); $route = $injector.get('$route'); service = $injector.get('horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit'); init = service.init; loadBalancerState = $q.defer(); })); it('should define the correct service properties', function() { expect(service.init).toBeDefined(); expect(service.edit).toBeDefined(); }); it('should have the "allowed" and "perform" functions', function() { expect(service.edit.allowed).toBeDefined(); expect(service.edit.perform).toBeDefined(); }); it('should allow edit a health monitor under an ACTIVE load balancer', function() { loadBalancerState.resolve(); init(loadBalancerState.promise); expect(allowed({})).toBe(true); }); it('should not allow editing a health monitor under a NON-ACTIVE load balancer', function() { loadBalancerState.reject(); init(loadBalancerState.promise); expect(allowed({})).toBe(false); }); it('should reload page after edit', function() { loadBalancerState.resolve(); spyOn($route, 'reload'); init(loadBalancerState.promise).edit.allowed({}); service.edit.perform(); expect($route.reload).toHaveBeenCalled(); }); }); })(); ././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/edit/wizard.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000362513245511613034130 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Edit Health Monitor Wizard Controller', function() { var ctrl; var model = { submit: function() { return 'updated'; }, initialize: angular.noop }; var workflow = function() { return 'foo'; }; var scope = { launchContext: {id: 'healthmonitor1'} }; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function ($provide) { $provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model); $provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflow); })); beforeEach(inject(function ($controller) { spyOn(model, 'initialize'); ctrl = $controller('EditHealthMonitorWizardController', { $scope: scope }); })); it('defines the controller', function() { expect(ctrl).toBeDefined(); }); it('calls initialize on the given model', function() { expect(model.initialize).toHaveBeenCalled(); }); it('sets scope.workflow to the given workflow', function() { expect(scope.workflow).toBe('foo'); }); it('defines scope.submit', function() { expect(scope.submit).toBeDefined(); expect(scope.submit()).toBe('updated'); }); }); })(); ././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/edit/edit.action.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000433713245511613034131 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.healthmonitors') .factory('horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit', editService); editService.$inject = [ '$q', '$route', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.i18n.gettext' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.healthmonitors.actions.editService * @description * Provides the service for editing a health monitor resource. * @param $q The angular service for promises. * @param $route The angular $route service. * @param workflowModal The LBaaS workflow modal service. * @param policy The horizon policy service. * @param gettext The horizon gettext function for translation. * @returns The health monitor edit service. */ function editService($q, $route, workflowModal, policy, gettext) { var statePromise; var edit = workflowModal.init({ controller: 'EditHealthMonitorWizardController', message: gettext('The health monitor has been updated.'), handle: handle, allowed: allowed }); var service = { init: init, edit: edit }; return service; ////////////// function init(_statePromise_) { statePromise = _statePromise_; return service; } function allowed(/*healthmonitor*/) { return $q.all([ statePromise, policy.ifAllowed({ rules: [['neutron', 'update_health_monitor']] }) ]); } function handle(/*response*/) { $route.reload(); } } })(); ././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/row-actions.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000357113245511613034130 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Health Monitor Row Actions Service', function() { var actions; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function ($injector) { var rowActionsService = $injector.get( 'horizon.dashboard.project.lbaasv2.healthmonitors.actions.rowActions'); actions = rowActionsService.init('1', '2', '3').actions(); var loadbalancerService = $injector.get( 'horizon.dashboard.project.lbaasv2.loadbalancers.service'); spyOn(loadbalancerService, 'isActionable').and.returnValue(true); })); it('should define correct table row actions', function() { expect(actions.length).toBe(2); expect(actions[0].template.text).toBe('Edit'); expect(actions[1].template.text).toBe('Delete Health Monitor'); }); it('should have the "allowed" and "perform" functions', function() { actions.forEach(function(action) { expect(action.service.allowed).toBeDefined(); expect(action.service.perform).toBeDefined(); }); }); }); })(); ././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/row-actions.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000477713245511613034141 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.healthmonitors') .factory('horizon.dashboard.project.lbaasv2.healthmonitors.actions.rowActions', rowActions); rowActions.$inject = [ 'horizon.framework.util.i18n.gettext', 'horizon.dashboard.project.lbaasv2.loadbalancers.service', 'horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit', 'horizon.dashboard.project.lbaasv2.healthmonitors.actions.delete' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.healthmonitors.actions.rowActions * * @description * Provides the service for the health monitor row actions. * * @param gettext The horizon gettext function for translation. * @param loadBalancersService The LBaaS v2 load balancers service. * @param editService The LBaaS v2 health monitor edit service. * @param deleteService The LBaaS v2 health monitor delete service. * @returns Health monitor row actions service object. */ function rowActions(gettext, loadBalancersService, editService, deleteService) { var loadBalancerIsActionable, loadbalancerId, listenerId, poolId; var service = { actions: actions, init: init }; return service; /////////////// function init(_loadbalancerId_, _listenerId_, _poolId_) { loadbalancerId = _loadbalancerId_; listenerId = _listenerId_; poolId = _poolId_; loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId); return service; } function actions() { return [{ service: editService.init(loadBalancerIsActionable).edit, template: { text: gettext('Edit') } },{ service: deleteService.init(loadbalancerId, listenerId, poolId, loadBalancerIsActionable), template: { text: gettext('Delete Health Monitor'), type: 'delete' } }]; } } })(); ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/create/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000775000175100017510000000000013245512321034113 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/create/wizard.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000277113245511613034131 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.healthmonitors') .controller('CreateHealthMonitorWizardController', CreateHealthMonitorWizardController); CreateHealthMonitorWizardController.$inject = [ '$scope', '$routeParams', 'horizon.dashboard.project.lbaasv2.workflow.model', 'horizon.dashboard.project.lbaasv2.workflow.workflow', 'horizon.framework.util.i18n.gettext' ]; function CreateHealthMonitorWizardController( $scope, $routeParams, model, workflowService, gettext ) { var loadbalancerId = $routeParams.loadbalancerId; var scope = $scope; scope.model = model; scope.submit = scope.model.submit; scope.workflow = workflowService( gettext('Create Health Monitor'), 'fa fa-cloud-download', ['monitor'] ); scope.model.initialize('monitor', false, loadbalancerId, scope.launchContext.id); } })(); ././@LongLink0000000000000000000000000000021600000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/create/create.action.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000541613245511613034130 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.healthmonitors') .factory('horizon.dashboard.project.lbaasv2.healthmonitors.actions.create', createService); createService.$inject = [ '$q', '$location', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.i18n.gettext', 'horizon.framework.util.q.extensions' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.healthmonitors.actions.createService * @description * Provides the service for creating a health monitor resource. * @param $q The angular service for promises. * @param $location The angular $location service. * @param workflowModal The LBaaS workflow modal service. * @param policy The horizon policy service. * @param gettext The horizon gettext function for translation. * @param qExtensions Horizon extensions to the $q service. * @returns The health monitor create service. */ function createService($q, $location, workflowModal, policy, gettext, qExtensions) { var loadbalancerId, listenerId, poolId, statePromise; var create = workflowModal.init({ controller: 'CreateHealthMonitorWizardController', message: gettext('A new health monitor is being created.'), handle: onCreate, allowed: allowed }); var service = { init: init, create: create }; return service; ////////////// function init(_loadbalancerId_, _listenerId_, _statePromise_) { loadbalancerId = _loadbalancerId_; listenerId = _listenerId_; statePromise = _statePromise_; return service; } function allowed(pool) { poolId = pool.id; return $q.all([ statePromise, qExtensions.booleanAsPromise(!pool.healthmonitor_id), policy.ifAllowed({ rules: [['neutron', 'create_health_monitor']] }) ]); } function onCreate(response) { var healthMonitorId = response.data.id; $location.path('project/ngloadbalancersv2/' + loadbalancerId + '/listeners/' + listenerId + '/pools/' + poolId + '/healthmonitors/' + healthMonitorId); } } })(); ././@LongLink0000000000000000000000000000022300000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/create/create.action.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000725113245511613034127 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Create Health Monitor Action Service', function() { var scope, $q, $location, policy, init, service, loadBalancerState; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = service.create.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith( {rules: [['neutron', 'create_health_monitor']]}); return allowed; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { $provide.value('$uibModal', { open: function() { return { result: { then: function(func) { func({ data: { id: 'healthmonitor1' } }); } } }; } }); })); beforeEach(inject(function ($injector) { scope = $injector.get('$rootScope').$new(); $q = $injector.get('$q'); policy = $injector.get('horizon.app.core.openstack-service-api.policy'); $location = $injector.get('$location'); service = $injector.get('horizon.dashboard.project.lbaasv2.healthmonitors.actions.create'); init = service.init; loadBalancerState = $q.defer(); })); it('should define the correct service properties', function() { expect(service.init).toBeDefined(); expect(service.create).toBeDefined(); }); it('should have the "allowed" and "perform" functions', function() { expect(service.create.allowed).toBeDefined(); expect(service.create.perform).toBeDefined(); }); it('should allow creating a health monitor under an ACTIVE load balancer', function() { loadBalancerState.resolve(); init('active', '1', loadBalancerState.promise); expect(allowed({})).toBe(true); }); it('should not allow creating a health monitor under a NON-ACTIVE load balancer', function() { loadBalancerState.reject(); init('non-active', '1', loadBalancerState.promise); expect(allowed({})).toBe(false); }); it('should not allow creating a health monitor if one already exists', function() { loadBalancerState.resolve(); init('active', '1', loadBalancerState.promise); expect(allowed({ healthmonitor_id: '1234' })).toBe(false); }); it('should redirect after create', function() { loadBalancerState.resolve(); spyOn($location, 'path').and.callThrough(); init('loadbalancer1', 'listener1', loadBalancerState.promise).create.allowed({id: 'pool1'}); service.create.perform(); expect($location.path).toHaveBeenCalledWith( 'project/ngloadbalancersv2/loadbalancer1/listeners/listener1/pools/pool1/' + 'healthmonitors/healthmonitor1'); }); }); })(); ././@LongLink0000000000000000000000000000021700000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/create/wizard.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000362013245511613034123 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Create Health Monitor Wizard Controller', function() { var ctrl; var model = { submit: function() { return 'created'; }, initialize: angular.noop }; var workflow = function() { return 'foo'; }; var scope = { launchContext: {id: 'pool1'} }; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function ($provide) { $provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model); $provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflow); })); beforeEach(inject(function ($controller) { spyOn(model, 'initialize'); ctrl = $controller('CreateHealthMonitorWizardController', { $scope: scope }); })); it('defines the controller', function() { expect(ctrl).toBeDefined(); }); it('calls initialize on the given model', function() { expect(model.initialize).toHaveBeenCalled(); }); it('sets scope.workflow to the given workflow', function() { expect(scope.workflow).toBe('foo'); }); it('defines scope.submit', function() { expect(scope.submit).toBeDefined(); expect(scope.submit()).toBe('created'); }); }); })(); ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000775000175100017510000000000013245512321034113 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000022300000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000001261413245511613034126 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Health Monitor Delete Service', function() { var service, policy, modal, lbaasv2Api, $scope, $location, $q, toast, monitor; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(makePromise()); var promise = service.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); $scope.$apply(); expect(policy.ifAllowed) .toHaveBeenCalledWith({rules: [['neutron', 'delete_health_monitor']]}); return allowed; } function makePromise(reject) { var def = $q.defer(); def[reject ? 'reject' : 'resolve'](); return def.promise; } function isActionable(id) { if (id === 'active') { return $q.when(); } else { return $q.reject(); } } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(function() { monitor = { id: '1', name: 'HealthMonitor1' }; }); beforeEach(module(function($provide) { $provide.value('$uibModal', { open: function() { return { result: makePromise() }; } }); $provide.value('horizon.app.core.openstack-service-api.lbaasv2', { deleteHealthMonitor: function() { return makePromise(); } }); $provide.value('$location', { path: function() { return ''; } }); })); beforeEach(inject(function ($injector) { policy = $injector.get('horizon.app.core.openstack-service-api.policy'); lbaasv2Api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); modal = $injector.get('horizon.framework.widgets.modal.deleteModalService'); $scope = $injector.get('$rootScope').$new(); $location = $injector.get('$location'); $q = $injector.get('$q'); toast = $injector.get('horizon.framework.widgets.toast.service'); service = $injector.get('horizon.dashboard.project.lbaasv2.healthmonitors.actions.delete'); service.init('1', '2', '3', isActionable('active')); $scope.$apply(); })); it('should have the "allowed" and "perform" functions', function() { expect(service.allowed).toBeDefined(); expect(service.perform).toBeDefined(); }); it('should allow deleting health monitor from load balancer in ACTIVE state', function() { expect(allowed()).toBe(true); }); it('should not allow deleting health monitor from load balancer in PENDING state', function() { service.init('1', '2', '3', isActionable('pending')); expect(allowed()).toBe(false); }); it('should open the delete modal', function() { spyOn(modal, 'open'); service.perform(monitor); $scope.$apply(); expect(modal.open.calls.count()).toBe(1); var args = modal.open.calls.argsFor(0); expect(args.length).toBe(3); expect(args[0]).toEqual({ $emit: jasmine.any(Function) }); expect(args[1]).toEqual([monitor]); expect(args[2]).toEqual(jasmine.objectContaining({ labels: jasmine.any(Object), deleteEntity: jasmine.any(Function) })); expect(args[2].labels.title).toBe('Confirm Delete Health Monitor'); }); it('should pass function to modal that deletes the health monitor', function() { spyOn(modal, 'open').and.callThrough(); spyOn(lbaasv2Api, 'deleteHealthMonitor').and.callThrough(); service.perform(monitor); $scope.$apply(); expect(lbaasv2Api.deleteHealthMonitor.calls.count()).toBe(1); expect(lbaasv2Api.deleteHealthMonitor).toHaveBeenCalledWith('1', true); }); it('should show message if any items fail to be deleted', function() { spyOn(modal, 'open').and.callThrough(); spyOn(lbaasv2Api, 'deleteHealthMonitor').and.returnValue(makePromise(true)); spyOn(toast, 'add'); service.perform(monitor); $scope.$apply(); expect(modal.open).toHaveBeenCalled(); expect(lbaasv2Api.deleteHealthMonitor.calls.count()).toBe(1); expect(toast.add).toHaveBeenCalledWith('error', 'The following health monitor could not ' + 'be deleted: HealthMonitor1.'); }); it('should return to pool details after delete', function() { var path = 'project/ngloadbalancersv2/1/listeners/2/pools/3'; spyOn($location, 'path'); spyOn(toast, 'add'); service.perform(monitor); $scope.$apply(); expect($location.path).toHaveBeenCalledWith(path); expect(toast.add).toHaveBeenCalledWith('success', 'Deleted health monitor: HealthMonitor1.'); }); }); })(); ././@LongLink0000000000000000000000000000021600000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000731213245511613034125 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.healthmonitors') .factory('horizon.dashboard.project.lbaasv2.healthmonitors.actions.delete', deleteService); deleteService.$inject = [ '$q', '$location', '$route', 'horizon.framework.widgets.modal.deleteModalService', 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.i18n.gettext' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.healthmonitors.actions.deleteService * @description * Brings up the delete health monitor confirmation modal dialog. * On submit, deletes selected health monitor. * On cancel, does nothing. * @param $q The angular service for promises. * @param $location The angular $location service. * @param $route The angular $route service. * @param deleteModal The horizon delete modal service. * @param api The LBaaS v2 API service. * @param policy The horizon policy service. * @param gettext The horizon gettext function for translation. * @returns The health monitor delete service. */ function deleteService( $q, $location, $route, deleteModal, api, policy, gettext ) { var loadbalancerId, listenerId, poolId, statePromise; var context = { labels: { title: gettext('Confirm Delete Health Monitor'), message: gettext('You have selected "%s". Please confirm your selection. Deleted health ' + 'monitors are not recoverable.'), submit: gettext('Delete Health Monitor'), success: gettext('Deleted health monitor: %s.'), error: gettext('The following health monitor could not be deleted: %s.') }, deleteEntity: deleteItem, successEvent: 'success', failedEvent: 'error' }; var service = { perform: perform, allowed: allowed, init: init }; return service; ////////////// function init(_loadbalancerId_, _listenerId_, _poolId_, _statePromise_) { loadbalancerId = _loadbalancerId_; listenerId = _listenerId_; poolId = _poolId_; statePromise = _statePromise_; return service; } function perform(item) { deleteModal.open({ $emit: actionComplete }, [item], context); } function allowed(/*item*/) { return $q.all([ statePromise, // This rule is made up and should therefore always pass. I assume at some point there // will be a valid rule similar to this that we will want to use. policy.ifAllowed({ rules: [['neutron', 'delete_health_monitor']] }) ]); } function deleteItem(id) { return api.deleteHealthMonitor(id, true); } function actionComplete(eventType) { if (eventType === context.failedEvent) { // Error, reload page $route.reload(); } else { // Success, go back to pool details page var path = 'project/ngloadbalancersv2/' + loadbalancerId + '/listeners/' + listenerId + '/pools/' + poolId; $location.path(path); } } } })(); ././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/healthmonitors.module.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000170413245511613034124 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; /** * @ngdoc overview * @ngname horizon.dashboard.project.lbaasv2.healthmonitors * * @description * Provides the services and widgets required to support and display the project healthmonitors * for the load balancers v2 panel. */ angular .module('horizon.dashboard.project.lbaasv2.healthmonitors', []); })(); ././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/healthmonitors.module.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000150213245511613034120 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Healthmonitors Module', function() { it('should exist', function() { expect(angular.module('horizon.dashboard.project.lbaasv2.healthmonitors')).toBeDefined(); }); }); })(); ././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/detail.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000660313245511613034127 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Healthmonitor Detail Controller', function() { var lbaasv2API, $controller, apiFail, qAllFail; function fakePromise(data, reject) { return { then: function(success, fail) { if (reject) { fail(); } else { success({ data: data }); } return fakePromise(); } }; } function fakeAPI() { return fakePromise('foo', apiFail); } function loadbalancerAPI() { return fakePromise({ provisioning_status: 'ACTIVE' }); } function qAll() { return fakePromise(null, qAllFail); } function createController() { return $controller('HealthMonitorDetailController', { $routeParams: { loadbalancerId: 'loadbalancerId', listenerId: 'listenerId', poolId: 'poolId', healthmonitorId: 'healthmonitorId' } }); } /////////////////////// beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { apiFail = false; qAllFail = false; $provide.value('$q', { all: qAll }); })); beforeEach(inject(function($injector) { lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); spyOn(lbaasv2API, 'getHealthMonitor').and.callFake(fakeAPI); spyOn(lbaasv2API, 'getPool').and.callFake(fakeAPI); spyOn(lbaasv2API, 'getListener').and.callFake(fakeAPI); spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI); $controller = $injector.get('$controller'); })); it('should invoke lbaasv2 apis', function() { var ctrl = createController(); expect(lbaasv2API.getHealthMonitor).toHaveBeenCalledWith('healthmonitorId'); expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId'); expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId'); expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId'); expect(ctrl.loadbalancer).toEqual({ provisioning_status: 'ACTIVE' }); expect(ctrl.listener).toBe('foo'); expect(ctrl.pool).toBe('foo'); expect(ctrl.healthmonitor).toBe('foo'); }); it('should throw error on API fail', function() { apiFail = true; var init = function() { createController(); }; expect(init).toThrow(); }); it('should set error state if any APIs fail', function() { qAllFail = true; var ctrl = createController(); expect(ctrl.loading).toBe(false); expect(ctrl.error).toBe(true); }); }); })(); ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/detail.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000464113245511613034127 0ustar zuulzuul00000000000000
Type
{$ ::ctrl.healthmonitor.type $}
Delay
{$ ::ctrl.healthmonitor.delay $}
Max Retries
{$ ::ctrl.healthmonitor.max_retries $}
Timeout
{$ ::ctrl.healthmonitor.timeout $}
HTTP Method
{$ ::ctrl.healthmonitor.http_method $}
Expected Codes
{$ ::ctrl.healthmonitor.expected_codes $}
URL Path
{$ ::ctrl.healthmonitor.url_path $}
Admin State Up
{$ ctrl.healthmonitor.admin_state_up | yesno $}
Monitor ID
{$ ::ctrl.healthmonitor.id $}
Tenant ID
{$ ::ctrl.healthmonitor.tenant_id $}
././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/detail.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitor0000666000175100017510000000565113245511613034131 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.healthmonitors') .controller('HealthMonitorDetailController', HealthMonitorDetailController); HealthMonitorDetailController.$inject = [ 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.dashboard.project.lbaasv2.healthmonitors.actions.rowActions', '$routeParams', '$q' ]; /** * @ngdoc controller * @name HealthMonitorDetailController * * @description * Controller for the LBaaS v2 health monitor detail page. * * @param api The LBaaS v2 API service. * @param rowActions The LBaaS v2 health monitor row actions service. * @param $routeParams The angular $routeParams service. * @param $q The angular service for promises. * @returns undefined */ function HealthMonitorDetailController(api, rowActions, $routeParams, $q) { var ctrl = this; ctrl.loading = true; ctrl.error = false; ctrl.actions = rowActions.init($routeParams.loadbalancerId, $routeParams.listenerId, $routeParams.poolId).actions; init(); //////////////////////////////// function init() { ctrl.healthmonitor = null; ctrl.pool = null; ctrl.listener = null; ctrl.loadbalancer = null; ctrl.loading = true; ctrl.error = false; $q.all([ api.getHealthMonitor($routeParams.healthmonitorId) .then(success('healthmonitor'), fail('healthmonitor')), api.getPool($routeParams.poolId) .then(success('pool'), fail('pool')), api.getListener($routeParams.listenerId) .then(success('listener'), fail('listener')), api.getLoadBalancer($routeParams.loadbalancerId) .then(success('loadbalancer'), fail('loadbalancer')) ]).then(postInit, initError); } function success(property) { return angular.bind(null, function setProp(property, response) { ctrl[property] = response.data; }, property); } function fail(property) { return angular.bind(null, function setProp(property, error) { ctrl[property] = null; throw error; }, property); } function postInit() { ctrl.loading = false; } function initError() { ctrl.loading = false; ctrl.error = true; } } })(); neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/0000775000175100017510000000000013245512321033325 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000775000175100017510000000000013245512321034015 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/batch-actions.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000000653213245511613034032 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Listeners Table Batch Actions Service', function() { var $location, actions, policy, $scope, $q; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { var response = { data: { id: '5678' } }; var modal = { open: function() { return { result: { then: function(func) { func(response); } } }; } }; $provide.value('$uibModal', modal); $provide.value('horizon.dashboard.project.lbaasv2.loadbalancers.service', { isActionable: function() { return $q.when(); } }); $provide.value('horizon.app.core.openstack-service-api.policy', { ifAllowed: function() { return $q.when(); } }); })); beforeEach(inject(function ($injector) { $location = $injector.get('$location'); $scope = $injector.get('$rootScope').$new(); $q = $injector.get('$q'); policy = $injector.get('horizon.app.core.openstack-service-api.policy'); var batchActionsService = $injector.get( 'horizon.dashboard.project.lbaasv2.listeners.actions.batchActions'); actions = batchActionsService.init('1234').actions(); $scope.$apply(); })); it('should define correct table batch actions', function() { expect(actions.length).toBe(2); expect(actions[0].template.text).toBe('Create Listener'); expect(actions[1].template.text).toBe('Delete Listeners'); }); it('should have the "allowed" and "perform" functions', function() { actions.forEach(function(action) { expect(action.service.allowed).toBeDefined(); expect(action.service.perform).toBeDefined(); }); }); it('should check policy to allow creating a listener', function() { spyOn(policy, 'ifAllowed').and.callThrough(); var promise = actions[0].service.allowed(); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); $scope.$apply(); expect(allowed).toBe(true); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'create_listener']]}); }); it('should redirect after create', function() { spyOn($location, 'path').and.callThrough(); actions[0].service.perform(); expect($location.path).toHaveBeenCalledWith('project/ngloadbalancersv2/1234/listeners/5678'); }); }); })(); ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/edit/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000775000175100017510000000000013245512321034015 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/edit/wizard.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000000477013245511613034034 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .controller('EditListenerWizardController', EditListenerWizardController); EditListenerWizardController.$inject = [ '$scope', '$q', 'horizon.dashboard.project.lbaasv2.workflow.model', 'horizon.dashboard.project.lbaasv2.workflow.workflow', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc controller * @name EditListenerWizardController * * @description * Controller for the LBaaS v2 edit listener wizard. * * @param $scope The angular scope object. * @param $q The angular service for promises. * @param model The LBaaS V2 workflow model service. * @param workflowService The LBaaS V2 workflow service. * @param gettext The horizon gettext function for translation. * @returns undefined */ function EditListenerWizardController($scope, $q, model, workflowService, gettext) { var scope = $scope; var defer = $q.defer(); scope.model = model; scope.submit = scope.model.submit; scope.workflow = workflowService( gettext('Update Listener'), 'fa fa-pencil', ['listener'], defer.promise); var allSteps = scope.workflow.allSteps.concat([scope.workflow.certificatesStep]); scope.model.initialize('listener', scope.launchContext.id).then(addSteps).then(ready); function addSteps() { var steps = scope.model.visibleResources; steps.map(getStep).forEach(function addStep(step) { if (!stepExists(step.id)) { scope.workflow.append(step); } }); } function getStep(id) { return allSteps.filter(function findStep(step) { return step.id === id; })[0]; } function stepExists(id) { return scope.workflow.steps.some(function exists(step) { return step.id === id; }); } function ready() { defer.resolve(); } } })(); ././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/edit/wizard.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000000554513245511613034035 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Edit Listener Wizard Controller', function() { var ctrl, workflowSpy, $q, scope; var model = { submit: function() { return 'updated'; }, initialize: function() { var defer = $q.defer(); defer.resolve(); return defer.promise; } }; var workflow = { steps: [{id: 'listener'}], allSteps: [{id: 'listener'}, {id: 'pool'}, {id: 'monitor'}], certificatesStep: {id: 'certificates'}, append: angular.noop }; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function ($provide) { workflowSpy = jasmine.createSpy('workflow').and.returnValue(workflow); $provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model); $provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflowSpy); })); beforeEach(inject(function ($controller, $injector) { $q = $injector.get('$q'); scope = $injector.get('$rootScope').$new(); scope.launchContext = { id: '1234' }; spyOn(model, 'initialize').and.callThrough(); ctrl = $controller('EditListenerWizardController', { $scope: scope }); })); it('defines the controller', function() { expect(ctrl).toBeDefined(); }); it('calls initialize on the given model', function() { expect(model.initialize).toHaveBeenCalledWith('listener', '1234'); }); it('sets scope.workflow to the given workflow', function() { expect(scope.workflow).toBe(workflow); }); it('initializes workflow with correct properties', function() { expect(workflowSpy).toHaveBeenCalledWith('Update Listener', 'fa fa-pencil', ['listener'], jasmine.any(Object)); }); it('defines scope.submit', function() { expect(scope.submit).toBe(model.submit); expect(scope.submit()).toBe('updated'); }); it('adds necessary steps after initializing', function() { model.visibleResources = ['listener', 'pool', 'monitor']; spyOn(workflow, 'append'); scope.$apply(); expect(workflow.append).toHaveBeenCalledWith({id: 'pool'}); expect(workflow.append).toHaveBeenCalledWith({id: 'monitor'}); }); }); })(); ././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/row-actions.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000000721613245511613034032 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Listeners Table Row Actions Service', function() { var scope, $route, $q, actions, policy, init; function canEdit(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = actions[0].service.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_listener']]}); return allowed; } function isActionableMock(id) { if (id === 'active') { return $q.when(); } else { return $q.reject(); } } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { var response = { data: { id: '1' } }; var modal = { open: function() { return { result: { then: function(func) { func(response); } } }; } }; $provide.value('$uibModal', modal); })); beforeEach(inject(function ($injector) { scope = $injector.get('$rootScope').$new(); $q = $injector.get('$q'); $route = $injector.get('$route'); policy = $injector.get('horizon.app.core.openstack-service-api.policy'); var rowActionsService = $injector.get( 'horizon.dashboard.project.lbaasv2.listeners.actions.rowActions'); actions = rowActionsService.actions(); init = rowActionsService.init; var loadbalancerService = $injector.get( 'horizon.dashboard.project.lbaasv2.loadbalancers.service'); spyOn(loadbalancerService, 'isActionable').and.callFake(isActionableMock); })); it('should define correct table row actions', function() { expect(actions.length).toBe(3); expect(actions[0].template.text).toBe('Edit'); expect(actions[1].template.text).toBe('Create Pool'); expect(actions[2].template.text).toBe('Delete Listener'); }); it('should allow editing a listener of an ACTIVE load balancer', function() { init('active'); expect(canEdit({listenerId: '1234'})).toBe(true); }); it('should not allow editing a listener of a non-ACTIVE load balancer', function() { init('non-active'); expect(canEdit({listenerId: '1234'})).toBe(false); }); it('should have the "allowed" and "perform" functions', function() { actions.forEach(function(action) { expect(action.service.allowed).toBeDefined(); expect(action.service.perform).toBeDefined(); }); }); it('should reload table after edit', function() { spyOn($route, 'reload').and.callThrough(); actions[0].service.perform(); expect($route.reload).toHaveBeenCalled(); }); }); })(); ././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/row-actions.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000000644313245511613034033 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.listeners') .factory('horizon.dashboard.project.lbaasv2.listeners.actions.rowActions', tableRowActions); tableRowActions.$inject = [ '$q', '$route', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.i18n.gettext', 'horizon.dashboard.project.lbaasv2.loadbalancers.service', 'horizon.dashboard.project.lbaasv2.listeners.actions.delete', 'horizon.dashboard.project.lbaasv2.pools.actions.create' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.listeners.actions.rowActions * * @description * Provides the service for the Listener table row actions. * * @param $q The angular service for promises. * @param $route The angular $route service. * @param workflowModal The LBaaS workflow modal service. * @param policy The horizon policy service. * @param gettext The horizon gettext function for translation. * @param loadBalancersService The LBaaS v2 load balancers service. * @param deleteService The LBaaS v2 listeners delete service. * @param createPoolService The LBaaS v2 pools create service. * @returns Listeners row actions service object. */ function tableRowActions( $q, $route, workflowModal, policy, gettext, loadBalancersService, deleteService, createPoolService ) { var loadbalancerId, loadBalancerIsActionable; var edit = workflowModal.init({ controller: 'EditListenerWizardController', message: gettext('The listener has been updated.'), handle: onEdit, allowed: canEdit }); var service = { actions: actions, init: init }; return service; /////////////// function init(_loadbalancerId_) { loadbalancerId = _loadbalancerId_; loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId); return service; } function actions() { return [{ service: edit, template: { text: gettext('Edit') } },{ service: createPoolService.init(loadbalancerId, loadBalancerIsActionable).create, template: { text: gettext('Create Pool') } },{ service: deleteService.init(loadbalancerId, loadBalancerIsActionable), template: { text: gettext('Delete Listener'), type: 'delete' } }]; } function canEdit(/*item*/) { return $q.all([ loadBalancerIsActionable, policy.ifAllowed({ rules: [['neutron', 'update_listener']] }) ]); } function onEdit(/*response*/) { $route.reload(); } } })(); ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/batch-actions.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000000623413245511613034031 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.listeners') .factory('horizon.dashboard.project.lbaasv2.listeners.actions.batchActions', tableBatchActions); tableBatchActions.$inject = [ '$q', '$location', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.i18n.gettext', 'horizon.dashboard.project.lbaasv2.loadbalancers.service', 'horizon.dashboard.project.lbaasv2.listeners.actions.delete' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.listeners.actions.batchActions * * @description * Provides the service for the Listeners table batch actions. * * @param $q The angular service for promises. * @param $location The angular $location service. * @param workflowModal The LBaaS workflow modal service. * @param policy The horizon policy service. * @param gettext The horizon gettext function for translation. * @param loadBalancersService The LBaaS v2 load balancers service. * @param deleteService The LBaaS v2 listeners delete service. * @returns Listeners table batch actions service object. */ function tableBatchActions( $q, $location, workflowModal, policy, gettext, loadBalancersService, deleteService ) { var loadBalancerIsActionable, loadBalancerId; var create = workflowModal.init({ controller: 'CreateListenerWizardController', message: gettext('A new listener is being created.'), handle: onCreate, allowed: canCreate }); var service = { actions: actions, init: init }; return service; /////////////// function init(_loadBalancerId_) { loadBalancerId = _loadBalancerId_; loadBalancerIsActionable = loadBalancersService.isActionable(loadBalancerId); return service; } function actions() { return [{ service: create, template: { type: 'create', text: gettext('Create Listener') } },{ service: deleteService.init(loadBalancerId, loadBalancerIsActionable), template: { text: gettext('Delete Listeners'), type: 'delete-selected' } }]; } function canCreate() { return $q.all([ loadBalancerIsActionable, policy.ifAllowed({ rules: [['neutron', 'create_listener']] }) ]); } function onCreate(response) { var id = response.data.id; $location.path('project/ngloadbalancersv2/' + loadBalancerId + '/listeners/' + id); } } })(); ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/create/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000775000175100017510000000000013245512321034015 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/create/wizard.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000000273213245511613034030 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.listeners') .controller('CreateListenerWizardController', CreateListenerWizardController); CreateListenerWizardController.$inject = [ '$scope', '$routeParams', 'horizon.dashboard.project.lbaasv2.workflow.model', 'horizon.dashboard.project.lbaasv2.workflow.workflow', 'horizon.framework.util.i18n.gettext' ]; function CreateListenerWizardController($scope, $routeParams, model, workflowService, gettext) { var loadbalancerId = $routeParams.loadbalancerId; var scope = $scope; scope.model = model; scope.submit = scope.model.submit; scope.workflow = workflowService( gettext('Create Listener'), 'fa fa-cloud-download', ['listener', 'pool', 'members', 'monitor'] ); scope.model.initialize('listener', false, loadbalancerId); } })(); ././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/create/wizard.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000000353513245511613034032 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Create Listener Wizard Controller', function() { var ctrl; var model = { submit: function() { return 'created'; }, initialize: angular.noop }; var workflow = function() { return 'foo'; }; var scope = {}; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function ($provide) { $provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model); $provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflow); })); beforeEach(inject(function ($controller) { spyOn(model, 'initialize'); ctrl = $controller('CreateListenerWizardController', { $scope: scope }); })); it('defines the controller', function() { expect(ctrl).toBeDefined(); }); it('calls initialize on the given model', function() { expect(model.initialize).toHaveBeenCalled(); }); it('sets scope.workflow to the given workflow', function() { expect(scope.workflow).toBe('foo'); }); it('defines scope.submit', function() { expect(scope.submit).toBeDefined(); expect(scope.submit()).toBe('created'); }); }); })(); ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/delete/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000775000175100017510000000000013245512321034015 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021600000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/delete/delete.action.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000001445013245511613034030 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Listeners Delete Service', function() { var service, policy, modal, lbaasv2Api, $scope, $route, $location, $q, toast, items, path; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(makePromise()); var promise = service.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); $scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'delete_listener']]}); return allowed; } function makePromise(reject) { var def = $q.defer(); def[reject ? 'reject' : 'resolve'](); return def.promise; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(function() { items = [{ id: '1', name: 'First' }, { id: '2', name: 'Second' }]; }); beforeEach(module(function($provide) { $provide.value('$uibModal', { open: function() { return { result: makePromise() }; } }); $provide.value('horizon.app.core.openstack-service-api.lbaasv2', { deleteListener: function() { return makePromise(); } }); $provide.value('$location', { path: function() { return path; } }); })); beforeEach(inject(function ($injector) { policy = $injector.get('horizon.app.core.openstack-service-api.policy'); lbaasv2Api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); modal = $injector.get('horizon.framework.widgets.modal.deleteModalService'); $scope = $injector.get('$rootScope').$new(); $route = $injector.get('$route'); $location = $injector.get('$location'); $q = $injector.get('$q'); toast = $injector.get('horizon.framework.widgets.toast.service'); service = $injector.get('horizon.dashboard.project.lbaasv2.listeners.actions.delete'); service.init('1', makePromise()); })); it('should have the "allowed" and "perform" functions', function() { expect(service.allowed).toBeDefined(); expect(service.perform).toBeDefined(); }); it('should check policy to allow deleting a listener (single)', function() { expect(allowed(items[0])).toBe(true); }); it('should check policy to allow deleting a listener (batch)', function() { expect(allowed()).toBe(true); }); it('should not allow deleting a listener from load balancer in a PENDING state', function() { service.init('1', makePromise(true)); expect(allowed()).toBe(false); }); it('should not allow deleting a listener that has a default pool', function() { expect(allowed({default_pool_id: 'pool1'})).toBe(false); }); it('should open the delete modal', function() { spyOn(modal, 'open'); service.perform(items[0]); $scope.$apply(); expect(modal.open.calls.count()).toBe(1); var args = modal.open.calls.argsFor(0); expect(args.length).toBe(3); expect(args[0]).toEqual({ $emit: jasmine.any(Function) }); expect(args[1]).toEqual([jasmine.objectContaining({ id: '1' })]); expect(args[2]).toEqual(jasmine.objectContaining({ labels: jasmine.any(Object), deleteEntity: jasmine.any(Function) })); expect(args[2].labels.title).toBe('Confirm Delete Listeners'); }); it('should pass function to modal that deletes listeners', function() { spyOn(modal, 'open').and.callThrough(); spyOn(lbaasv2Api, 'deleteListener').and.callThrough(); service.perform(items[0]); $scope.$apply(); expect(lbaasv2Api.deleteListener.calls.count()).toBe(1); expect(lbaasv2Api.deleteListener).toHaveBeenCalledWith('1', true); }); it('should show message if any items fail to be deleted', function() { spyOn(modal, 'open').and.callThrough(); spyOn(lbaasv2Api, 'deleteListener').and.returnValue(makePromise(true)); spyOn(toast, 'add'); items.splice(1, 1); service.perform(items); $scope.$apply(); expect(modal.open).toHaveBeenCalled(); expect(lbaasv2Api.deleteListener.calls.count()).toBe(1); expect(toast.add).toHaveBeenCalledWith('error', 'The following listeners could not ' + 'be deleted, possibly due to existing pools: First.'); }); it('should reload table after delete', function() { path = 'project/ngloadbalancersv2/1'; spyOn($route, 'reload'); service.perform(items); $scope.$apply(); expect($route.reload).toHaveBeenCalled(); }); it('should return to table after delete if on detail page', function() { path = 'project/ngloadbalancersv2/1/listeners/2'; spyOn($location, 'path'); spyOn(toast, 'add'); service.perform(items[0]); $scope.$apply(); expect($location.path).toHaveBeenCalledWith('project/ngloadbalancersv2/1'); expect(toast.add).toHaveBeenCalledWith('success', 'Deleted listeners: First.'); }); it('should show message if any selected items do not allow for delete (batch)', function() { spyOn(modal, 'open'); spyOn(toast, 'add'); items[0].default_pool_id = 'pool1'; items[1].default_pool_id = 'pool2'; service.perform(items); $scope.$apply(); expect(modal.open).not.toHaveBeenCalled(); expect(toast.add).toHaveBeenCalledWith('error', 'The following listeners will not be deleted ' + 'due to existing pools: First, Second.'); }); }); })(); ././@LongLink0000000000000000000000000000021100000000000011207 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/delete/delete.action.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/act0000666000175100017510000001175013245511613034030 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.listeners') .factory('horizon.dashboard.project.lbaasv2.listeners.actions.delete', deleteService); deleteService.$inject = [ '$q', '$location', '$route', 'horizon.framework.widgets.modal.deleteModalService', 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.widgets.toast.service', 'horizon.framework.util.q.extensions', 'horizon.framework.util.i18n.gettext' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.listeners.actions.deleteService * @description * Brings up the delete listeners confirmation modal dialog. * On submit, deletes selected listeners. * On cancel, does nothing. * @param $q The angular service for promises. * @param $location The angular $location service. * @param $route The angular $route service. * @param deleteModal The horizon delete modal service. * @param api The LBaaS v2 API service. * @param policy The horizon policy service. * @param toast The horizon message service. * @param qExtensions Horizon extensions to the $q service. * @param gettext The horizon gettext function for translation. * @returns The listeners table delete service. */ function deleteService( $q, $location, $route, deleteModal, api, policy, toast, qExtensions, gettext ) { var loadbalancerId, statePromise; var notAllowedMessage = gettext('The following listeners will not be deleted ' + 'due to existing pools: %s.'); var context = { labels: { title: gettext('Confirm Delete Listeners'), message: gettext('You have selected "%s". Please confirm your selection. Deleted ' + 'listeners are not recoverable.'), submit: gettext('Delete Listeners'), success: gettext('Deleted listeners: %s.'), error: gettext('The following listeners could not be deleted, possibly due to ' + 'existing pools: %s.') }, deleteEntity: deleteItem, successEvent: 'success', failedEvent: 'error' }; var service = { perform: perform, allowed: allowed, init: init }; return service; ////////////// function init(_loadbalancerId_, _statePromise_) { loadbalancerId = _loadbalancerId_; statePromise = _statePromise_; return service; } function perform(items) { if (angular.isArray(items)) { qExtensions.allSettled(items.map(checkPermission)).then(afterCheck); } else { deleteModal.open({ $emit: actionComplete }, [items], context); } } function allowed(item) { var promises = [policy.ifAllowed({ rules: [['neutron', 'delete_listener']] }), statePromise]; if (item) { promises.push(qExtensions.booleanAsPromise(!item.default_pool_id)); } return $q.all(promises); } function deleteItem(id) { return api.deleteListener(id, true); } function actionComplete(eventType) { if (eventType === context.failedEvent) { // Action failed, reload the page $route.reload(); } else { // If the user is on the listeners table then just reload the page, otherwise they // are on the details page and we return to the table. var regex = new RegExp('project\/ngloadbalancersv2\/' + loadbalancerId + '(\/)?$'); if (regex.test($location.path())) { $route.reload(); } else { $location.path('project/ngloadbalancersv2/' + loadbalancerId); } } } function checkPermission(item) { return { promise: canBeDeleted(item), context: item }; } function afterCheck(result) { if (result.fail.length > 0) { toast.add('error', getMessage(notAllowedMessage, result.fail)); } if (result.pass.length > 0) { deleteModal.open({ $emit: actionComplete }, result.pass.map(getEntity), context); } } function canBeDeleted(item) { return qExtensions.booleanAsPromise(!item.default_pool_id); } function getMessage(message, entities) { return interpolate(message, [entities.map(getName).join(", ")]); } function getName(result) { return getEntity(result).name; } function getEntity(result) { return result.context; } } })(); ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/table.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/tab0000666000175100017510000000617713245511613034036 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Listeners Table Controller', function() { var controller, lbaasv2API, rowActions, batchActions; var items = [{ foo: 'bar' }]; var apiFail = false; function fakeAPI() { return { then: function(success, fail) { if (apiFail && fail) { fail(); } else { success({ data: { items: items } }); } } }; } function initMock() { return rowActions; } /////////////////////// beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { $provide.value('$uibModal', {}); })); beforeEach(inject(function($injector) { lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); controller = $injector.get('$controller'); rowActions = $injector.get('horizon.dashboard.project.lbaasv2.listeners.actions.rowActions'); batchActions = $injector.get( 'horizon.dashboard.project.lbaasv2.listeners.actions.batchActions'); spyOn(rowActions, 'init').and.callFake(initMock); spyOn(lbaasv2API, 'getListeners').and.callFake(fakeAPI); })); function createController() { return controller('ListenersTableController', { $routeParams: { loadbalancerId: '1234' } }); } it('should initialize correctly', function() { var ctrl = createController(); expect(ctrl.items).toEqual([]); expect(ctrl.src).toEqual(items); expect(ctrl.loading).toBe(false); expect(ctrl.error).toBe(false); expect(ctrl.checked).toEqual({}); expect(ctrl.loadbalancerId).toEqual('1234'); expect(rowActions.init).toHaveBeenCalledWith(ctrl.loadbalancerId); expect(ctrl.rowActions).toBeDefined(); expect(ctrl.rowActions).toEqual(rowActions); expect(ctrl.batchActions).toBeDefined(); expect(ctrl.batchActions).toEqual(batchActions); }); it('should invoke lbaasv2 apis', function() { var ctrl = createController(); expect(lbaasv2API.getListeners).toHaveBeenCalled(); expect(ctrl.src.length).toBe(1); }); it('should show error if loading fails', function() { apiFail = true; var ctrl = createController(); expect(ctrl.src.length).toBe(0); expect(ctrl.error).toBe(true); }); }); })(); ././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/detail.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/det0000666000175100017510000000576213245511613034043 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Listener Detail Controller', function() { var lbaasv2API, $controller, apiFail, qAllFail; function fakePromise(data, reject) { return { then: function(success, fail) { if (reject) { fail(); } else { success({ data: data }); } return fakePromise(); } }; } function fakeAPI() { return fakePromise('foo', apiFail); } function loadbalancerAPI() { return fakePromise({ provisioning_status: 'ACTIVE' }); } function qAll() { return fakePromise(null, qAllFail); } function createController() { return $controller('ListenerDetailController', { $routeParams: { loadbalancerId: 'loadbalancerId', listenerId: 'listenerId' } }); } /////////////////////// beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { apiFail = false; qAllFail = false; $provide.value('$q', { all: qAll }); $provide.value('$uibModal', {}); })); beforeEach(inject(function($injector) { lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); spyOn(lbaasv2API, 'getListener').and.callFake(fakeAPI); spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI); $controller = $injector.get('$controller'); })); it('should invoke lbaasv2 apis', function() { var ctrl = createController(); expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId'); expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId'); expect(ctrl.loadbalancer).toEqual({ provisioning_status: 'ACTIVE' }); expect(ctrl.listener).toBe('foo'); }); it('should throw error on API fail', function() { apiFail = true; var init = function() { createController(); }; expect(init).toThrow(); }); it('should set error state if any APIs fail', function() { qAllFail = true; var ctrl = createController(); expect(ctrl.loading).toBe(false); expect(ctrl.error).toBe(true); }); }); })(); ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/table.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/tab0000666000175100017510000001005413245511613034023 0ustar zuulzuul00000000000000
Name Description Protocol Port Actions
{$ ::(item.name || item.id) $} {$ ::item.description | noValue $} {$ ::item.protocol$} {$ ::item.protocol_port$}
ID
{$ ::item.id $}
Admin State Up
{$ ::item.admin_state_up | yesno $}
Connection Limit
{$ ::item.connection_limit | limit $}
Default Pool ID
{$ ::item.default_pool_id | noValue $}
././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/detail.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/det0000666000175100017510000000372113245511613034034 0ustar zuulzuul00000000000000
Protocol
{$ ::ctrl.listener.protocol $}
Protocol Port
{$ ::ctrl.listener.protocol_port $}
Connection Limit
{$ ctrl.listener.connection_limit | limit $}
Admin State Up
{$ ctrl.listener.admin_state_up | yesno $}
Default Pool ID
{$ ::ctrl.listener.default_pool_id $} {$ 'None' | translate $}
Listener ID
{$ ::ctrl.listener.id $}
Tenant ID
{$ ::ctrl.listener.tenant_id $}
././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/listeners.module.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/lis0000666000175100017510000000166513245511613034054 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; /** * @ngdoc overview * @ngname horizon.dashboard.project.lbaasv2.listeners * * @description * Provides the services and widgets required to support and display the project listeners * for the load balancers v2 panel. */ angular .module('horizon.dashboard.project.lbaasv2.listeners', []); })(); ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/listeners.module.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/lis0000666000175100017510000000147013245511613034046 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Listeners Module', function() { it('should exist', function() { expect(angular.module('horizon.dashboard.project.lbaasv2.listeners')).toBeDefined(); }); }); })(); ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/detail.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/det0000666000175100017510000000475613245511613034045 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.listeners') .controller('ListenerDetailController', ListenerDetailController); ListenerDetailController.$inject = [ 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.dashboard.project.lbaasv2.listeners.actions.rowActions', '$routeParams', '$q' ]; /** * @ngdoc controller * @name ListenerDetailController * * @description * Controller for the LBaaS v2 listener detail page. * * @param api The LBaaS v2 API service. * @param rowActions The listener row actions service. * @param $routeParams The angular $routeParams service. * @param $q The angular service for promises. * @returns undefined */ function ListenerDetailController(api, rowActions, $routeParams, $q) { var ctrl = this; ctrl.loading = true; ctrl.error = false; ctrl.actions = rowActions.init($routeParams.loadbalancerId).actions; init(); //////////////////////////////// function init() { ctrl.listener = null; ctrl.loadbalancer = null; ctrl.loading = true; ctrl.error = false; $q.all([ api.getListener($routeParams.listenerId) .then(success('listener'), fail('listener')), api.getLoadBalancer($routeParams.loadbalancerId) .then(success('loadbalancer'), fail('loadbalancer')) ]).then(postInit, initError); } function success(property) { return angular.bind(null, function setProp(property, response) { ctrl[property] = response.data; }, property); } function fail(property) { return angular.bind(null, function setProp(property, error) { ctrl[property] = null; throw error; }, property); } function postInit() { ctrl.loading = false; } function initError() { ctrl.loading = false; ctrl.error = true; } } })(); ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/table.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/tab0000666000175100017510000000440613245511613034027 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.listeners') .controller('ListenersTableController', ListenersTableController); ListenersTableController.$inject = [ 'horizon.app.core.openstack-service-api.lbaasv2', '$routeParams', 'horizon.dashboard.project.lbaasv2.listeners.actions.rowActions', 'horizon.dashboard.project.lbaasv2.listeners.actions.batchActions' ]; /** * @ngdoc controller * @name ListenersTableController * * @description * Controller for the LBaaS v2 listeners table. Serves as the focal point for table actions. * * @param api The LBaaS V2 service API. * @param $routeParams The angular $routeParams service. * @param rowActions The listener row actions service. * @param batchActions The listener batch actions service. * @returns undefined */ function ListenersTableController(api, $routeParams, rowActions, batchActions) { var ctrl = this; ctrl.items = []; ctrl.src = []; ctrl.loading = true; ctrl.error = false; ctrl.checked = {}; ctrl.loadbalancerId = $routeParams.loadbalancerId; ctrl.batchActions = batchActions.init(ctrl.loadbalancerId); ctrl.rowActions = rowActions.init(ctrl.loadbalancerId); init(); //////////////////////////////// function init() { ctrl.src = []; ctrl.loading = true; ctrl.error = false; api.getListeners(ctrl.loadbalancerId).then(success, fail); } function success(response) { ctrl.src = response.data.items; ctrl.loading = false; } function fail(/*response*/) { ctrl.src = []; ctrl.loading = false; ctrl.error = true; } } })(); neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/0000775000175100017510000000000013245512321032451 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000775000175100017510000000000013245512321034032 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/edit/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000775000175100017510000000000013245512321034032 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/edit/wizard.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000507113245511613034044 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') .controller('EditPoolWizardController', EditPoolWizardController); EditPoolWizardController.$inject = [ '$scope', '$routeParams', '$q', 'horizon.dashboard.project.lbaasv2.workflow.model', 'horizon.dashboard.project.lbaasv2.workflow.workflow', 'horizon.framework.util.i18n.gettext' ]; /** * @ngdoc controller * @name EditPoolWizardController * * @description * Controller for the LBaaS v2 edit pool wizard. * * @param $scope The angular scope object. * @param $routeParams The angular $routeParams service. * @param $q The angular service for promises. * @param model The LBaaS V2 workflow model service. * @param workflowService The LBaaS V2 workflow service. * @param gettext The horizon gettext function for translation. * @returns undefined */ function EditPoolWizardController($scope, $routeParams, $q, model, workflowService, gettext) { var scope = $scope; var defer = $q.defer(); var loadbalancerId = $routeParams.loadbalancerId; scope.model = model; scope.submit = scope.model.submit; scope.workflow = workflowService( gettext('Update Pool'), 'fa fa-pencil', ['pool'], defer.promise); scope.model.initialize( 'pool', scope.launchContext.id, loadbalancerId).then(addSteps).then(ready); function addSteps() { var steps = scope.model.visibleResources; steps.map(getStep).forEach(function addStep(step) { if (!stepExists(step.id)) { scope.workflow.append(step); } }); } function getStep(id) { return scope.workflow.allSteps.filter(function findStep(step) { return step.id === id; })[0]; } function stepExists(id) { return scope.workflow.steps.some(function exists(step) { return step.id === id; }); } function ready() { defer.resolve(); } } })(); ././@LongLink0000000000000000000000000000020600000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/edit/edit.action.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000626413245511613034051 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Edit Pool Action Service', function() { var scope, $q, $route, policy, init, editPoolService, defer; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = editPoolService.edit.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_pool']]}); return allowed; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { var response = { data: { id: '9012' } }; var modal = { open: function() { return { result: { then: function(func) { func(response); } } }; } }; $provide.value('$uibModal', modal); })); beforeEach(inject(function ($injector) { scope = $injector.get('$rootScope').$new(); $q = $injector.get('$q'); policy = $injector.get('horizon.app.core.openstack-service-api.policy'); $route = $injector.get('$route'); editPoolService = $injector.get( 'horizon.dashboard.project.lbaasv2.pools.actions.edit'); init = editPoolService.init; defer = $q.defer(); })); it('should define the correct service properties', function() { expect(editPoolService.init).toBeDefined(); expect(editPoolService.edit).toBeDefined(); }); it('should have the "allowed" and "perform" functions', function() { expect(editPoolService.edit.allowed).toBeDefined(); expect(editPoolService.edit.perform).toBeDefined(); }); it('should allow editing a pool under an ACTIVE load balancer', function() { defer.resolve(); init(defer.promise); expect(allowed({default_pool_id: '1234'})).toBe(true); }); it('should not allow editing a pool under an NON-ACTIVE load balancer', function() { defer.reject(); init(defer.promise); expect(allowed({default_pool_id: '1234'})).toBe(false); }); it('should redirect after edit', function() { spyOn($route, 'reload').and.callThrough(); editPoolService.edit.perform(); expect($route.reload).toHaveBeenCalled(); }); }); })(); ././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/edit/wizard.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000552213245511613034045 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Edit Pool Wizard Controller', function() { var ctrl, workflowSpy, $q, scope; var model = { submit: function() { return 'updated'; }, initialize: function() { var defer = $q.defer(); defer.resolve(); return defer.promise; } }; var workflow = { steps: [{id: 'pool'}], allSteps: [{id: 'pool'}, {id: 'pool'}, {id: 'monitor'}], certificatesStep: {id: 'certificates'}, append: angular.noop }; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function ($provide) { workflowSpy = jasmine.createSpy('workflow').and.returnValue(workflow); $provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model); $provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflowSpy); })); beforeEach(inject(function ($controller, $injector) { $q = $injector.get('$q'); scope = $injector.get('$rootScope').$new(); scope.launchContext = { id: 'poolId' }; spyOn(model, 'initialize').and.callThrough(); ctrl = $controller('EditPoolWizardController', { $scope: scope, $routeParams: {loadbalancerId: 'loadbalancerId'}}); })); it('defines the controller', function() { expect(ctrl).toBeDefined(); }); it('calls initialize on the given model', function() { expect(model.initialize).toHaveBeenCalledWith('pool', 'poolId', 'loadbalancerId'); }); it('sets scope.workflow to the given workflow', function() { expect(scope.workflow).toBe(workflow); }); it('initializes workflow with correct properties', function() { expect(workflowSpy).toHaveBeenCalledWith('Update Pool', 'fa fa-pencil', ['pool'], jasmine.any(Object)); }); it('defines scope.submit', function() { expect(scope.submit).toBe(model.submit); expect(scope.submit()).toBe('updated'); }); it('adds necessary steps after initializing', function() { model.visibleResources = ['pool', 'monitor']; spyOn(workflow, 'append'); scope.$apply(); expect(workflow.append).toHaveBeenCalledWith({id: 'monitor'}); }); }); })(); ././@LongLink0000000000000000000000000000020100000000000011206 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/edit/edit.action.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000424513245511613034046 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.pools') .factory('horizon.dashboard.project.lbaasv2.pools.actions.edit', editService); editService.$inject = [ '$q', '$route', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.i18n.gettext' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.listeners.actions.editService * @description * Provides the service for editing a pool resource. * @param $q The angular service for promises. * @param $route The angular $route service. * @param workflowModal The LBaaS workflow modal service. * @param policy The horizon policy service. * @param gettext The horizon gettext function for translation. * @returns The load balancers pool edit service. */ function editService( $q, $route, workflowModal, policy, gettext ) { var statePromise; var edit = workflowModal.init({ controller: 'EditPoolWizardController', message: gettext('The pool has been updated.'), handle: onEdit, allowed: allowed }); var service = { init: init, edit: edit }; return service; ////////////// function init(_statePromise_) { statePromise = _statePromise_; return service; } function allowed(/*item*/) { return $q.all([ statePromise, policy.ifAllowed({ rules: [['neutron', 'update_pool']] }) ]); } function onEdit(/*response*/) { $route.reload(); } } })(); ././@LongLink0000000000000000000000000000020100000000000011206 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/row-actions.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000364313245511613034047 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Pools Row Actions Service', function() { var actions; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function ($injector) { var rowActionsService = $injector.get( 'horizon.dashboard.project.lbaasv2.pools.actions.rowActions'); actions = rowActionsService.init('1', '2').actions(); var loadbalancerService = $injector.get( 'horizon.dashboard.project.lbaasv2.loadbalancers.service'); spyOn(loadbalancerService, 'isActionable').and.returnValue(true); })); it('should define correct table row actions', function() { expect(actions.length).toBe(3); expect(actions[0].template.text).toBe('Edit Pool'); expect(actions[1].template.text).toBe('Create Health Monitor'); expect(actions[2].template.text).toBe('Delete Pool'); }); it('should have the "allowed" and "perform" functions', function() { actions.forEach(function(action) { expect(action.service.allowed).toBeDefined(); expect(action.service.perform).toBeDefined(); }); }); }); })(); ././@LongLink0000000000000000000000000000017400000000000011217 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/row-actions.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000531513245511613034045 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.pools') .factory('horizon.dashboard.project.lbaasv2.pools.actions.rowActions', rowActions); rowActions.$inject = [ 'horizon.framework.util.i18n.gettext', 'horizon.dashboard.project.lbaasv2.loadbalancers.service', 'horizon.dashboard.project.lbaasv2.pools.actions.edit', 'horizon.dashboard.project.lbaasv2.pools.actions.delete', 'horizon.dashboard.project.lbaasv2.healthmonitors.actions.create' ]; /** * @ngdoc service * @ngname horizon.dashboard.project.lbaasv2.pools.actions.rowActions * * @description * Provides the service for the pool row actions. * * @param gettext The horizon gettext function for translation. * @param loadBalancersService The LBaaS v2 load balancers service. * @param editService The LBaaS v2 pools delete service. * @param deleteService The LBaaS v2 pools delete service. * @param createService The LBaaS v2 health monitor create service. * @returns Pool row actions service object. */ function rowActions(gettext, loadBalancersService, editService, deleteService, createService) { var loadBalancerIsActionable, loadbalancerId, listenerId; var service = { actions: actions, init: init }; return service; /////////////// function init(_loadbalancerId_, _listenerId_) { loadbalancerId = _loadbalancerId_; listenerId = _listenerId_; loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId); return service; } function actions() { return [{ service: editService.init(loadBalancerIsActionable).edit, template: { text: gettext('Edit Pool') } },{ service: createService.init(loadbalancerId, listenerId, loadBalancerIsActionable).create, template: { text: gettext('Create Health Monitor') } },{ service: deleteService.init(loadbalancerId, listenerId, loadBalancerIsActionable), template: { text: gettext('Delete Pool'), type: 'delete' } }]; } } })(); ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000775000175100017510000000000013245512321034032 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000020100000000000011206 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000271213245511613034043 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.pools') .controller('CreatePoolWizardController', CreatePoolWizardController); CreatePoolWizardController.$inject = [ '$scope', '$routeParams', 'horizon.dashboard.project.lbaasv2.workflow.model', 'horizon.dashboard.project.lbaasv2.workflow.workflow', 'horizon.framework.util.i18n.gettext' ]; function CreatePoolWizardController($scope, $routeParams, model, workflowService, gettext) { var loadbalancerId = $routeParams.loadbalancerId; var scope = $scope; scope.model = model; scope.submit = scope.model.submit; scope.workflow = workflowService( gettext('Create Pool'), 'fa fa-cloud-download', ['pool', 'members', 'monitor'] ); scope.model.initialize('pool', false, loadbalancerId, scope.launchContext.id); } })(); ././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/create.action.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000517113245511613034045 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.pools') .factory('horizon.dashboard.project.lbaasv2.pools.actions.create', createService); createService.$inject = [ '$q', '$location', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.q.extensions', 'horizon.framework.util.i18n.gettext' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.listeners.actions.createService * @description * Provides the service for creating a pool resource. * @param $q The angular service for promises. * @param $location The angular $location service. * @param workflowModal The LBaaS workflow modal service. * @param policy The horizon policy service. * @param qExtensions Horizon extensions to the $q service. * @param gettext The horizon gettext function for translation. * @returns The load balancers pool create service. */ function createService( $q, $location, workflowModal, policy, qExtensions, gettext ) { var loadbalancerId, listenerId, statePromise; var create = workflowModal.init({ controller: 'CreatePoolWizardController', message: gettext('A new pool is being created.'), handle: onCreate, allowed: allowed }); var service = { init: init, create: create }; return service; ////////////// function init(_loadbalancerId_, _statePromise_) { loadbalancerId = _loadbalancerId_; statePromise = _statePromise_; return service; } function allowed(item) { listenerId = item.id; return $q.all([ statePromise, qExtensions.booleanAsPromise(!item.default_pool_id), policy.ifAllowed({ rules: [['neutron', 'create_pool']] }) ]); } function onCreate(response) { var poolId = response.data.id; $location.path('project/ngloadbalancersv2/' + loadbalancerId + '/listeners/' + listenerId + '/pools/' + poolId); } } })(); ././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/create.action.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000716013245511613034045 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Create Pool Action Service', function() { var scope, $q, $location, policy, init, createPoolService, defer; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(true); var promise = createPoolService.create.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'create_pool']]}); return allowed; } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { var response = { data: { id: '9012' } }; var modal = { open: function() { return { result: { then: function(func) { func(response); } } }; } }; $provide.value('$uibModal', modal); })); beforeEach(inject(function ($injector) { scope = $injector.get('$rootScope').$new(); $q = $injector.get('$q'); policy = $injector.get('horizon.app.core.openstack-service-api.policy'); $location = $injector.get('$location'); createPoolService = $injector.get( 'horizon.dashboard.project.lbaasv2.pools.actions.create'); init = createPoolService.init; defer = $q.defer(); })); it('should define the correct service properties', function() { expect(createPoolService.init).toBeDefined(); expect(createPoolService.create).toBeDefined(); }); it('should have the "allowed" and "perform" functions', function() { expect(createPoolService.create.allowed).toBeDefined(); expect(createPoolService.create.perform).toBeDefined(); }); it('should allow creating a pool under an ACTIVE load balancer', function() { defer.resolve(); init('active', defer.promise); expect(allowed({default_pool_id: ''})).toBe(true); }); it('should not allow creating a pool under an NON-ACTIVE load balancer', function() { defer.reject(); init('non-active', defer.promise); expect(allowed({default_pool_id: ''})).toBe(false); }); it('should not allow creating a pool if a listener pool already exists', function() { defer.resolve(); init('active', defer.promise); expect(allowed({default_pool_id: '1234'})).toBe(false); }); it('should redirect after create', function() { defer.resolve(); spyOn($location, 'path').and.callThrough(); init('1234', defer.promise).create.allowed({id: '5678'}); createPoolService.create.perform(); expect($location.path).toHaveBeenCalledWith( 'project/ngloadbalancersv2/1234/listeners/5678/pools/9012'); }); }); })(); ././@LongLink0000000000000000000000000000020600000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000357413245511613034052 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('LBaaS v2 Create Pool Wizard Controller', function() { var ctrl; var model = { submit: function() { return 'created'; }, initialize: angular.noop }; var workflow = function() { return 'foo'; }; var scope = { launchContext: {id: '1234'} }; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function ($provide) { $provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model); $provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflow); })); beforeEach(inject(function ($controller) { spyOn(model, 'initialize'); ctrl = $controller('CreatePoolWizardController', { $scope: scope }); })); it('defines the controller', function() { expect(ctrl).toBeDefined(); }); it('calls initialize on the given model', function() { expect(model.initialize).toHaveBeenCalled(); }); it('sets scope.workflow to the given workflow', function() { expect(scope.workflow).toBe('foo'); }); it('defines scope.submit', function() { expect(scope.submit).toBeDefined(); expect(scope.submit()).toBe('created'); }); }); })(); ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000775000175100017510000000000013245512321034032 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000001224113245511613034041 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Pool Delete Service', function() { var service, policy, modal, lbaasv2Api, $scope, $location, $q, toast, pool; function allowed(item) { spyOn(policy, 'ifAllowed').and.returnValue(makePromise()); var promise = service.allowed(item); var allowed; promise.then(function() { allowed = true; }, function() { allowed = false; }); $scope.$apply(); expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'delete_pool']]}); return allowed; } function makePromise(reject) { var def = $q.defer(); def[reject ? 'reject' : 'resolve'](); return def.promise; } function isActionable(id) { if (id === 'active') { return $q.when(); } else { return $q.reject(); } } beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(function() { pool = { id: '1', name: 'Pool1' }; }); beforeEach(module(function($provide) { $provide.value('$uibModal', { open: function() { return { result: makePromise() }; } }); $provide.value('horizon.app.core.openstack-service-api.lbaasv2', { deletePool: function() { return makePromise(); } }); $provide.value('$location', { path: function() { return ''; } }); })); beforeEach(inject(function ($injector) { policy = $injector.get('horizon.app.core.openstack-service-api.policy'); lbaasv2Api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); modal = $injector.get('horizon.framework.widgets.modal.deleteModalService'); $scope = $injector.get('$rootScope').$new(); $location = $injector.get('$location'); $q = $injector.get('$q'); toast = $injector.get('horizon.framework.widgets.toast.service'); service = $injector.get('horizon.dashboard.project.lbaasv2.pools.actions.delete'); service.init('1', '2', isActionable('active')); $scope.$apply(); })); it('should have the "allowed" and "perform" functions', function() { expect(service.allowed).toBeDefined(); expect(service.perform).toBeDefined(); }); it('should allow deleting pool from load balancer in ACTIVE state', function() { expect(allowed()).toBe(true); }); it('should not allow deleting pool from load balancer in a PENDING state', function() { service.init('1', '2', isActionable('pending')); expect(allowed()).toBe(false); }); it('should open the delete modal', function() { spyOn(modal, 'open'); service.perform(pool); $scope.$apply(); expect(modal.open.calls.count()).toBe(1); var args = modal.open.calls.argsFor(0); expect(args.length).toBe(3); expect(args[0]).toEqual({ $emit: jasmine.any(Function) }); expect(args[1]).toEqual([pool]); expect(args[2]).toEqual(jasmine.objectContaining({ labels: jasmine.any(Object), deleteEntity: jasmine.any(Function) })); expect(args[2].labels.title).toBe('Confirm Delete Pool'); }); it('should pass function to modal that deletes the pool', function() { spyOn(modal, 'open').and.callThrough(); spyOn(lbaasv2Api, 'deletePool').and.callThrough(); service.perform(pool); $scope.$apply(); expect(lbaasv2Api.deletePool.calls.count()).toBe(1); expect(lbaasv2Api.deletePool).toHaveBeenCalledWith('1', true); }); it('should show message if any items fail to be deleted', function() { spyOn(modal, 'open').and.callThrough(); spyOn(lbaasv2Api, 'deletePool').and.returnValue(makePromise(true)); spyOn(toast, 'add'); service.perform(pool); $scope.$apply(); expect(modal.open).toHaveBeenCalled(); expect(lbaasv2Api.deletePool.calls.count()).toBe(1); expect(toast.add).toHaveBeenCalledWith('error', 'The following pool could not ' + 'be deleted: Pool1.'); }); it('should return to listener details after delete', function() { spyOn($location, 'path'); spyOn(toast, 'add'); service.perform(pool); $scope.$apply(); expect($location.path).toHaveBeenCalledWith('project/ngloadbalancersv2/1/listeners/2'); expect(toast.add).toHaveBeenCalledWith('success', 'Deleted pool: Pool1.'); }); }); })(); ././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions0000666000175100017510000000676213245511613034054 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.pools') .factory('horizon.dashboard.project.lbaasv2.pools.actions.delete', deleteService); deleteService.$inject = [ '$q', '$location', '$route', 'horizon.framework.widgets.modal.deleteModalService', 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.app.core.openstack-service-api.policy', 'horizon.framework.util.i18n.gettext' ]; /** * @ngDoc factory * @name horizon.dashboard.project.lbaasv2.pools.actions.deleteService * @description * Brings up the delete pool confirmation modal dialog. * On submit, deletes selected pool. * On cancel, does nothing. * @param $q The angular service for promises. * @param $location The angular $location service. * @param $route The angular $route service. * @param deleteModal The horizon delete modal service. * @param api The LBaaS v2 API service. * @param policy The horizon policy service. * @param gettext The horizon gettext function for translation. * @returns The load balancers table delete service. */ function deleteService($q, $location, $route, deleteModal, api, policy, gettext) { var loadbalancerId, listenerId, statePromise; var context = { labels: { title: gettext('Confirm Delete Pool'), message: gettext('You have selected "%s". Please confirm your selection. Deleted pools ' + 'are not recoverable.'), submit: gettext('Delete Pool'), success: gettext('Deleted pool: %s.'), error: gettext('The following pool could not be deleted: %s.') }, deleteEntity: deleteItem, successEvent: 'success', failedEvent: 'error' }; var service = { perform: perform, allowed: allowed, init: init }; return service; ////////////// function init(_loadbalancerId_, _listenerId_, _statePromise_) { loadbalancerId = _loadbalancerId_; listenerId = _listenerId_; statePromise = _statePromise_; return service; } function perform(item) { deleteModal.open({ $emit: actionComplete }, [item], context); } function allowed(/*item*/) { return $q.all([ statePromise, // This rule is made up and should therefore always pass. I assume at some point there // will be a valid rule similar to this that we will want to use. policy.ifAllowed({ rules: [['neutron', 'delete_pool']] }) ]); } function deleteItem(id) { return api.deletePool(id, true); } function actionComplete(eventType) { if (eventType === context.failedEvent) { // Error, reload page $route.reload(); } else { // Success, go back to listener details page var path = 'project/ngloadbalancersv2/' + loadbalancerId + '/listeners/' + listenerId; $location.path(path); } } } })(); ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/pools.module.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/pools.m0000666000175100017510000000165113245511613033773 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; /** * @ngdoc overview * @ngname horizon.dashboard.project.lbaasv2.pools * * @description * Provides the services and widgets required to support and display the project pools * for the load balancers v2 panel. */ angular .module('horizon.dashboard.project.lbaasv2.pools', []); })(); ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/pools.module.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/pools.m0000666000175100017510000000146013245511613033771 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Pools Module', function() { it('should exist', function() { expect(angular.module('horizon.dashboard.project.lbaasv2.pools')).toBeDefined(); }); }); })(); ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/detail.controller.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/detail.0000666000175100017510000000757213245511613033734 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; describe('LBaaS v2 Pool Detail Controller', function() { var lbaasv2API, $scope, $window, $controller, apiFail, qAllFail; function fakePromise(data, reject) { return { then: function(success, fail) { if (reject) { fail(); } else { success({ data: data }); } return fakePromise(); } }; } function fakeAPI() { return fakePromise('foo', apiFail); } function loadbalancerAPI() { return fakePromise({ provisioning_status: 'ACTIVE' }); } function qAll() { return fakePromise(null, qAllFail); } function createController() { return $controller('PoolDetailController', { $scope: $scope, $window: $window, $routeParams: { loadbalancerId: 'loadbalancerId', listenerId: 'listenerId', poolId: 'poolId' } }); } /////////////////////// beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.app.core.openstack-service-api')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(module(function($provide) { apiFail = false; qAllFail = false; $provide.value('$q', { all: qAll }); })); beforeEach(inject(function($injector) { lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); spyOn(lbaasv2API, 'getPool').and.callFake(fakeAPI); spyOn(lbaasv2API, 'getListener').and.callFake(fakeAPI); spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI); $scope = $injector.get('$rootScope').$new(); $window = {}; $controller = $injector.get('$controller'); })); it('should invoke lbaasv2 apis', function() { var ctrl = createController(); expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId'); expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId'); expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId'); expect(ctrl.loadbalancer).toEqual({provisioning_status: 'ACTIVE'}); expect(ctrl.listener).toBe('foo'); expect(ctrl.pool).toBe('foo'); }); it('should define mapping for the load balancer algorithm', function() { var ctrl = createController(); expect(ctrl.loadBalancerAlgorithm).toBeDefined(); }); it('should save changes to members tab active state', function() { var ctrl = createController(); expect($window.membersTabActive).toBeUndefined(); expect(ctrl.membersTabActive).toBeUndefined(); ctrl.membersTabActive = true; $scope.$apply(); expect($window.membersTabActive).toBe(true); ctrl.membersTabActive = false; $scope.$apply(); expect($window.membersTabActive).toBe(false); }); it('should throw error on API fail', function() { apiFail = true; var init = function() { createController(); }; expect(init).toThrow(); }); it('should set error state if any APIs fail', function() { qAllFail = true; var ctrl = createController(); expect(ctrl.loading).toBe(false); expect(ctrl.error).toBe(true); }); }); })(); ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/detail.htmlneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/detail.0000666000175100017510000000505013245511613033721 0ustar zuulzuul00000000000000
Protocol
{$ ::ctrl.pool.protocol $}
Load Balancer Algorithm
{$ ctrl.pool.lb_algorithm | decode:ctrl.loadBalancerAlgorithm $}
Session Persistence
{$ ctrl.pool.session_persistence | noValue:('None' | translate) $}
Admin State Up
{$ ctrl.pool.admin_state_up | yesno $}
Health Monitor ID
{$ ::ctrl.pool.healthmonitor_id $} {$ 'None' | translate $}
Pool ID
{$ ::ctrl.pool.id $}
Tenant ID
{$ ::ctrl.pool.tenant_id $}
././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/detail.controller.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/detail.0000666000175100017510000000660313245511613033726 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function() { 'use strict'; angular .module('horizon.dashboard.project.lbaasv2.pools') .controller('PoolDetailController', PoolDetailController); PoolDetailController.$inject = [ 'horizon.app.core.openstack-service-api.lbaasv2', 'horizon.dashboard.project.lbaasv2.pools.actions.rowActions', '$routeParams', 'horizon.framework.util.i18n.gettext', '$window', '$scope', '$q' ]; /** * @ngdoc controller * @name PoolDetailController * * @description * Controller for the LBaaS v2 pool detail page. * * @param api The LBaaS v2 API service. * @param rowActions The LBaaS v2 pool row actions service. * @param $routeParams The angular $routeParams service. * @param gettext The horizon gettext function for translation. * @param $window Angular's reference to the browser window object. * @param $scope The angular scope object. * @param $q The angular service for promises. * @returns undefined */ function PoolDetailController(api, rowActions, $routeParams, gettext, $window, $scope, $q) { var ctrl = this; ctrl.loading = true; ctrl.error = false; ctrl.loadBalancerAlgorithm = { ROUND_ROBIN: gettext('Round Robin'), LEAST_CONNECTIONS: gettext('Least Connections'), SOURCE_IP: gettext('Source IP') }; ctrl.actions = rowActions.init($routeParams.loadbalancerId, $routeParams.listenerId).actions; ctrl.membersTabActive = $window.membersTabActive; init(); //////////////////////////////// function init() { ctrl.pool = null; ctrl.listener = null; ctrl.loadbalancer = null; ctrl.loading = true; ctrl.error = false; $q.all([ api.getPool($routeParams.poolId) .then(success('pool'), fail('pool')), api.getListener($routeParams.listenerId) .then(success('listener'), fail('listener')), api.getLoadBalancer($routeParams.loadbalancerId) .then(success('loadbalancer'), fail('loadbalancer')) ]).then(postInit, initError); } function success(property) { return angular.bind(null, function setProp(property, response) { ctrl[property] = response.data; }, property); } function fail(property) { return angular.bind(null, function setProp(property, error) { ctrl[property] = null; throw error; }, property); } function postInit() { ctrl.loading = false; } function initError() { ctrl.loading = false; ctrl.error = true; } // Save the active state of the members tab in the global window object so it can stay // active after reloading the route following an action. $scope.$watch(function() { return ctrl.membersTabActive; }, function(active) { $window.membersTabActive = active; }); } })(); neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/util/0000775000175100017510000000000013245512321032272 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/util/validators/neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/util/validato0000775000175100017510000000000013245512321034016 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/util/validators/validate-unique.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/util/validato0000666000175100017510000000377113245511613034035 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; /** * @ngdoc directive * @name horizon.dashboard.project.lbaasv2:validateUnique * @element ng-model * @description * The `validateUnique` directive provides validation * for form input elements to ensure values are unique. * * Validator returns true if model/view value is not in * the array of values specified. * * @restrict A * * @example * ``` * * ``` */ angular .module('horizon.dashboard.project.lbaasv2') .directive('validateUnique', validateUnique); function validateUnique() { var directive = { require: 'ngModel', restrict: 'A', link: link }; return directive; ////////// function link(scope, element, attrs, ctrl) { ctrl.$parsers.push(uniqueValidator); ctrl.$formatters.push(uniqueValidator); attrs.$observe('validateUnique', function () { uniqueValidator(ctrl.$modelValue); }); function uniqueValidator(value) { var values = scope.$eval(attrs.validateUnique); if (angular.isArray(values) && values.length > 0 && values.indexOf(value) > -1) { ctrl.$setValidity('unique', false); } else { ctrl.$setValidity('unique', true); } // Return the value rather than undefined if invalid return value; } } } })(); ././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/util/validators/validate-unique.spec.jsneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/util/validato0000666000175100017510000000431413245511613034027 0ustar zuulzuul00000000000000/* * Copyright 2016 IBM Corp. * * 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. */ (function () { 'use strict'; describe('validate-unique directive', function () { var $compile, scope, element, port, name; var markup = '
' + '' + '' + '
'; beforeEach(module('horizon.framework.widgets')); beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function ($injector) { $compile = $injector.get('$compile'); scope = $injector.get('$rootScope').$new(); // generate dom from markup element = $compile(markup)(scope); port = element.children('input[type="number"]'); name = element.children('input[type="string"]'); // setup up initial data scope.ports = [80, 443]; scope.names = ['name1', 'name2']; scope.$apply(); })); it('should be initially empty', function () { expect(port.val()).toEqual(''); expect(name.val()).toEqual(''); expect(port.hasClass('ng-valid')).toBe(true); expect(name.hasClass('ng-valid')).toBe(true); }); it('should be invalid if values are not unique', function () { scope.port = 80; scope.name = 'name1'; scope.$apply(); expect(port.hasClass('ng-valid')).toBe(false); expect(name.hasClass('ng-valid')).toBe(false); }); it('should be valid if values are unique', function () { scope.port = 81; scope.name = 'name3'; scope.$apply(); expect(port.hasClass('ng-valid')).toBe(true); expect(name.hasClass('ng-valid')).toBe(true); }); }); })(); neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/post_install.sh0000777000175100017510000000111113245511613026150 0ustar zuulzuul00000000000000#!/bin/bash -x # This script will be executed inside npm postinstall task, see package.json # pull down the test shim from horizon master because it's not # included in the installed horizon packages if [ ! -f test-shim.js ]; then wget -nv -t 3 https://raw.githubusercontent.com/openstack/horizon/master/test-shim.js fi echo "Note: neutron-lbaas-dashboard is now deprecated." echo "Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation" echo "Creating a tox env which will contain xStatic libraries, horizon, and openstack_dashboard" tox -epy27 --notest; neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/__init__.py0000666000175100017510000000121513245511613025214 0ustar zuulzuul00000000000000# 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( 'neutron_lbaas_dashboard').version_string() neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/0000775000175100017510000000000013245512321024336 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ja/0000775000175100017510000000000013245512321024730 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ja/LC_MESSAGES/0000775000175100017510000000000013245512321026515 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ja/LC_MESSAGES/django.po0000666000175100017510000000120213245511613030317 0ustar zuulzuul00000000000000# Yusuke Higashino , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01:36+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-21 01:20+0000\n" "Last-Translator: Yusuke Higashino \n" "Language-Team: Japanese\n" "Language: ja\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=1; plural=0\n" msgid "Load Balancers" msgstr "ロードバランサー" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ja/LC_MESSAGES/djangojs.po0000666000175100017510000004423713245511613030673 0ustar zuulzuul00000000000000# Alex Eng , 2016. #zanata # Yukinori Yagisawa , 2016. #zanata # Yusuke Higashino , 2016. #zanata # 小羽根 陸 , 2016. #zanata # Kyohei Moriyama , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.0.0b4.dev3\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-08-11 03:11+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:42+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 "%(ip)s..." msgstr "%(ip)s..." msgid "" "HTTP method:\n" " The HTTP method used to perform the health check." msgstr "" "HTTP method:\n" "   ヘルスチェックの実行に使用されたHTTPメソッドです。" msgid "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgstr "" "Interval:\n" "ヘルスチェックの間隔はタイムアウト値以上でなければいけません。" msgid "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgstr "" " 取得 :\n" " 接続可能数が失敗するにはメンバーを無効しなければいけません。数は1~10までで" "す。" msgid "" "Subnet:\n" " The network which contains the IP address of the member." msgstr "" "Subnet:\n" "メンバーのIPアドレスを含むネットワーク。" msgid "A new health monitor is being created." msgstr "新しいヘルスモニターが作成されました。" msgid "A new listener is being created." msgstr "新しいリスナーが作成されました。" msgid "A new load balancer is being created." msgstr "新しいロードバランサーが作成されました。" msgid "A new pool is being created." msgstr "新しいプールが作成されました。" msgid "" "A pool represents a group of members over which the load balancing will be " "applied." msgstr "プールは負荷分散が適用されるメンバーのグループを表します。" msgid "Actions" msgstr "アクション" msgid "Active" msgstr "稼働中" msgid "Add" msgstr "追加" msgid "Add external member" msgstr "メンバーの追加" msgid "Add members to the load balancer pool." msgstr "ロードバランサーにメンバーを追加します。" msgid "Add/Remove Pool Members" msgstr "プールメンバーの追加・削除" msgid "Address" msgstr "アドレス" msgid "Admin State Up" msgstr "管理状態有効" msgid "Allocated Members" msgstr "割り当て済みのメンバー" msgid "An error occurred. Please try again later." msgstr "エラーが発生しました。後からもう一度お試しください。" msgid "Associate" msgstr "割り当て" msgid "Associate Floating IP" msgstr "Floating IP の割り当て" msgid "Associate Floating IP Address" msgstr "Floating IP アドレス の割り当て" msgid "Associating floating IP with load balancer." msgstr "ロードバランサーのFloating IP アドレスの割り当て" msgid "Available Instances" msgstr "有効なインスタンス" msgid "Back" msgstr "戻る" msgid "Cancel" msgstr "取り消し" msgid "Certificate Name" msgstr "認証名" msgid "Confirm Delete Health Monitor" msgstr "ヘルスモニターの削除確認" msgid "Confirm Delete Listeners" msgstr "リスナーの削除確認" msgid "Confirm Delete Load Balancers" msgstr "ロードバランサーの削除確認" msgid "Confirm Delete Pool" msgstr "プールの削除確認" msgid "Confirm Disassociate Floating IP Address" msgstr "Floating IP アドレスの割り当てを解除確認" msgid "Connection Limit" msgstr "最大接続数" msgid "Create Health Monitor" msgstr "ヘルスモニター作成" msgid "Create Listener" msgstr "リスナーの作成" msgid "Create Load Balancer" msgstr "ロードバランサーの作成" msgid "Create Pool" msgstr "プールの作成" msgid "Default Pool ID" msgstr "デフォルトプール ID" msgid "Degraded" msgstr "縮退中" msgid "Delay" msgstr "遅延" msgid "Delete Health Monitor" msgstr "ヘルスモニター削除" msgid "Delete Listener" msgstr "リスナーの削除" msgid "Delete Listeners" msgstr "リスナーの削除" msgid "Delete Load Balancer" msgstr "ロードバランサーの削除" msgid "Delete Load Balancers" msgstr "ロードバランサーの削除" msgid "Delete Pool" msgstr "プールの削除" #, python-format msgid "Deleted health monitor: %s." msgstr "ヘルスモニターは削除されました:%s。" #, python-format msgid "Deleted listeners: %s." msgstr "リスナーを削除しました:%s。" #, python-format msgid "Deleted load balancers: %s." msgstr "ロードバランサーが削除されました:%s。" #, python-format msgid "Deleted pool: %s." msgstr "プールを削除しました:%s。" msgid "Description" msgstr "説明" msgid "Disassociate" msgstr "割り当て解除" msgid "Disassociate Floating IP" msgstr "Floating IP の割り当て解除" #, python-format msgid "Disassociated floating IP address from load balancer: %s." msgstr "ロードバランサー:%sからFloating IP アドレスの割り当てを解除しました。" msgid "Edit" msgstr "編集" msgid "Edit Pool" msgstr "プールの編集" msgid "Error" msgstr "エラー" msgid "Expected Codes" msgstr "コードの期待値" msgid "Expected status codes" msgstr "ステータスコードの期待値" msgid "Expiration Date" msgstr "期限切れ日" msgid "Floating IP Address" msgstr "Floating IP アドレス" msgid "" "Floating IP address or pool\n" " " msgstr "" "Floating IP アドレスもしくは、プール " msgid "Floating IP addresses" msgstr "Floating IP アドレス" msgid "Floating IP pools" msgstr "Floating IP プール" msgid "HTTP Method" msgstr "HTTP メソッド" msgid "HTTP method" msgstr "HTTP メソッド" msgid "Health Monitor ID" msgstr "ヘルスモニター ID" msgid "ID" msgstr "ID" msgid "IP Address" msgstr "IP アドレス" #, python-format msgid "IP Addresses (%(count)s)" msgstr "IP アドレス(%(count)s)" msgid "IP address" msgstr "IP アドレス" msgid "Inactive" msgstr "非稼働" msgid "" "Interval (sec)\n" " " msgstr "" "インターバル(秒)\n" " " msgid "Least Connections" msgstr "最小接続数" #, python-format msgid "Listener %(index)s" msgstr "リスナー%(index)s" msgid "Listener 1" msgstr "リスナー1" msgid "Listener Details" msgstr "リスナーの詳細" msgid "Listener ID" msgstr "リスナーID" msgid "Listeners" msgstr "リスナー" #, python-format msgid "Load Balancer %(index)s" msgstr "ロードバランサー%(index)s" msgid "Load Balancer Algorithm" msgstr "ロードバランサーアルゴリズム" msgid "Load Balancer Details" msgstr "ロードバランサーの詳細" msgid "Load Balancer ID" msgstr "ロードバランサーID" msgid "Load Balancers" msgstr "ロードバランサー" msgid "Loading" msgstr "読み込み中" msgid "Max Retries" msgstr "最大試行回数" msgid "Member ID" msgstr "メンバー ID" msgid "Members" msgstr "メンバー" msgid "" "Method\n" " " msgstr "メソッド" msgid "Monitor Details" msgstr "モニターの詳細" msgid "Monitor ID" msgstr "モニター ID" msgid "" "Monitor type\n" " " msgstr "" "モニタータイプ\n" " " msgid "Name" msgstr "名前" msgid "No available certificates" msgstr "有効な認証がありません" msgid "No available instances" msgstr "有効なインスタンスがありません" msgid "No items to display." msgstr "表示する項目がありません" msgid "No members have been allocated" msgstr "メンバーが割り当てられていません。" msgid "None" msgstr "なし" msgid "Offline" msgstr "オフライン" msgid "Online" msgstr "オンライン" msgid "Operating Status" msgstr "作動状態" msgid "Overview" msgstr "概要" msgid "Pending Create" msgstr "作成待ち" msgid "Pending Delete" msgstr "削除待ち" msgid "Pending Update" msgstr "更新待ち" msgid "Pool 1" msgstr "プール1" msgid "Pool Details" msgstr "プールの詳細" msgid "Pool ID" msgstr "プール ID" msgid "Pool Members" msgstr "プールメンバー" msgid "Pool member weight has been updated." msgstr "プールメンバーのウェイトが更新されました。" msgid "Port" msgstr "ポート" msgid "Port ID" msgstr "ポート ID" msgid "Protocol" msgstr "プロトコル" msgid "Protocol Port" msgstr "ポート番号" msgid "Provide the details for the health monitor." msgstr "ヘルスモニターの詳細を設定してください。" msgid "Provide the details for the pool." msgstr "プールの詳細を設定してください" msgid "Provider" msgstr "プロバイダー" msgid "Provisioning Status" msgstr "プロビジョニング状態" msgid "Remove" msgstr "削除" msgid "" "Retries\n" " " msgstr "" "取得\n" " " msgid "Round Robin" msgstr "ラウンドロビン" msgid "SSL Certificates" msgstr "SSL認証" msgid "" "Select a floating IP address to associate with the load balancer or a " "floating IP pool in which to allocate a new floating IP address." msgstr "" "ロードバランサを設定するためにフローティングIPアドレス、もしくは、新しいフ" "ローティングIPアドレス配置するためのフローティングIPアドレスプールを選択して" "ください" msgid "Select certificates from the available certificates below" msgstr "以下の利用可能な認証から、認証を選択してください。" msgid "Select one or more SSL certificates for the listener." msgstr "SSL認証を 1 つ以上選択してください" msgid "Session Persistence" msgstr "セッション永続性" msgid "Source IP" msgstr "送信元 IP" msgid "" "Subnet\n" " " msgstr "サブネット" msgid "Subnet ID" msgstr "サブネット ID" msgid "Tenant ID" msgstr "テナント ID" msgid "The URL path is not valid." msgstr "URLは有効ではありません。" #, python-format msgid "The following health monitor could not be deleted: %s." msgstr "以下のヘルスモニターは削除することができません:%s。" #, python-format msgid "" "The following listeners could not be deleted, possibly due to existing " "pools: %s." msgstr "以下のリスナーはプールがあるため削除することができません:%s。" #, python-format msgid "The following listeners will not be deleted due to existing pools: %s." msgstr "以下のリスナーはプールがあるため削除することができません:%s。" #, python-format msgid "The following load balancers are pending and cannot be deleted: %s." msgstr "以下のロードバランサーは待機状態のため削除することができません:%s" #, python-format msgid "" "The following load balancers could not be deleted, possibly due to existing " "listeners: %s." msgstr "" "以下のロードバランサーはおそらくリスナーがあるため削除することができません:" "%s。" #, python-format msgid "The following pool could not be deleted: %s." msgstr "以下のプールは削除することができません:%s。" msgid "The health check interval must be greater than or equal to the timeout." msgstr "ヘルスチェックの間隔はタイムアウト値以上でなければいけません。" msgid "The health monitor has been updated." msgstr "ヘルスモニターが更新されました。" msgid "The listener has been updated." msgstr "リスナーが更新されました。" msgid "The load balancer has been updated." msgstr "ロードバランサーが更新されました。" msgid "The max retry count must be a number between 1 and 10." msgstr "最大試行回数は1~10までとなっています。" msgid "The pool has been updated." msgstr "プールが更新されました。" msgid "The pool members have been updated." msgstr "プールメンバーが更新されました。" msgid "The port must be a number between 1 and 65535." msgstr "ポートは1~65535までとなっています。" msgid "The timeout must be a number greater than or equal to 0." msgstr "タイムアウトの値 は 0 以上でなければなりません。" msgid "The weight must be a number between 1 and 256." msgstr "ウェイトは1~256までとなっています。" msgid "Timeout" msgstr "タイムアウト" msgid "" "Timeout (sec)\n" " " msgstr "" "タイムアウト(秒)\n" " " msgid "Type" msgstr "種別" msgid "URL Path" msgstr "URL パス" msgid "URL path" msgstr "URL パス" msgid "Unable to create health monitor." msgstr "ヘルスモニターの作成ができません。" msgid "Unable to create listener." msgstr "リスナーの作成ができません。" msgid "Unable to create load balancer." msgstr "ロードバランサーの作成ができません。" msgid "Unable to create pool." msgstr "プールの作成ができません。" msgid "Unable to delete health monitor." msgstr "ヘルスモニターの削除ができません。" msgid "Unable to delete listener." msgstr "リスナーの削除ができません。" msgid "Unable to delete load balancer." msgstr "ロードバランサーの削除ができません。" msgid "Unable to delete pool." msgstr "プールの削除ができません。" #, python-format msgid "Unable to disassociate floating IP address from load balancer: %s." msgstr "" "ロードバランサー:%sからFloating IP アドレスの割り当て解除ができません。" msgid "Unable to retrieve SSL certificates." msgstr "SSL認証の取得ができません。" msgid "Unable to retrieve health monitor." msgstr "ヘルスモニターの取得ができません。" msgid "Unable to retrieve listener." msgstr "リスナーの取得ができません。" msgid "Unable to retrieve listeners." msgstr "リスター一覧の取得ができません。" msgid "Unable to retrieve load balancer status tree." msgstr "ロードバランサのステータスツリーを取得できません" msgid "Unable to retrieve load balancer." msgstr "ロードバランサーの取得ができません。" msgid "Unable to retrieve load balancers." msgstr "ロードバランサー一覧の取得ができません。" msgid "Unable to retrieve member." msgstr "メンバーの取得ができません。" msgid "Unable to retrieve members." msgstr "メンバー一覧の取得ができません。" msgid "Unable to retrieve pool." msgstr "プールの取得できません。" msgid "Unable to retrieve secrets." msgstr "事前共通鍵の取得ができません。" msgid "Unable to update health monitor." msgstr "ヘルスモニターの更新ができません。" msgid "Unable to update listener." msgstr "リスナーの更新ができません。" msgid "Unable to update load balancer." msgstr "ロードバランサーの更新ができません。" msgid "Unable to update member list." msgstr "メンバー一覧の更新ができません。" msgid "Unable to update member." msgstr "メンバーの更新ができません。" msgid "Unable to update pool." msgstr "プールの更新ができません。" msgid "Update" msgstr "更新" msgid "Update Health Monitor" msgstr "ヘルスモニターの更新" msgid "Update Listener" msgstr "リスナーの更新" msgid "Update Load Balancer" msgstr "ロードバランサーの更新" msgid "Update Member Weight" msgstr "メンバーウェイトの更新" msgid "Update Pool" msgstr "プールの更新" msgid "Update Weight" msgstr "ウェイトの更新" msgid "Weight" msgstr "ウェイト" msgid "" "Weight\n" " " msgstr "ウェイト" #, python-format msgid "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." msgstr "" "あなたはロードバランサー\"%s\"からFloating IP アドレスの割り当てを解除しよう" "としています。確認してください。" #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." msgstr "" "\"%s\" を選択しました。選択内容を確認してください。削除されたヘルスモニターは" "元に戻せません。" #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted listeners " "are not recoverable." msgstr "" "\"%s\" を選択しました。選択内容を確認してください。削除されたリスナーは元に戻" "せません。" #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." msgstr "" "\"%s\" を選択しました。選択内容を確認してください。削除されたロードバランサー" "は元に戻せません。" #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." msgstr "" "\"%s\" を選択しました。選択内容を確認してください。削除されたプールは元に戻せ" "ません。" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/zh_CN/0000775000175100017510000000000013245512321025337 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/zh_CN/LC_MESSAGES/0000775000175100017510000000000013245512321027124 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/zh_CN/LC_MESSAGES/django.po0000666000175100017510000000112613245511613030733 0ustar zuulzuul00000000000000# liuyanfu , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01:36+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-21 12:54+0000\n" "Last-Translator: liuyanfu \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 "Load Balancers" msgstr "负载均衡" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/zh_CN/LC_MESSAGES/djangojs.po0000666000175100017510000006273113245511613031301 0ustar zuulzuul00000000000000# BillXiang , 2016. #zanata # Bin , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.0.0b4.dev1\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-08-05 02:17+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-28 02:53+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" #, python-format msgid "%(ip)s..." msgstr "%(ip)s..." msgid "" "Expected status codes:\n" " The expected HTTP status codes to get from a successful health check. Must " "be a single number,\n" " a comma separated list of numbers, or a range (two numbers separated by a " "hyphen)." msgstr "" "期望的状态码:\n" "健康检查成功返回的期望HTTP状态码。\n" "必须为单个数字,逗号分隔的一组数字或一个范围(用连接符分隔的两个数字)。" msgid "" "HTTP method:\n" " The HTTP method used to perform the health check." msgstr "" "HTTP方法:\n" "用来进行健康检查的HTTP请求方式。" msgid "" "IP address:\n" " If an IP address is provided it must be a well-formed IPv4 or IPv6 " "address. The system will\n" " attempt to assign the provided IP address to the load balancer. If an IP " "address is not provided\n" " then one will be allocated for you." msgstr "" "IP地址:\n" "IP地址必须为格式良好的IPv4或IPv6地址。\n" "系统尝试为负载均衡器分配提供的IP地址。\n" "如果没有提供IP地址,则需要你手动分配一个IP。" msgid "" "IP address:\n" " The IP address of the member to receive traffic from the load balancer. " "Must be a well-formed\n" " IPv4 or IPv6 address." msgstr "" "IP地址:\n" "成员的IP地址从负载均衡器中接收消息。\n" "必须使用格式良好的IPv4或IPv6地址。" msgid "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgstr "" "隔离:\n" "健康检查之间相互隔离,必须大于或等于超时时限。" msgid "" "Method:\n" " The load balancer algorithm that distributes traffic to the pool members.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgstr "" "方法:\n" " 资源池成员分布式通信的负载均衡算法\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS:为实例分配请求的最少活动连接次数。\n" " \n" "
  • \n" "
  • \n" " ROUND_ROBIN:多个实例之间的轮询请求。\n" "
  • \n" "
  • \n" " SOURCE_IP:来自唯一源IP地址的请求直接连续的发送到同一实例。\n" "
  • \n" "
" msgid "" "Port:\n" " The port on which the front end listens. Must be an integer from 1 to " "65535." msgstr "" "端口:\n" "监听器之间的端口号。必须为1到65536之间的整数。" msgid "" "Port:\n" " The port on which the member listens for traffic. Must be a number from 1 " "to 65535." msgstr "" "端口:\n" "用来通信的成员监听端口。必须为1到65536之间的整数。" msgid "" "Protocol:\n" " The protocol for which the front end listens. The TERMINATED_HTTPS " "protocol is only available if\n" " the key-manager service is enabled and you have authority to list " "certificate containers and\n" " secrets." msgstr "" "协议:\n" "监听器之间通信的协议。\n" "TERMINATED_HTTPS协议只有在key-manager服务可用\n" "并且你又权限查询证书容器和密钥的情况下才有用。" msgid "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgstr "" "重试:\n" "在将成员标记为未活动状态之前,允许连接失败的次数。\n" "必须为1到10之间的整数。" msgid "" "Subnet:\n" " The network on which to allocate the load balancer's IP address." msgstr "" "子网:\n" "给分配负载均衡器IP地址的网络。" msgid "" "Subnet:\n" " The network which contains the IP address of the member." msgstr "" "子网:\n" "关联成员IP地址的网络。" msgid "" "Timeout:\n" " The time after which a health check times out. Must be a number greater " "than or equal to 0\n" " and less than or equal to the interval." msgstr "" "超时时限:\n" "健康检查请求超时的时间。\n" "必须为大于或等于0的整数,并小于或等于间隔时间。" msgid "" "URL path:\n" " The target of the health check HTTP request to the member. Must be a valid " "URL path." msgstr "" "URL地址:\n" "成员发送健康检查HTTP请求的目标地址,必须为合法的URL路径。" msgid "" "Weight:\n" " The weight of a member determines the portion of requests or connections " "it services compared\n" " to the other members of the pool. A higher weight means it will receive " "more traffic. Must be\n" " a number from 1 to 256." msgstr "" "权重:\n" "成员的权重决定了它在服务中与其他池成员的请求和连接的占比。\n" "权重越高意味着接收的消息越多。\n" "必须为1到256之间的整数。" msgid "A new health monitor is being created." msgstr "一个新的健康监控器正在创建。" msgid "A new listener is being created." msgstr "一个新的监听器正在创建。" msgid "A new load balancer is being created." msgstr "一个新的负载均衡器正在创建。" msgid "A new pool is being created." msgstr "一个新的资源池正在创建。" msgid "" "A pool represents a group of members over which the load balancing will be " "applied." msgstr "资源池代表负载均衡器提供的一组成员。" msgid "Actions" msgstr "行为" msgid "Active" msgstr "运行中" msgid "Add" msgstr "添加" msgid "Add external member" msgstr "添加外部成员" msgid "Add members to the load balancer pool." msgstr "为负载均衡池添加成员。" msgid "Add/Remove Pool Members" msgstr "添加/移除负载均衡池成员" msgid "Address" msgstr "地址" msgid "Admin State Up" msgstr "管理状态:启动" msgid "Allocated Members" msgstr "分配成员" msgid "An error occurred. Please try again later." msgstr "发生错误,请稍后重试。" msgid "Associate" msgstr "关联" msgid "Associate Floating IP" msgstr "关联浮动IP" msgid "Associate Floating IP Address" msgstr "关联浮动IP地址" msgid "Associating floating IP with load balancer." msgstr "为负载均衡器关联浮动IP。" msgid "Available Instances" msgstr "可用实例" msgid "Back" msgstr "后退" msgid "Cancel" msgstr "取消" msgid "Certificate Name" msgstr "证书名称" msgid "Confirm Delete Health Monitor" msgstr "确认删除健康监控器。" msgid "Confirm Delete Listeners" msgstr "确认删除监听器。" msgid "Confirm Delete Load Balancers" msgstr "确认删除负载均衡器" msgid "Confirm Delete Pool" msgstr "确认删除池" msgid "Confirm Disassociate Floating IP Address" msgstr "确认解除关联浮动IP地址。" msgid "Connection Limit" msgstr "连接限制" msgid "Create Health Monitor" msgstr "创建健康监控器。" msgid "Create Listener" msgstr "创建监听器" msgid "Create Load Balancer" msgstr "创建负载均衡器" msgid "Create Pool" msgstr "创建资源池" msgid "Default Pool ID" msgstr "默认资源池ID" msgid "Degraded" msgstr "衰退" msgid "Delay" msgstr "延迟" msgid "Delete Health Monitor" msgstr "删除健康监控" msgid "Delete Listener" msgstr "删除监听器" msgid "Delete Listeners" msgstr "删除监听器" msgid "Delete Load Balancer" msgstr "删除负载均衡器" msgid "Delete Load Balancers" msgstr "删除负载均衡器" msgid "Delete Pool" msgstr "删除资源池" #, python-format msgid "Deleted health monitor: %s." msgstr "删除健康监控器:%s。" #, python-format msgid "Deleted listeners: %s." msgstr "删除监听器:%s。" #, python-format msgid "Deleted load balancers: %s." msgstr "删除负载均衡器:%s。" #, python-format msgid "Deleted pool: %s." msgstr "删除池:%s。" msgid "Description" msgstr "描述" msgid "Disassociate" msgstr "取消关联" msgid "Disassociate Floating IP" msgstr "解除浮动IP关联" #, python-format msgid "Disassociated floating IP address from load balancer: %s." msgstr "从负载均衡器取解除浮动IP关联:%s。" msgid "" "Each port that listens for traffic on a particular load balancer is " "configured separately and\n" " tied to the load balancer. Multiple listeners can be associated with the " "same load balancer but\n" " each must use a unique port." msgstr "" "负载均衡器中的每一个监听的端口独立地配置并与负载均衡器关联。\n" "多个监听器关联到同一个负载均衡器上,\n" "但每个都必须使用唯一的端口。" msgid "Edit" msgstr "编辑" msgid "Edit Pool" msgstr "编辑资源池" msgid "Error" msgstr "错误" msgid "Expected Codes" msgstr "预期的编码" msgid "Expected status codes" msgstr "期望的状态码" msgid "Expiration Date" msgstr "截止日期" msgid "Floating IP Address" msgstr "浮动IP地址" msgid "" "Floating IP address or pool\n" " " msgstr "" "浮动IP地址或浮动IP地址池\n" "" msgid "Floating IP addresses" msgstr "浮动IP地址" msgid "Floating IP pools" msgstr "浮动IP池" msgid "HTTP Method" msgstr "HTTP方法" msgid "HTTP method" msgstr "HTTP方法" msgid "Health Monitor ID" msgstr "健康监听器ID" msgid "ID" msgstr "ID" msgid "IP Address" msgstr "IP地址" msgid "" "IP Address\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " msgstr "" "IP地址\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " #, python-format msgid "IP Addresses (%(count)s)" msgstr "IP地址(%(count)s)" msgid "IP address" msgstr "IP地址" msgid "" "If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL " "certificates must\n" " be selected. The first certificate will be the default." msgstr "" "如果监听器使用TERMINATED_HTTPS协议,则必须选择一个或多个SSL证书。\n" "默认选择第一个。" msgid "Inactive" msgstr "失效" msgid "" "Interval (sec)\n" " " msgstr "" "时间间隔(秒)\n" "" msgid "Least Connections" msgstr "最少连接数" #, python-format msgid "Listener %(index)s" msgstr "监听器%(index)s" msgid "Listener 1" msgstr "监听器1" msgid "Listener Details" msgstr "监听器详情" msgid "Listener ID" msgstr "监听器ID" msgid "Listeners" msgstr "监控器" #, python-format msgid "Load Balancer %(index)s" msgstr "负载均衡器%(index)s" msgid "Load Balancer Algorithm" msgstr "负载均衡器算法" msgid "Load Balancer Details" msgstr "负载均衡器详情" msgid "Load Balancer ID" msgstr "负载均衡器ID" msgid "Load Balancers" msgstr "负载均衡器" msgid "Loading" msgstr "加载中" msgid "Max Retries" msgstr "最大尝试次数" msgid "Member ID" msgstr "成员ID" msgid "Members" msgstr "成员" msgid "" "Members are the actual IP addresses that will receive traffic from the load " "balancer. Each\n" " member must have a unique combination of IP address and port." msgstr "" "成员是在负载均衡器中通信的实际IP地址。\n" "每个成员必须有一个唯一关联的IP地址和端口。" msgid "" "Method\n" " " msgstr "" "方法\n" "" msgid "Monitor Details" msgstr "监控详情" msgid "Monitor ID" msgstr "监控ID" msgid "" "Monitor type\n" " " msgstr "" "健康类型\n" "" msgid "Name" msgstr "名称" msgid "No available certificates" msgstr "无可用证书" msgid "No available instances" msgstr "无可用实例" msgid "No items to display." msgstr "没有要显示的项目。" msgid "No members have been allocated" msgstr "没有成员分配" msgid "None" msgstr "无" msgid "Offline" msgstr "离线" msgid "Online" msgstr "在线" msgid "Operating Status" msgstr "操作状态" msgid "Overview" msgstr "概览" msgid "Pending Create" msgstr "暂挂创建" msgid "Pending Delete" msgstr "暂挂删除" msgid "Pending Update" msgstr "暂挂更新" msgid "Pool 1" msgstr "资源池1" msgid "Pool Details" msgstr "资源池详情" msgid "Pool ID" msgstr "资源池ID" msgid "Pool Members" msgstr "资源池成员" msgid "Pool member weight has been updated." msgstr "负载均衡池成员权重已经更新。" msgid "Port" msgstr "端口" msgid "" "Port\n" " " msgstr "" "端口\n" "" msgid "Port ID" msgstr "端口ID" msgid "Protocol" msgstr "协议" msgid "" "Protocol\n" " " msgstr "" "协议\n" "" msgid "Protocol Port" msgstr "协议端口" msgid "Provide the details for the health monitor." msgstr "为健康监控提供详情。" msgid "Provide the details for the listener." msgstr "为监听器提供详情。" msgid "Provide the details for the load balancer." msgstr "为负载均衡器提供详情。" msgid "Provide the details for the pool." msgstr "为资源池提供详情。" msgid "Provider" msgstr "提供者" msgid "Provisioning Status" msgstr "配置状态" msgid "Remove" msgstr "移除" msgid "" "Retries\n" " " msgstr "" "重试次数\n" "" msgid "Round Robin" msgstr "轮询" msgid "SSL Certificates" msgstr "SSL证书" msgid "" "Select a floating IP address to associate with the load balancer or a " "floating IP pool in which to allocate a new floating IP address." msgstr "" "选择一个浮动IP地址关联一个负载均衡器或为浮动IP池分配一个新的浮动IP地址池。" msgid "Select certificates from the available certificates below" msgstr "从下面可选的证书中选择证书" msgid "Select one or more SSL certificates for the listener." msgstr "为监听器选择一个或多个SSL证书。" msgid "Session Persistence" msgstr "会话持久化" msgid "Source IP" msgstr "源IP" msgid "" "Subnet\n" " " msgstr "" "子网\n" "" msgid "Subnet ID" msgstr "子网ID" msgid "Tenant ID" msgstr "租户ID" msgid "" "The Available Instances table contains existing compute instances that can " "be added as members\n" " of the pool. Use the \"Add external member\" button to add a member not " "found in the Available\n" " Instances table." msgstr "" "可用实例表显示了存在的可以添加为资源池成员的计算实例。\n" "使用“添加外部成员”按钮可以添加在可用实例表中找不到的成员。" msgid "The IP address is not valid." msgstr "IP地址无效。" msgid "The URL path is not valid." msgstr "URL路径无效。" msgid "The expected status code is not valid." msgstr "期望状态码无效。" #, python-format msgid "The following health monitor could not be deleted: %s." msgstr "以下健康监控器无法删除:%s。" #, python-format msgid "" "The following listeners could not be deleted, possibly due to existing " "pools: %s." msgstr "由于存在的资源池,以下的监听器可能无法删除:%s。" #, python-format msgid "The following listeners will not be deleted due to existing pools: %s." msgstr "由于存在资源池,以下的监听器将不能删除:%s。" #, python-format msgid "The following load balancers are pending and cannot be deleted: %s." msgstr "以下的负载均衡器正在挂起不能删除:%s。" #, python-format msgid "" "The following load balancers could not be deleted, possibly due to existing " "listeners: %s." msgstr "因为存在监听器,以下的负载均衡器可能无法删除:%s。" #, python-format msgid "The following pool could not be deleted: %s." msgstr "以下资源池无法删除:%s。" msgid "The health check interval must be greater than or equal to the timeout." msgstr "健康检查间隔必须大于或等于超时时限。" msgid "The health monitor has been updated." msgstr "健康监控器已经更新。" msgid "" "The health monitor is used to determine the health of your pool members. " "Health checks\n" " routinely run against each member within the pool and the result of the " "health check is used\n" " to determine if the member receives new connections. Each pool can only " "have one health\n" " monitor." msgstr "" "健康监控用来确定你的资源池成员的健康状况。\n" "健康检查通常在资源池中与每个成员隔离运行,健康检查的结果通过成员接收到新的连" "接来确定。\n" "每个资源池只能有一个健康监控。" msgid "The listener has been updated." msgstr "监听器已经删除 。" msgid "The load balancer has been updated." msgstr "负载均衡器已经更新。" msgid "" "The load balancer occupies a neutron network port and has an IP address " "assigned from a subnet." msgstr "负载均衡器占用一个neutron网络端口和一个子网分配的IP地址。" msgid "The max retry count must be a number between 1 and 10." msgstr "最大重试次数必须为1到10之间的整数。" msgid "The pool has been updated." msgstr "资源池已经更新。" msgid "The pool members have been updated." msgstr "负载均衡池成员权重已经更新。" msgid "The port must be a number between 1 and 65535." msgstr "端口必须为1到65536之间的整数。" msgid "" "The port must be unique among all listeners attached to this load balancer." msgstr "负载均衡器上的所有监听器之间的端口号必须唯一。" msgid "The timeout must be a number greater than or equal to 0." msgstr "超时时限必须为一个大于等于0的整数。" msgid "The weight must be a number between 1 and 256." msgstr "权重必须为1到256的整数。" msgid "" "The weight of a member determines the portion of requests or connections it " "services compared to the other members of the pool." msgstr "成员的权重决定了它在服务中与其他池成员的请求和连接的占比。" msgid "Timeout" msgstr "超时时限" msgid "" "Timeout (sec)\n" " " msgstr "" "超时时限(秒)\n" "" msgid "Type" msgstr "类型" msgid "URL Path" msgstr "URL路径" msgid "URL path" msgstr "URL路径" msgid "Unable to create health monitor." msgstr "无法创建健康监控。" msgid "Unable to create listener." msgstr "无法创建监听器。" msgid "Unable to create load balancer." msgstr "无法创建负载均衡器。" msgid "Unable to create pool." msgstr "无法创建资源池。" msgid "Unable to delete health monitor." msgstr "无法删除健康监控。" msgid "Unable to delete listener." msgstr "无法删除监听器。" msgid "Unable to delete load balancer." msgstr "无法删除负载均衡器。" msgid "Unable to delete pool." msgstr "无法删除资源池。" #, python-format msgid "Unable to disassociate floating IP address from load balancer: %s." msgstr "无法从负载均衡器解除浮动IP地址关联:%s。" msgid "Unable to retrieve SSL certificates." msgstr "不能获取SSL证书。" msgid "Unable to retrieve health monitor." msgstr "无法获取健康监控。" msgid "Unable to retrieve listener." msgstr "无法检索监听器。" msgid "Unable to retrieve listeners." msgstr "无法检索监听器。" msgid "Unable to retrieve load balancer status tree." msgstr "无法检索负载均衡状态树。" msgid "Unable to retrieve load balancer." msgstr "无法检索负载均衡器。" msgid "Unable to retrieve load balancers." msgstr "无法检索负载均衡器。" msgid "Unable to retrieve member." msgstr "无法检索成员。" msgid "Unable to retrieve members." msgstr "无法检索成员。" msgid "Unable to retrieve pool." msgstr "无法检索资源池。" msgid "Unable to retrieve secrets." msgstr "无法获取密匙。" msgid "Unable to update health monitor." msgstr "无法更新健康监控。" msgid "Unable to update listener." msgstr "无法更新监听器。" msgid "Unable to update load balancer." msgstr "无法更新负载均衡器。" msgid "Unable to update member list." msgstr "无法更新成员列表。" msgid "Unable to update member." msgstr "无法更新成员。" msgid "Unable to update pool." msgstr "无法更新资源池。" msgid "Update" msgstr "更新" msgid "Update Health Monitor" msgstr "更新健康监控器。" msgid "Update Listener" msgstr "更新监听器" msgid "Update Load Balancer" msgstr "更新负载均衡器" msgid "Update Member Weight" msgstr "更新成员权重" msgid "Update Pool" msgstr "更新资源池" msgid "Update Weight" msgstr "更新权重" msgid "" "Use the key-manager service to create any certificate containers before " "creating the listener.\n" " The following documentation provides information on how to create a " "certificate container:\n" " " msgstr "" "创建监听器前,使用key-manager服务创建所有证书容器。\n" "下面的文档介绍了如何创建一个证书容器:\n" "" msgid "Weight" msgstr "权重" msgid "" "Weight\n" " " msgstr "" "权重\n" "" #, python-format msgid "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." msgstr "你将从负载均衡器解除浮动IP地址关联“%s”,请确认。" #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." msgstr "你选择了“%s”。请确认你的选择,删除健康监控器无法恢复。" #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted listeners " "are not recoverable." msgstr "你选择了“%s”。请确认你的选择,删除监听器无法恢复。" #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." msgstr "你选择了“%s”。请确认你的选择,删除的负载均衡无法恢复。" #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." msgstr "你选择了“%s”。请确认你的选择,删除的池无法恢复。" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ko_KR/0000775000175100017510000000000013245512321025343 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ko_KR/LC_MESSAGES/0000775000175100017510000000000013245512321027130 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ko_KR/LC_MESSAGES/django.po0000666000175100017510000000116313245511613030740 0ustar zuulzuul00000000000000# Eunseop Shin , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01:36+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-20 11:32+0000\n" "Last-Translator: Eunseop 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 "Load Balancers" msgstr "로드 밸런서" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ko_KR/LC_MESSAGES/djangojs.po0000666000175100017510000007140113245511613031277 0ustar zuulzuul00000000000000# ByungYeol Woo , 2017. #zanata # Eunseop Shin , 2017. #zanata # Hyeunjee Kim , 2017. #zanata # Sungjin Kang , 2017. #zanata # minwook-shin , 2017. #zanata # youngwoo Kim , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 4.0.0.0b3.dev3\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-12-15 19:47+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-12-15 09:11+0000\n" "Last-Translator: ByungYeol Woo \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 "%(ip)s..." msgstr "%(ip)s..." msgid "" "Expected status codes:\n" " The expected HTTP status codes to get from a successful health check. Must " "be a single number,\n" " a comma separated list of numbers, or a range (two numbers separated by a " "hyphen)." msgstr "" "예상 상태 코드:\n" " 상태 체크가 성공했을 때 수신하게 되는 HTTP 상태 코드입니다. 단일 숫자이어" "야 하고,\n" " 쉼표로 구분된 숫자 리스트이거나 두 개의 숫자가 하이픈으로 구별된 범주이어" "야 합니다." msgid "" "HTTP method:\n" " The HTTP method used to perform the health check." msgstr "" "HTTP 메소드:\n" " 상태 체크를 수행하기 위한 HTTP 메소드." msgid "" "IP address:\n" " If an IP address is provided it must be a well-formed IPv4 or IPv6 " "address. The system will\n" " attempt to assign the provided IP address to the load balancer. If an IP " "address is not provided\n" " then one will be allocated for you." msgstr "" " IP 주소: \n" "   IP 주소가 제공된 경우 올바른 형식의 IPv4 또는 IPv6 주소여야합니다. 시스템" "은\n" "   제공된 IP 주소를 로드 밸런서에 할당하려고 시도합니다. IP 주소가 제공되지 " "않은 경우\n" "   하나가 할당될 것입니다." msgid "" "IP address:\n" " The IP address of the member to receive traffic from the load balancer. " "Must be a well-formed\n" " IPv4 or IPv6 address." msgstr "" "IP 주소:\n" " 로드 밸런서에서 트래픽을 받는 멤버의 IP 주소입니다. 양식에 맞는 \n" " IPv4나 IPv6 주소이어야 합니다." msgid "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgstr "" "간격:\n" " 상태 체크 사이의 간격. 타임아웃 이상이어야 합니다." msgid "" "Method:\n" " The load balancer algorithm that distributes traffic to the pool members.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgstr "" "방법:\n" " 풀 구성원에게 트래픽을 분산시키는 로드 밸런서 알고리즘.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS : 가장 적은 수의 활성 연결을 가진 인스턴스에 요청을 " "할당합니다.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: 여러 인스턴스간에 요청을 균등하게 회전합니다.\n" "
  • \n" "
  • \n" " SOURCE_IP: 고유 한 소스 IP 주소의 요청은 일관되게 동일한 인스턴스로 전" "달됩니다.\n" "
  • \n" "
" msgid "" "Port:\n" " The port on which the front end listens. Must be an integer from 1 to " "65535." msgstr "" "포트:\n" " 프런트 엔드에서 listen하는 포트. 1에서 65535 사이의 정수여야 합니다." msgid "" "Port:\n" " The port on which the member listens for traffic. Must be a number from 1 " "to 65535." msgstr "" "포트:\n" " 트래픽을 수신하는 멤버의 포트 번호입니다. 포트 번호는 1 ~ 65535 사이 숫자이" "어야 합니다." msgid "" "Protocol:\n" " The protocol for which the front end listens. The TERMINATED_HTTPS " "protocol is only available if\n" " the key-manager service is enabled and you have authority to list " "certificate containers and\n" " secrets." msgstr "" "프로토콜:\n" " 프런트 엔드에서 수신하는 프로토콜. TERMINATED_HTTPS 프로토콜은\n" " key-manager 서비스가 활성화되고 인증서 컨테이너와 비밀값을 리스트할 수 있" "는 \n" " 권한이 있어야 이용이 가능합니다." msgid "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgstr "" "재시도: \n" " 재시도 횟수를 초과하여 연결이 실패하면 멤버는 비활성화 되고, 재시도 횟수" "는\n" " 1에서 10까지의 숫자이어야 합니다." msgid "" "Subnet:\n" " The network on which to allocate the load balancer's IP address." msgstr "" "서브넷:\n" " 로드 밸런서의 IP 주소를 할당하는 네트워크" msgid "" "Subnet:\n" " The network which contains the IP address of the member." msgstr "" "서브넷:\n" " 멤버의 IP 주소를 포함하고 있는 네트워크입니다." msgid "" "Timeout:\n" " The time after which a health check times out. Must be a number greater " "than or equal to 0\n" " and less than or equal to the interval." msgstr "" "타임아웃:\n" " 상태 체크 시간이 종료되는 시간. 0 이상의 숫자이어야 하고\n" " 타임아웃 값은 상태 체크 간격 이하이어야 합니다." msgid "" "URL path:\n" " The target of the health check HTTP request to the member. Must be a valid " "URL path." msgstr "" "URL 경로:\n" " 상태 체크하기 위해 멤버에게 HTTP 요청하는 대상. 유효한 URL 경로이어야 합니" "다." msgid "" "Weight:\n" " The weight of a member determines the portion of requests or connections " "it services compared\n" " to the other members of the pool. A higher weight means it will receive " "more traffic. Must be\n" " a number from 1 to 256." msgstr "" "가중치:\n" " 멤버의 가중치는 풀의 다른 멤버와 비교하여 요청이나 연결의\n" " 양을 결정합니다. 가중치가 높을수록 더 많은 트래픽을 받게 됩니다.\n" " 가중치는 숫자 1과 256사이여야 합니다." msgid "A new health monitor is being created." msgstr "새로운 상태 모니터를 생성하고 있습니다." msgid "A new listener is being created." msgstr "새로운 리스너가 생성되고 있습니다." msgid "A new load balancer is being created." msgstr "새 로드 밸런서가 생성되고 있습니다." msgid "A new pool is being created." msgstr "새로운 풀이 생성되고 있습니다." msgid "" "A pool represents a group of members over which the load balancing will be " "applied." msgstr "풀은 로드 밸런싱이 적용될 멤버들의 그룹을 나타냅니다." msgid "Actions" msgstr "작업" msgid "Active" msgstr "활성" msgid "Add" msgstr "추가" msgid "Add external member" msgstr "외부 멤버 추가" msgid "Add members to the load balancer pool." msgstr "로드 밸런서 풀에 멤버를 추가합니다." msgid "Add/Remove Pool Members" msgstr "풀 맴버 추가/삭제" msgid "Address" msgstr "주소" msgid "Admin State Up" msgstr "관리 업 상태" msgid "Allocated Members" msgstr "할당된 멤버" msgid "An error occurred. Please try again later." msgstr "오류가 발생했습니다. 나중에 다시 시도하십시오." msgid "Associate" msgstr "연결" msgid "Associate Floating IP" msgstr "유동 IP 연결" msgid "Associate Floating IP Address" msgstr "유동 IP 주소와 연결" msgid "Associating floating IP with load balancer." msgstr "유동 IP와 로드 밸런서 연결" msgid "Available Instances" msgstr "가용 인스턴스" msgid "Back" msgstr "뒤로" msgid "Cancel" msgstr "취소" msgid "Certificate Name" msgstr "인증서 이름" msgid "Confirm Delete Health Monitor" msgstr "상태 모니터 삭제 확인" msgid "Confirm Delete Listeners" msgstr "리스너 삭제 확인" msgid "Confirm Delete Load Balancers" msgstr "로드 밸런서 삭제 확인" msgid "Confirm Delete Pool" msgstr "풀 삭제 확인" msgid "Confirm Disassociate Floating IP Address" msgstr "유동 IP 주소 연결 해제 확인" msgid "Connection Limit" msgstr "연결 제한" msgid "Create Health Monitor" msgstr "상태 모니터 생성" msgid "Create Listener" msgstr "리스너 생성" msgid "Create Load Balancer" msgstr "로드 밸런서 생성" msgid "Create Pool" msgstr "풀 생성" msgid "Default Pool ID" msgstr "기본 풀 ID" msgid "Degraded" msgstr "기능이 만료됨" msgid "Delay" msgstr "지연" msgid "Delete Health Monitor" msgstr "상태 모니터 삭제" msgid "Delete Listener" msgstr "리스너 삭제" msgid "Delete Listeners" msgstr "리스너 삭제" msgid "Delete Load Balancer" msgstr "로드 밸런서 삭제" msgid "Delete Load Balancers" msgstr "로드 밸런서 삭제" msgid "Delete Pool" msgstr "풀 삭제" #, python-format msgid "Deleted health monitor: %s." msgstr "상태 모니터 %s를 삭제하였습니다." #, python-format msgid "Deleted listeners: %s." msgstr "삭제된 리스너 : %s." #, python-format msgid "Deleted load balancers: %s." msgstr "삭제된 로드 밸런서: %s." #, python-format msgid "Deleted pool: %s." msgstr "삭제된 풀: %s." msgid "Description" msgstr "설명" msgid "Disassociate" msgstr "연결 해제" msgid "Disassociate Floating IP" msgstr "유동 IP 연결 해제" #, python-format msgid "Disassociated floating IP address from load balancer: %s." msgstr "다음 로드 밸런서에서 유동 IP 주소가 연결 해제됨: %s." msgid "" "Each port that listens for traffic on a particular load balancer is " "configured separately and\n" " tied to the load balancer. Multiple listeners can be associated with the " "same load balancer but\n" " each must use a unique port." msgstr "" "특정 로드 밸런서에서 발생하는 트래픽을 위한 리스너의 각 포트는 별도로 설정되" "어야 하고\n" " 로드 밸런서에 연결되어야 합니다. 여러 리스너는 같은 로드 밸런서에 연결되 " "수 있지만\n" " 각각 유일한 포트를 사용해야 합니다." msgid "Edit" msgstr "편집" msgid "Edit Pool" msgstr "풀 편집" msgid "Error" msgstr "오류" msgid "Expected Codes" msgstr "예상 코드" msgid "Expected status codes" msgstr "예상 상태 코드" msgid "Expiration Date" msgstr "만료 날짜" msgid "Floating IP Address" msgstr "유동 IP 주소" msgid "" "Floating IP address or pool\n" " " msgstr "" "유동 IP 주소 또는 풀\n" " " msgid "Floating IP addresses" msgstr "유동 IP 주소" msgid "Floating IP pools" msgstr "유동 IP 풀" msgid "HTTP Method" msgstr "HTTP 메서드" msgid "HTTP method" msgstr "HTTP 메서드" msgid "Health Monitor ID" msgstr "상태 모니터 ID" msgid "ID" msgstr "ID" msgid "IP Address" msgstr "IP 주소" msgid "" "IP Address\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " msgstr "" "IP 주소\n" " 0\">\n" " \n" " \n" " 서브넷\n" " 0\">\n" " \n" " \n" " 포트\n" " 0\">\n" " \n" " 가중치\n" " " #, python-format msgid "IP Addresses (%(count)s)" msgstr "IP 주소 (%(count)s)" msgid "IP address" msgstr "IP 주소" msgid "" "If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL " "certificates must\n" " be selected. The first certificate will be the default." msgstr "" "리스너가 TERMINATED_HTTPS 프로토콜을 이용하고 있다면, 하나 이상의 SSL 인증서" "를 선택하십시오. 첫번째 인증서는 default 인증서가 됩니다." msgid "Inactive" msgstr "비활성" msgid "" "Interval (sec)\n" " " msgstr "" "간격 (초)\n" " " msgid "Least Connections" msgstr "최소 연결" #, python-format msgid "Listener %(index)s" msgstr "Listener %(index)s" msgid "Listener 1" msgstr "Listener 1" msgid "Listener Details" msgstr "리스너 세부정보" msgid "Listener ID" msgstr "리스너 ID" msgid "Listeners" msgstr "리스너" #, python-format msgid "Load Balancer %(index)s" msgstr "Load Balancer %(index)s" msgid "Load Balancer Algorithm" msgstr "로드 밸런서 알고리즘" msgid "Load Balancer Details" msgstr "로드 밸런서 세부정보" msgid "Load Balancer ID" msgstr "로드 밸런서 ID" msgid "Load Balancers" msgstr "로드 밸런서" msgid "Loading" msgstr "불러오는 중" msgid "Max Retries" msgstr "최대 재시도" msgid "Member ID" msgstr "맴버 ID" msgid "Members" msgstr "맴버" msgid "" "Members are the actual IP addresses that will receive traffic from the load " "balancer. Each\n" " member must have a unique combination of IP address and port." msgstr "" "멤버는 로드 밸런서에서 트래픽을 받게 되는 실제 IP 주소입니다.\n" " 각 멤버는 유일한 IP 주소와 포트의 조합을 가지고 있어야 합니다." msgid "" "Method\n" " " msgstr "" "메소드\n" " " msgid "Monitor Details" msgstr "모니터 세부정보" msgid "Monitor ID" msgstr "모니터 ID" msgid "" "Monitor type\n" " " msgstr "" "모니터 타입\n" " " msgid "Name" msgstr "이름" msgid "No available certificates" msgstr "이용 가능한 인증서 없음" msgid "No available instances" msgstr "가용 인스턴스가 없음" msgid "No items to display." msgstr "표시할 항목이 없습니다." msgid "No members have been allocated" msgstr "할당된 멤버가 없음." msgid "None" msgstr "없음" msgid "Offline" msgstr "오프라인" msgid "Online" msgstr "온라인" msgid "Operating Status" msgstr "운영 상태" msgid "Overview" msgstr "개요" msgid "Pending Create" msgstr "생성 대기중" msgid "Pending Delete" msgstr "삭제 대기중" msgid "Pending Update" msgstr "업데이트 대기중" msgid "Pool 1" msgstr "Pool 1" msgid "Pool Details" msgstr "풀 세부정보" msgid "Pool ID" msgstr "풀 ID" msgid "Pool Members" msgstr "풀 맴버" msgid "Pool member weight has been updated." msgstr "풀 멤버의 가중치가 업데이트 되었습니다." msgid "Port" msgstr "포트" msgid "" "Port\n" " " msgstr "" "포트\n" " " msgid "Port ID" msgstr "포트 ID" msgid "Protocol" msgstr "프로토콜" msgid "" "Protocol\n" " " msgstr "" "프로토콜\n" " " msgid "Protocol Port" msgstr "프로토콜 포트" msgid "Provide the details for the health monitor." msgstr "상태 모니터의 세부 사항을 제공하십시오." msgid "Provide the details for the listener." msgstr "리스너에 대한 자세한 정보를 제공하십시오." msgid "Provide the details for the load balancer." msgstr "로드 밸런서에 대한 자세한 정보를 제공하십시오." msgid "Provide the details for the pool." msgstr "풀에 대한 자세한 정보를 작성하십시오." msgid "Provider" msgstr "프로바이더" msgid "Provisioning Status" msgstr "프로비저닝 상태" msgid "Remove" msgstr "제거" msgid "" "Retries\n" " " msgstr "" "재시도\n" " " msgid "Round Robin" msgstr "라운드 로빈" msgid "SSL Certificates" msgstr "SSL 인증서" msgid "" "Select a floating IP address to associate with the load balancer or a " "floating IP pool in which to allocate a new floating IP address." msgstr "" "로드 밸런서와 연결할 유동 IP 주소 또는 새로운 유동 IP 주소를 할당하기 위한 유" "동 IP 풀을 선택하세요." msgid "Select certificates from the available certificates below" msgstr "아래의 이용가능한 인증서 중에서 선택" msgid "Select one or more SSL certificates for the listener." msgstr "Listener 에 대한 하나 이상의 SSL 인증서를 선택하십시오." msgid "Session Persistence" msgstr "세션 지속성" msgid "Source IP" msgstr "소스 IP" msgid "" "Subnet\n" " " msgstr "" "서브넷\n" " " msgid "Subnet ID" msgstr "서브넷 ID" msgid "Tenant ID" msgstr "테넌트 ID" msgid "" "The Available Instances table contains existing compute instances that can " "be added as members\n" " of the pool. Use the \"Add external member\" button to add a member not " "found in the Available\n" " Instances table." msgstr "" "사용 가능한 인스턴스 테이블에는 풀의 멤버로 추가 할 수 있는 기존의 \n" " 컴퓨트 인스턴스가 포함되어 있습니다. \"외부 멤버 추가\" 버튼을 사용하여 \n" " 사용 가능한 인스턴스 테이블에 없는 멤버를 추가하십시오." msgid "The IP address is not valid." msgstr "올바른 IP 주소가 아닙니다." msgid "The URL path is not valid." msgstr "URL 경로가 올바르지 않습니다." msgid "The expected status code is not valid." msgstr "status code가 올바르지 않습니다." #, python-format msgid "The following health monitor could not be deleted: %s." msgstr "상태 모니터 %s는 삭제할 수 없습니다." #, python-format msgid "" "The following listeners could not be deleted, possibly due to existing " "pools: %s." msgstr "리스너 %s는 존재하는 풀 때문에 삭제할 수 없습니다." #, python-format msgid "The following listeners will not be deleted due to existing pools: %s." msgstr "다음 리스너는 기존 풀 때문세 삭제되지 않을 것입니다: %s." #, python-format msgid "The following load balancers are pending and cannot be deleted: %s." msgstr "다음 로드 밸런싱는 보류 중이며 삭제할 수 없습니다: %s." #, python-format msgid "" "The following load balancers could not be deleted, possibly due to existing " "listeners: %s." msgstr "" "기존 리스너가 존재하는 등의 이유로 다음 로드 밸런서는 삭제될 수 없습니다: %s." #, python-format msgid "The following pool could not be deleted: %s." msgstr "다음 풀은 삭제될 수 없습니다: %s." msgid "The health check interval must be greater than or equal to the timeout." msgstr "상태 체크 간격은 타임아웃 값 이상이어야 합니다." msgid "The health monitor has been updated." msgstr "상태 모니터가 업데이트 되었습니다." msgid "" "The health monitor is used to determine the health of your pool members. " "Health checks\n" " routinely run against each member within the pool and the result of the " "health check is used\n" " to determine if the member receives new connections. Each pool can only " "have one health\n" " monitor." msgstr "" "상태 모니터는 풀 멤버의 상태를 결정하는 데 사용됩니다. 상태 체크는\n" " 풀 내의 각 멤버에 대해 주기적으로 실행하고, 상태 체크 결과로 \n" " 멤버가 새 연결을 받을 수 있는지를 결정합니다. 각 풀은 하나의 상태 모니터" "만 \n" " 가질 수 있습니다." msgid "The listener has been updated." msgstr "리스너가 업데이트 되었습니다." msgid "The load balancer has been updated." msgstr "로드 밸런서가 업데이트 되었습니다." msgid "" "The load balancer occupies a neutron network port and has an IP address " "assigned from a subnet." msgstr "" "로드 밸런서는 뉴트론 네트워크 포트를 사용하고 서브넷에서 할당된 IP를 가집니" "다." msgid "The max retry count must be a number between 1 and 10." msgstr "최대 재시도 횟수는 1 ~ 10회입니다." msgid "The pool has been updated." msgstr "풀이 업데이트 되었습니다." msgid "The pool members have been updated." msgstr "풀 멤버가 업데이트 되었습니다." msgid "The port must be a number between 1 and 65535." msgstr "포트 번호는 1 ~ 65535 사이 숫자를 사용해야 합니다." msgid "" "The port must be unique among all listeners attached to this load balancer." msgstr "" "이 로드 밸런서에 연결될 포트는 모든 리스너 중 유일한 포트이어야 합니다." msgid "The timeout must be a number greater than or equal to 0." msgstr "타임아웃 시간은 0 이거나 보다 커야됩니다." msgid "The weight must be a number between 1 and 256." msgstr "가중치는 반드시 숫자 1과 256사이여야 합니다." msgid "" "The weight of a member determines the portion of requests or connections it " "services compared to the other members of the pool." msgstr "" "맴버의 가중치는 풀의 다른 맴버와 비교하여 서비스의 요청이나 연결 부분을 결정" "합니다." msgid "Timeout" msgstr "제한시간" msgid "" "Timeout (sec)\n" " " msgstr "" "타임아웃 (초)\n" " " msgid "Type" msgstr "타입" msgid "URL Path" msgstr "URL 경로" msgid "URL path" msgstr "URL 경로" msgid "Unable to create health monitor." msgstr "상태 모니터를 생성할 수 없습니다." msgid "Unable to create listener." msgstr "리스너를 생성할 수 없습니다." msgid "Unable to create load balancer." msgstr "로드 밸런서를 생성할 수 없습니다." msgid "Unable to create pool." msgstr "풀을 생성할 수 없습니다." msgid "Unable to delete health monitor." msgstr "상태 모니터를 삭제할 수 없습니다." msgid "Unable to delete listener." msgstr "리스너를 삭제할 수 없습니다." msgid "Unable to delete load balancer." msgstr "로드 밸런서를 삭제할 수 없습니다." msgid "Unable to delete pool." msgstr "풀을 삭제할 수 없습니다." #, python-format msgid "Unable to disassociate floating IP address from load balancer: %s." msgstr "다음 로드 밸런서에서 유동 IP를 연결 해제 할 수 없습니다: %s" msgid "Unable to retrieve SSL certificates." msgstr "SSL 인증을 찾을 수 없습니다." msgid "Unable to retrieve health monitor." msgstr "상태 모니터를 가져올 수 없습니다." msgid "Unable to retrieve listener." msgstr "리스너를 가져올 수 없습니다." msgid "Unable to retrieve listeners." msgstr "리스너를 가져올 수 없습니다." msgid "Unable to retrieve load balancer status tree." msgstr "로드 밸런서 상태 트리를 가져올 수 없습니다." msgid "Unable to retrieve load balancer." msgstr "로드 밸런서를 가져올 수 없습니다." msgid "Unable to retrieve load balancers." msgstr "로드 밸런서를 가져올 수 없습니다." msgid "Unable to retrieve member." msgstr "멤버를 가져올 수 없습니다." msgid "Unable to retrieve members." msgstr "멤버를 가져올 수 없습니다." msgid "Unable to retrieve pool." msgstr "풀을 가져올 수 없습니다." msgid "Unable to retrieve secrets." msgstr "비밀 값을 찾을 수 없습니다." msgid "Unable to update health monitor." msgstr "상태 모니터를 업데이트할 수 없습니다." msgid "Unable to update listener." msgstr "리스너를 업데이트할 수 없습니다." msgid "Unable to update load balancer." msgstr "로드 밸런서를 업데이트할 수 없습니다. " msgid "Unable to update member list." msgstr "멤버 목록을 업데이트할 수 없습니다." msgid "Unable to update member." msgstr "멤버를 업데이트할 수 없습니다." msgid "Unable to update pool." msgstr "풀을 업데이트할 수 없습니다." msgid "Update" msgstr "업데이트" msgid "Update Health Monitor" msgstr "상태 모니터 갱신" msgid "Update Listener" msgstr "리스너 업데이트" msgid "Update Load Balancer" msgstr "로드 밸런서 업데이트" msgid "Update Member Weight" msgstr "맴버 가중치 업데이트" msgid "Update Pool" msgstr "풀 업데이트" msgid "Update Weight" msgstr "가중치 업데이트" msgid "" "Use the key-manager service to create any certificate containers before " "creating the listener.\n" " The following documentation provides information on how to create a " "certificate container:\n" " " msgstr "" "리스너를 생성하기 전에 키 관리자 서비스를 사용하여 인증 컨테이너를 만드세" "요.\n" " 다음 문서가 어떻게 인증 컨테이너를 만들수 있는지 정보를 제공합니다.\n" " " msgid "Weight" msgstr "가충치" msgid "" "Weight\n" " " msgstr "" "가중치\n" " " #, python-format msgid "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." msgstr "" "로드 밸런서 \"%s\"에서 유동 IP 주소를 연결 해제하려고 합니다. 확인해주세요. " #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." msgstr "" "\"%s\"을(를) 선택했습니다. 선택 내역을 확인하십시오. 삭제된 상태 모니터는 복" "구할 수 없습니다." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted listeners " "are not recoverable." msgstr "" "\"%s\"을(를) 선택했습니다. 선택을 확인하십시오. 삭제한 리스너는 복구할 수 없" "습니다." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." msgstr "" "\"%s\"를 선택했습니다. 선택 내역을 확인하십시오. 삭제된 로드 밸런서는 복구되" "지 않습니다." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." msgstr "" "\"%s\"을(를) 선택했습니다. 선택 내역을 확인하십시오. 삭제된 풀은 복구할 수 없" "습니다." neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/id/0000775000175100017510000000000013245512321024732 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/id/LC_MESSAGES/0000775000175100017510000000000013245512321026517 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/id/LC_MESSAGES/django.po0000666000175100017510000000117213245511613030327 0ustar zuulzuul00000000000000# suhartono , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01: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-01-17 04:02+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 "Load Balancers" msgstr "Load Balancers (penyeimbang beban)" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/id/LC_MESSAGES/djangojs.po0000666000175100017510000007206713245511613030677 0ustar zuulzuul00000000000000# suhartono , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.0.0b4.dev2\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-08-07 16: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-09 03:20+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" #, python-format msgid "%(ip)s..." msgstr "%(ip)s..." msgid "" "Expected status codes:\n" " The expected HTTP status codes to get from a successful health check. Must " "be a single number,\n" " a comma separated list of numbers, or a range (two numbers separated by a " "hyphen)." msgstr "" "Expected status codes:\n" "Kode status HTTP yang diharapkan untuk mendapatkan dari pemeriksaan " "kesehatan yang sukses. Harus nomor tunggal, \n" "   daftar nomor yang dipisahkan koma, atau kisaran (dua angka yang " "dipisahkan oleh tanda hubung)." msgid "" "HTTP method:\n" " The HTTP method used to perform the health check." msgstr "" "HTTP method:\n" "Metode HTTP yang digunakan untuk melakukan cek kesehatan." msgid "" "IP address:\n" " If an IP address is provided it must be a well-formed IPv4 or IPv6 " "address. The system will\n" " attempt to assign the provided IP address to the load balancer. If an IP " "address is not provided\n" " then one will be allocated for you." msgstr "" "IP address:\n" " Jika alamat IP disediakan, maka itu harus menjadi alamat IPv4 atau IPv6 " "well-formed. Sistem akan\n" "   mencoba untuk menetapkan alamat IP yang disediakan untuk penyeimbang " "beban. Jika alamat IP tidak disediakan\n" "   maka salah satu akan dialokasikan untuk Anda." msgid "" "IP address:\n" " The IP address of the member to receive traffic from the load balancer. " "Must be a well-formed\n" " IPv4 or IPv6 address." msgstr "" "IP address:\n" " Alamat IP dari anggota untuk menerima lalu lintas dari penyeimbang beban. " "Harus alamat \n" "   IPv4 atau IPv6 well-formed." msgid "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgstr "" "Interval:\n" "Jarak waktu antara pemeriksaan kesehatan. Harus lebih besar dari atau sama " "dengan batas waktu (timeout)." msgid "" "Method:\n" " The load balancer algorithm that distributes traffic to the pool members.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgstr "" "Method:\n" "Algoritma penyeimbang beban yang mendistribusikan lalu lintas kepada anggota " "kolam.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgid "" "Port:\n" " The port on which the front end listens. Must be an integer from 1 to " "65535." msgstr "" "Port:\n" " Port dimana ujung depannya mendengarkan. Harus integer 1sampai 65535." msgid "" "Port:\n" " The port on which the member listens for traffic. Must be a number from 1 " "to 65535." msgstr "" "Port:\n" " port dimana anggota mendengarkan lalu lintas. Harus berupa angka 1 sampai " "65535." msgid "" "Protocol:\n" " The protocol for which the front end listens. The TERMINATED_HTTPS " "protocol is only available if\n" " the key-manager service is enabled and you have authority to list " "certificate containers and\n" " secrets." msgstr "" "Protocol:\n" " Protokol dimana ujung depannya mendengarkan. Protokol TERMINATED_HTTPS ini " "hanya tersedia jika\n" "   layanan key-manager diaktifkan dan Anda memiliki kewenangan untuk " "mendaftar kontainer sertifikat dan\n" "   kerahasiaan." msgid "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgstr "" "Retries:\n" "Jumlah kegagalan koneksi yang diperbolehkan sebelum menandai anggota sebagai " "tidak aktif. Harus\n" "   nomor dari 1 sampai 10." msgid "" "Subnet:\n" " The network on which to allocate the load balancer's IP address." msgstr "" "Subnet:\n" " Jaringan yang mengalokasikan alamat IP milik penyeimbang beban ini." msgid "" "Subnet:\n" " The network which contains the IP address of the member." msgstr "" "Subnet:\n" "Jaringan yang berisi alamat IP dari anggota." msgid "" "Timeout:\n" " The time after which a health check times out. Must be a number greater " "than or equal to 0\n" " and less than or equal to the interval." msgstr "" "Timeout:\n" " Waktu setelah beberapa kali pemeriksaan kesehatan keluar. Harus angka yang " "lebih besar dari atau sama dengan 0\n" "   dan kurang dari atau sama dengan interval." msgid "" "URL path:\n" " The target of the health check HTTP request to the member. Must be a valid " "URL path." msgstr "" "URL path:\n" "Target dari permintaan HTTP cek kesehatan ke anggota. Harus path URL yang " "valid." msgid "" "Weight:\n" " The weight of a member determines the portion of requests or connections " "it services compared\n" " to the other members of the pool. A higher weight means it will receive " "more traffic. Must be\n" " a number from 1 to 256." msgstr "" "Weight:\n" " Berat anggota menentukan porsi permintaan atau koneksi layanan IT " "dibandingkan\n" "   degan anggota lain dari kolam. Sebuah berat yang lebih tinggi berarti " "akan menerima lebih banyak lalu lintas. Harus dalam \n" "   nomor 1 sampai 256." msgid "A new health monitor is being created." msgstr "Sebuah pemantauan kesehatan baru sedang dibuat." msgid "A new listener is being created." msgstr "Sebuah pendengar baru sedang dibuat." msgid "A new load balancer is being created." msgstr "Sebuah penyeimbang beban baru sedang dibuat." msgid "A new pool is being created." msgstr "Sebuah kolam baru sedang dibuat." msgid "" "A pool represents a group of members over which the load balancing will be " "applied." msgstr "" "Sebuah kolam mewakili sekelompok anggota dimana load balancing akan " "diterapkan." msgid "Actions" msgstr "Actions (tindakan)" msgid "Active" msgstr "Active (aktif)" msgid "Add" msgstr "Add (tambah)" msgid "Add external member" msgstr "Tambahkan anggota eksternal" msgid "Add members to the load balancer pool." msgstr "Tambahkan anggota ke kolam penyeimbang beban." msgid "Add/Remove Pool Members" msgstr "Add/Remove Pool Members (anggota kolam Add/Remove)" msgid "Address" msgstr "Address (alamat)" msgid "Admin State Up" msgstr "Admin State Up" msgid "Allocated Members" msgstr "Anggota yang dialokasikan" msgid "An error occurred. Please try again later." msgstr "Terjadi kesalahan. Silakan coba lagi nanti." msgid "Associate" msgstr "Associate (mengkaitkan)" msgid "Associate Floating IP" msgstr "Associate Floating IP (mengkaitkan IP mengambang)" msgid "Associate Floating IP Address" msgstr "Associate Floating IP Address (alamat IP mengambang asosiasi)" msgid "Associating floating IP with load balancer." msgstr "Pengkaitan IP mengambang dengan beban penyeimbang." msgid "Available Instances" msgstr "Instance yang tersedia" msgid "Back" msgstr "Back" msgid "Cancel" msgstr "Cancel (batalkan)" msgid "Certificate Name" msgstr "Certificate Name (nama sertifikat)" msgid "Confirm Delete Health Monitor" msgstr "Confirm Delete Health Monitor (konfirmasi hapus pemantauan kesehatan)" msgid "Confirm Delete Listeners" msgstr "Confirm Delete Listeners (konfirmasi penghapusan pendengar)" msgid "Confirm Delete Load Balancers" msgstr "Confirm Delete Load Balancers (konfirmasi hapus beban penyeimbang)" msgid "Confirm Delete Pool" msgstr "Confirm Delete Pool (konfirmasi hapus kolam)" msgid "Confirm Disassociate Floating IP Address" msgstr "Konfirmasi pemisahan alamat IP mengambang" msgid "Connection Limit" msgstr "Connection Limit (batas koneksi)" msgid "Create Health Monitor" msgstr "Create Health Monitor (buat pemantauan kesehatan)" msgid "Create Listener" msgstr "Create Listener (buat pendengar)" msgid "Create Load Balancer" msgstr "Create Load Balancer (buat penyeimbang beban)" msgid "Create Pool" msgstr "Create Pool (buat kolam)" msgid "Default Pool ID" msgstr "Default Pool ID (ID pool default)" msgid "Degraded" msgstr "Degraded (diturunkan)" msgid "Delay" msgstr "Delay (menunda)" msgid "Delete Health Monitor" msgstr "Delete Health Monitor (hapus pemantauan kesehatan)" msgid "Delete Listener" msgstr "Delete Listener (hapus pendengar)" msgid "Delete Listeners" msgstr "Delete Listeners (hapus pendengar)" msgid "Delete Load Balancer" msgstr "Delete Load Balancer (hapus penyeimbang beban)" msgid "Delete Load Balancers" msgstr "Delete Load Balancers (hapus penyeimbang beban)" msgid "Delete Pool" msgstr "Delete Pool (hapus kolam)" #, python-format msgid "Deleted health monitor: %s." msgstr "Pemantauan kesehatan yang dihapus: %s." #, python-format msgid "Deleted listeners: %s." msgstr "Pendengar yang dihapus: %s." #, python-format msgid "Deleted load balancers: %s." msgstr "Penyeimbang beban yang dihapus: %s." #, python-format msgid "Deleted pool: %s." msgstr "Kolam yang dihapus: %s." msgid "Description" msgstr "Description (gambaran)" msgid "Disassociate" msgstr "Disassociate (pemisahan)" msgid "Disassociate Floating IP" msgstr "Disassociate Floating IP (memisahkan IP mengambang)" #, python-format msgid "Disassociated floating IP address from load balancer: %s." msgstr "Alamat IP mengambang yang dipisahkan dari penyeimbang beban: %s." msgid "" "Each port that listens for traffic on a particular load balancer is " "configured separately and\n" " tied to the load balancer. Multiple listeners can be associated with the " "same load balancer but\n" " each must use a unique port." msgstr "" "Setiap port yang mendengarkan lalu lintas pada penyeimbang beban tertentu " "dikonfigurasi secara terpisah dan\n" "   terikat penyeimbang beban. Beberapa pendengar dapat dikaitkan dengan " "penyeimbang beban yang sama tetapi\n" "   masing-masing harus menggunakan port yang unik." msgid "Edit" msgstr "Edit" msgid "Edit Pool" msgstr "Edit Pool (edit kolam)" msgid "Error" msgstr "Error (kesalahan)" msgid "Expected Codes" msgstr "Expected Codes (kode yang diharapkan)" msgid "Expected status codes" msgstr "Expected status codes (kode status yang diharapkan)" msgid "Expiration Date" msgstr "Expiration Date (tanggal kadaluarsa)" msgid "Floating IP Address" msgstr "Floating IP Address (alamat IP mengambang)" msgid "" "Floating IP address or pool\n" " " msgstr "" "Kolam atau alamat IP mengambang " msgid "Floating IP addresses" msgstr "Floating IP addresses (alamat IP mengambang)" msgid "Floating IP pools" msgstr "Floating IP pools (pool IP mengambang)" msgid "HTTP Method" msgstr "HTTP Method (metode HTTP)" msgid "HTTP method" msgstr "HTTP method (methode HTTP)" msgid "Health Monitor ID" msgstr "Health Monitor ID (ID pemantauan kesehatan)" msgid "ID" msgstr "ID" msgid "IP Address" msgstr "IP Address (alamat IP)" msgid "" "IP Address\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " msgstr "" "Alamat IP\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " #, python-format msgid "IP Addresses (%(count)s)" msgstr "Alamat IP (%(count)s)" msgid "IP address" msgstr "Alamat IP" msgid "" "If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL " "certificates must\n" " be selected. The first certificate will be the default." msgstr "" "Jika pendengar menggunakan protokol TERMINATED_HTTPS, maka satu atau lebih " "sertifikat SSL harus\n" "   dipilih. Sertifikat pertama akan menjadi default." msgid "Inactive" msgstr "Inactive" msgid "" "Interval (sec)\n" " " msgstr "" "Interval (sec)\n" " " msgid "Least Connections" msgstr "Least Connections (koneksi paling sedikit)" #, python-format msgid "Listener %(index)s" msgstr "Pendengar %(index)s" msgid "Listener 1" msgstr "Listener 1" msgid "Listener Details" msgstr "Listener Details (rincian pendengar)" msgid "Listener ID" msgstr "Listener ID" msgid "Listeners" msgstr "Listeners (pendengar)" #, python-format msgid "Load Balancer %(index)s" msgstr "Penyeimbang beban %(index)s" msgid "Load Balancer Algorithm" msgstr "Load Balancer Algorithm (algoritma penyeimbang beban)" msgid "Load Balancer Details" msgstr "Load Balancer Details (rincian beban penyeimbang)" msgid "Load Balancer ID" msgstr "Load Balancer ID (ID penyeimbang beban)" msgid "Load Balancers" msgstr "Load Balancers (penyeimbang beban)" msgid "Loading" msgstr "Loading (pemuatan)" msgid "Max Retries" msgstr "Max Retries (pengulangan terbanyak)" msgid "Member ID" msgstr "Member ID (ID anggota)" msgid "Members" msgstr "Members (anggota)" msgid "" "Members are the actual IP addresses that will receive traffic from the load " "balancer. Each\n" " member must have a unique combination of IP address and port." msgstr "" "Anggota adalah alamat IP yang sebenarnya yang akan menerima lalu lintas dari " "penyeimbang beban. Setiap\n" "   anggota harus memiliki kombinasi yang unik dari alamat IP dan port." msgid "" "Method\n" " " msgstr "" "Method\n" " " msgid "Monitor Details" msgstr "Monitor Details (rincian pemantauan)" msgid "Monitor ID" msgstr "Monitor ID" msgid "" "Monitor type\n" " " msgstr "" "Tipe pemantauan\n" " " msgid "Name" msgstr "Name (nama)" msgid "No available certificates" msgstr "Tidak ada sertifikat yang tersedia" msgid "No available instances" msgstr "Tidak ada instance yang tersedia" msgid "No items to display." msgstr "Tidak ada item untuk ditampilkan." msgid "No members have been allocated" msgstr "Tidak ada anggota telah dialokasikan" msgid "None" msgstr "None (tidak ada)" msgid "Offline" msgstr "Offline" msgid "Online" msgstr "Online" msgid "Operating Status" msgstr "Operating Status (status operasi)" msgid "Overview" msgstr "Overview (ikhtisar)" msgid "Pending Create" msgstr "Pending Create (penundaan pembuatan)" msgid "Pending Delete" msgstr "Pending Delete (penundaan penghapusan)" msgid "Pending Update" msgstr "Pending Update (penundaan pembaharuan)" msgid "Pool 1" msgstr "Pool 1" msgid "Pool Details" msgstr "Pool Details (rincian kolam)" msgid "Pool ID" msgstr "Pool ID (ID kolam)" msgid "Pool Members" msgstr "Pool Members (anggota kolam)" msgid "Pool member weight has been updated." msgstr "Berat anggota kolam telah diperbarui." msgid "Port" msgstr "Port" msgid "" "Port\n" " " msgstr "" "Port\n" " " msgid "Port ID" msgstr "Port ID (ID port)" msgid "Protocol" msgstr "Protocol (protokol)" msgid "" "Protocol\n" " " msgstr "" "Protokol\n" " " msgid "Protocol Port" msgstr "Protocol Port (port protokol)" msgid "Provide the details for the health monitor." msgstr "Memberikan rincian untuk pemantauan kesehatan." msgid "Provide the details for the listener." msgstr "Memberikan rincian untuk pendengar." msgid "Provide the details for the load balancer." msgstr "Memberikan rincian untuk penyeimbang beban." msgid "Provide the details for the pool." msgstr "Memberikan rincian untuk kolam." msgid "Provider" msgstr "Provider (penyedia)" msgid "Provisioning Status" msgstr "Provisioning Status (status penyediaan)" msgid "Remove" msgstr "Remove (hilangkan)" msgid "" "Retries\n" " " msgstr "" "Retries\n" " " msgid "Round Robin" msgstr "Round Robin" msgid "SSL Certificates" msgstr "SSL Certificates (sertifikat SSL)" msgid "" "Select a floating IP address to associate with the load balancer or a " "floating IP pool in which to allocate a new floating IP address." msgstr "" "Pilih alamat IP mengambang untuk mengasosiasikan dengan penyeimbang beban " "atau pool IP mengambang yang mengalokasikan alamat IP mengambang baru." msgid "Select certificates from the available certificates below" msgstr "Pilih sertifikat dari sertifikat yang tersedia di bawah ini" msgid "Select one or more SSL certificates for the listener." msgstr "Pilih salah satu atau lebih sertifikat SSL untuk pendengar." msgid "Session Persistence" msgstr "Session Persistence" msgid "Source IP" msgstr "Source IP (IP sumber)" msgid "" "Subnet\n" " " msgstr "" "Subnet\n" " " msgid "Subnet ID" msgstr "Subnet ID (ID subnet)" msgid "Tenant ID" msgstr "Tenant ID" msgid "" "The Available Instances table contains existing compute instances that can " "be added as members\n" " of the pool. Use the \"Add external member\" button to add a member not " "found in the Available\n" " Instances table." msgstr "" "Tabel Available Instance berisi instance komptasi yang ada dimana dapat " "ditambahkan sebagai anggota\n" "   kolam. Gunakan tombol \"Add external member\" untuk menambahkan anggota " "yang tidak ditemukan di tabel \n" "   Available Instance." msgid "The IP address is not valid." msgstr "Alamat IP tidak valid." msgid "The URL path is not valid." msgstr "Path URL tidak sah." msgid "The expected status code is not valid." msgstr "Kode status yang diharapkan adalah tidak sah." #, python-format msgid "The following health monitor could not be deleted: %s." msgstr "Pemantauan kesehatan berikut ini tidak bisa dihapus: %s." #, python-format msgid "" "The following listeners could not be deleted, possibly due to existing " "pools: %s." msgstr "" "Pendengar berikut ini tidak bisa dihapus, mungkin karena kolam yang ada: %s." #, python-format msgid "The following listeners will not be deleted due to existing pools: %s." msgstr "Pendengar berikut tidak akan dihapus karena kolam yang ada: %s." #, python-format msgid "The following load balancers are pending and cannot be deleted: %s." msgstr "Penyeimbang beban berikut yang tertunda dan tidak dapat dihapus: %s." #, python-format msgid "" "The following load balancers could not be deleted, possibly due to existing " "listeners: %s." msgstr "" "Penyeimbang beban berikut tidak dapat dihapus, mungkin karena pendengar yang " "sedang ada: %s." #, python-format msgid "The following pool could not be deleted: %s." msgstr "Kolam berikut ini tidak bisa dihapus: %s." msgid "The health check interval must be greater than or equal to the timeout." msgstr "" "Interval pemeriksaan kesehatan harus lebih besar dari atau sama dengan batas " "waktu." msgid "The health monitor has been updated." msgstr "Pemantauan kesehatan telah diperbarui." msgid "" "The health monitor is used to determine the health of your pool members. " "Health checks\n" " routinely run against each member within the pool and the result of the " "health check is used\n" " to determine if the member receives new connections. Each pool can only " "have one health\n" " monitor." msgstr "" "Pemantauan kesehatan digunakan untuk menentukan kesehatan anggota kolam " "Anda. Pemeriksaan kesehatan\n" "   secara rutin dijalankan terhadap setiap anggota dalam kolam dan hasil " "dari pemeriksaan kesehatan digunakan\n" "   untuk menentukan apakah anggota menerima sambungan baru. Setiap kolam " "hanya dapat memiliki satu pemantauan kesehatan." msgid "The listener has been updated." msgstr "Pendengar telah diperbarui." msgid "The load balancer has been updated." msgstr "Penyeimbang beban telah diperbarui." msgid "" "The load balancer occupies a neutron network port and has an IP address " "assigned from a subnet." msgstr "" "Penyeimbang beban menempati port jaringan neutron dan memiliki alamat IP " "yang ditetapkan dari subnet." msgid "The max retry count must be a number between 1 and 10." msgstr "Jumlah retry max harus dalam angka antara 1 dan 10." msgid "The pool has been updated." msgstr "Kolam telah diperbarui." msgid "The pool members have been updated." msgstr "Para anggota kolam telah diperbarui." msgid "The port must be a number between 1 and 65535." msgstr "Port harus dalam angka antara 1 dan 65535." msgid "" "The port must be unique among all listeners attached to this load balancer." msgstr "" "Port harus unik di antara semua pendengar yang terkait pada penyeimbang " "beban ini." msgid "The timeout must be a number greater than or equal to 0." msgstr "Timeout harus berupa angka lebih besar dari atau sama dengan 0." msgid "The weight must be a number between 1 and 256." msgstr "Berat harus dalam angka antara 1 dan 256." msgid "" "The weight of a member determines the portion of requests or connections it " "services compared to the other members of the pool." msgstr "" "Berat anggota menentukan porsi dari permintaan atau koneksi layanan IT " "dibandingkan dengan anggota lain dari kolam." msgid "Timeout" msgstr "Timeout (waktu habis)" msgid "" "Timeout (sec)\n" " " msgstr "" "Timeout (sec)\n" " " msgid "Type" msgstr "Type (tipe)" msgid "URL Path" msgstr "URL Path" msgid "URL path" msgstr "Path URL" msgid "Unable to create health monitor." msgstr "Tidak dapat membuat pemantauan kesehatan." msgid "Unable to create listener." msgstr "Tidak dapat membuat pendengar." msgid "Unable to create load balancer." msgstr "Tidak dapat membuat penyeimbang beban." msgid "Unable to create pool." msgstr "Tidak dapat membuat kolam." msgid "Unable to delete health monitor." msgstr "Tidak dapat menghapus pemantauan kesehatan." msgid "Unable to delete listener." msgstr "Tidak dapat menghapus pendengar." msgid "Unable to delete load balancer." msgstr "Tidak dapat menghapus penyeimbang beban." msgid "Unable to delete pool." msgstr "Tidak dapat menghapus kolam." #, python-format msgid "Unable to disassociate floating IP address from load balancer: %s." msgstr "" "Tidak dapat memisahkan alamat IP mengambang dari penyeimbang beban: %s." msgid "Unable to retrieve SSL certificates." msgstr "Tidak dapat mengambil sertifikat SSL." msgid "Unable to retrieve health monitor." msgstr "Tidak dapat mengambil pemantauan kesehatan." msgid "Unable to retrieve listener." msgstr "Tidak dapat mengambil pendengar." msgid "Unable to retrieve listeners." msgstr "Tidak dapat mengambil pendengar." msgid "Unable to retrieve load balancer status tree." msgstr "Tidak dapat mengambil status pohon penyeimbang beban." msgid "Unable to retrieve load balancer." msgstr "Tidak dapat mengambil penyeimbang beban." msgid "Unable to retrieve load balancers." msgstr "Tidak dapat mengambil penyeimbang beban." msgid "Unable to retrieve member." msgstr "Tidak dapat mengambil anggota." msgid "Unable to retrieve members." msgstr "Tidak dapat mengambil anggota." msgid "Unable to retrieve pool." msgstr "Tidak dapat mengambil kolam (pool)." msgid "Unable to retrieve secrets." msgstr "Tidak dapat mengambil rahasia." msgid "Unable to update health monitor." msgstr "Tidak dapat memperbarui pemantauan kesehatan." msgid "Unable to update listener." msgstr "Tidak dapat memperbarui pendengar." msgid "Unable to update load balancer." msgstr "Tidak dapat memperbarui penyeimbang beban." msgid "Unable to update member list." msgstr "Tidak dapat memperbarui daftar anggota." msgid "Unable to update member." msgstr "Tidak dapat memperbarui anggota." msgid "Unable to update pool." msgstr "Tidak dapat memperbarui kolam." msgid "Update" msgstr "Update (perbarui)" msgid "Update Health Monitor" msgstr "Update Health Monitor (perbaharui pemantauan kesehatan)" msgid "Update Listener" msgstr "Update Listener (perbarui pendengar)" msgid "Update Load Balancer" msgstr "Update Load Balancer (perbarui penyeimbang beban)" msgid "Update Member Weight" msgstr "Update Member Weight" msgid "Update Pool" msgstr "Update Pool (perbarui kolam)" msgid "Update Weight" msgstr "Update Weight (perbarui berat)" msgid "" "Use the key-manager service to create any certificate containers before " "creating the listener.\n" " The following documentation provides information on how to create a " "certificate container:\n" " " msgstr "" "Gunakan layanan key-manager untuk menciptakan kontainer sertifikat sebelum " "membuat pendengar.\n" "   Dokumentasi berikut memberikan informasi tentang cara membuat kontainer " "sertifikat:\n" " " msgid "Weight" msgstr "Weight (berat)" msgid "" "Weight\n" " " msgstr "" "Weight (berat) \n" " " #, python-format msgid "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." msgstr "" "Anda akan memisahkan alamat IP mengambang dari penyeimbang beban \"%s\". " "Silahkan konfirmasi." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." msgstr "" "Anda telah memilih \"%s\". Harap mengkonfirmasi pilihan Anda. Pemantauan " "kesehatan yang telah dihapus tidak dapat dipulihkan." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted listeners " "are not recoverable." msgstr "" "Anda telah memilih \"%s\". Harap mengkonfirmasi pilihan Anda. Pendengar yang " "telah dihapus tidak dapat dipulihkan." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." msgstr "" "Anda telah memilih \"%s\". Harap mengkonfirmasi pilihan Anda. Penyeimbang " "beban yang telah dihapus tidak dapat dipulihkan." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." msgstr "" "Anda telah memilih \"%s\". Harap mengkonfirmasi pilihan Anda. Kolam yang " "telah dihapus tidak dapat dipulihkan." neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/en_GB/0000775000175100017510000000000013245512321025310 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/en_GB/LC_MESSAGES/0000775000175100017510000000000013245512321027075 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/en_GB/LC_MESSAGES/django.po0000666000175100017510000000116613245511613030710 0ustar zuulzuul00000000000000# Andi Chandler , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01: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-09-28 03:59+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 "Load Balancers" msgstr "Load Balancers" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/en_GB/LC_MESSAGES/djangojs.po0000666000175100017510000006563013245511613031253 0ustar zuulzuul00000000000000# Andi Chandler , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01: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-10-09 12:39+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 "%(ip)s..." msgstr "%(ip)s..." msgid "" "Expected status codes:\n" " The expected HTTP status codes to get from a successful health check. Must " "be a single number,\n" " a comma separated list of numbers, or a range (two numbers separated by a " "hyphen)." msgstr "" "Expected status codes:\n" " The expected HTTP status codes to get from a successful health check. Must " "be a single number,\n" " a comma separated list of numbers, or a range (two numbers separated by a " "hyphen)." msgid "" "HTTP method:\n" " The HTTP method used to perform the health check." msgstr "" "HTTP method:\n" " The HTTP method used to perform the health check." msgid "" "IP address:\n" " If an IP address is provided it must be a well-formed IPv4 or IPv6 " "address. The system will\n" " attempt to assign the provided IP address to the load balancer. If an IP " "address is not provided\n" " then one will be allocated for you." msgstr "" "IP address:\n" " If an IP address is provided it must be a well-formed IPv4 or IPv6 " "address. The system will\n" " attempt to assign the provided IP address to the load balancer. If an IP " "address is not provided\n" " then one will be allocated for you." msgid "" "IP address:\n" " The IP address of the member to receive traffic from the load balancer. " "Must be a well-formed\n" " IPv4 or IPv6 address." msgstr "" "IP address:\n" " The IP address of the member to receive traffic from the load balancer. " "Must be a well-formed\n" " IPv4 or IPv6 address." msgid "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgstr "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgid "" "Method:\n" " The load balancer algorithm that distributes traffic to the pool members.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgstr "" "Method:\n" " The load balancer algorithm that distributes traffic to the pool members.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgid "" "Port:\n" " The port on which the front end listens. Must be an integer from 1 to " "65535." msgstr "" "Port:\n" " The port on which the front end listens. Must be an integer from 1 to " "65535." msgid "" "Port:\n" " The port on which the member listens for traffic. Must be a number from 1 " "to 65535." msgstr "" "Port:\n" " The port on which the member listens for traffic. Must be a number from 1 " "to 65535." msgid "" "Protocol:\n" " The protocol for which the front end listens. The TERMINATED_HTTPS " "protocol is only available if\n" " the key-manager service is enabled and you have authority to list " "certificate containers and\n" " secrets." msgstr "" "Protocol:\n" " The protocol for which the front end listens. The TERMINATED_HTTPS " "protocol is only available if\n" " the key-manager service is enabled and you have authority to list " "certificate containers and\n" " secrets." msgid "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgstr "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgid "" "Subnet:\n" " The network on which to allocate the load balancer's IP address." msgstr "" "Subnet:\n" " The network on which to allocate the load balancer's IP address." msgid "" "Subnet:\n" " The network which contains the IP address of the member." msgstr "" "Subnet:\n" " The network which contains the IP address of the member." msgid "" "Timeout:\n" " The time after which a health check times out. Must be a number greater " "than or equal to 0\n" " and less than or equal to the interval." msgstr "" "Timeout:\n" " The time after which a health check times out. Must be a number greater " "than or equal to 0\n" " and less than or equal to the interval." msgid "" "URL path:\n" " The target of the health check HTTP request to the member. Must be a valid " "URL path." msgstr "" "URL path:\n" " The target of the health check HTTP request to the member. Must be a valid " "URL path." msgid "" "Weight:\n" " The weight of a member determines the portion of requests or connections " "it services compared\n" " to the other members of the pool. A higher weight means it will receive " "more traffic. Must be\n" " a number from 1 to 256." msgstr "" "Weight:\n" " The weight of a member determines the portion of requests or connections " "it services compared\n" " to the other members of the pool. A higher weight means it will receive " "more traffic. Must be\n" " a number from 1 to 256." msgid "A new health monitor is being created." msgstr "A new health monitor is being created." msgid "A new listener is being created." msgstr "A new listener is being created." msgid "A new load balancer is being created." msgstr "A new load balancer is being created." msgid "A new pool is being created." msgstr "A new pool is being created." msgid "" "A pool represents a group of members over which the load balancing will be " "applied." msgstr "" "A pool represents a group of members over which the load balancing will be " "applied." msgid "Actions" msgstr "Actions" msgid "Active" msgstr "Active" msgid "Add" msgstr "Add" msgid "Add external member" msgstr "Add external member" msgid "Add members to the load balancer pool." msgstr "Add members to the load balancer pool." msgid "Add/Remove Pool Members" msgstr "Add/Remove Pool Members" msgid "Address" msgstr "Address" msgid "Admin State Up" msgstr "Admin State Up" msgid "Allocated Members" msgstr "Allocated Members" msgid "An error occurred. Please try again later." msgstr "An error occurred. Please try again later." msgid "Associate" msgstr "Associate" msgid "Associate Floating IP" msgstr "Associate Floating IP" msgid "Associate Floating IP Address" msgstr "Associate Floating IP Address" msgid "Associating floating IP with load balancer." msgstr "Associating floating IP with load balancer." msgid "Available Instances" msgstr "Available Instances" msgid "Back" msgstr "Back" msgid "Cancel" msgstr "Cancel" msgid "Certificate Name" msgstr "Certificate Name" msgid "Confirm Delete Health Monitor" msgstr "Confirm Delete Health Monitor" msgid "Confirm Delete Listeners" msgstr "Confirm Delete Listeners" msgid "Confirm Delete Load Balancers" msgstr "Confirm Delete Load Balancers" msgid "Confirm Delete Pool" msgstr "Confirm Delete Pool" msgid "Confirm Disassociate Floating IP Address" msgstr "Confirm Disassociate Floating IP Address" msgid "Connection Limit" msgstr "Connection Limit" msgid "Create Health Monitor" msgstr "Create Health Monitor" msgid "Create Listener" msgstr "Create Listener" msgid "Create Load Balancer" msgstr "Create Load Balancer" msgid "Create Pool" msgstr "Create Pool" msgid "Default Pool ID" msgstr "Default Pool ID" msgid "Degraded" msgstr "Degraded" msgid "Delay" msgstr "Delay" msgid "Delete Health Monitor" msgstr "Delete Health Monitor" msgid "Delete Listener" msgstr "Delete Listener" msgid "Delete Listeners" msgstr "Delete Listeners" msgid "Delete Load Balancer" msgstr "Delete Load Balancer" msgid "Delete Load Balancers" msgstr "Delete Load Balancers" msgid "Delete Pool" msgstr "Delete Pool" #, python-format msgid "Deleted health monitor: %s." msgstr "Deleted health monitor: %s." #, python-format msgid "Deleted listeners: %s." msgstr "Deleted listeners: %s." #, python-format msgid "Deleted load balancers: %s." msgstr "Deleted load balancers: %s." #, python-format msgid "Deleted pool: %s." msgstr "Deleted pool: %s." msgid "Description" msgstr "Description" msgid "Disassociate" msgstr "Disassociate" msgid "Disassociate Floating IP" msgstr "Disassociate Floating IP" #, python-format msgid "Disassociated floating IP address from load balancer: %s." msgstr "Disassociated floating IP address from load balancer: %s." msgid "" "Each port that listens for traffic on a particular load balancer is " "configured separately and\n" " tied to the load balancer. Multiple listeners can be associated with the " "same load balancer but\n" " each must use a unique port." msgstr "" "Each port that listens for traffic on a particular load balancer is " "configured separately and\n" " tied to the load balancer. Multiple listeners can be associated with the " "same load balancer but\n" " each must use a unique port." msgid "Edit" msgstr "Edit" msgid "Edit Pool" msgstr "Edit Pool" msgid "Error" msgstr "Error" msgid "Expected Codes" msgstr "Expected Codes" msgid "Expected status codes" msgstr "Expected status codes" msgid "Expiration Date" msgstr "Expiration Date" msgid "Floating IP Address" msgstr "Floating IP Address" msgid "" "Floating IP address or pool\n" " " msgstr "" "Floating IP address or pool\n" " " msgid "Floating IP addresses" msgstr "Floating IP addresses" msgid "Floating IP pools" msgstr "Floating IP pools" msgid "HTTP Method" msgstr "HTTP Method" msgid "HTTP method" msgstr "HTTP method" msgid "Health Monitor ID" msgstr "Health Monitor ID" msgid "ID" msgstr "ID" msgid "IP Address" msgstr "IP Address" msgid "" "IP Address\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " msgstr "" "IP Address\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " #, python-format msgid "IP Addresses (%(count)s)" msgstr "IP Addresses (%(count)s)" msgid "IP address" msgstr "IP address" msgid "" "If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL " "certificates must\n" " be selected. The first certificate will be the default." msgstr "" "If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL " "certificates must\n" " be selected. The first certificate will be the default." msgid "Inactive" msgstr "Inactive" msgid "" "Interval (sec)\n" " " msgstr "" "Interval (sec)\n" " " msgid "Least Connections" msgstr "Least Connections" #, python-format msgid "Listener %(index)s" msgstr "Listener %(index)s" msgid "Listener 1" msgstr "Listener 1" msgid "Listener Details" msgstr "Listener Details" msgid "Listener ID" msgstr "Listener ID" msgid "Listeners" msgstr "Listeners" #, python-format msgid "Load Balancer %(index)s" msgstr "Load Balancer %(index)s" msgid "Load Balancer Algorithm" msgstr "Load Balancer Algorithm" msgid "Load Balancer Details" msgstr "Load Balancer Details" msgid "Load Balancer ID" msgstr "Load Balancer ID" msgid "Load Balancers" msgstr "Load Balancers" msgid "Loading" msgstr "Loading" msgid "Max Retries" msgstr "Max Retries" msgid "Member ID" msgstr "Member ID" msgid "Members" msgstr "Members" msgid "" "Members are the actual IP addresses that will receive traffic from the load " "balancer. Each\n" " member must have a unique combination of IP address and port." msgstr "" "Members are the actual IP addresses that will receive traffic from the load " "balancer. Each\n" " member must have a unique combination of IP address and port." msgid "" "Method\n" " " msgstr "" "Method\n" " " msgid "Monitor Details" msgstr "Monitor Details" msgid "Monitor ID" msgstr "Monitor ID" msgid "" "Monitor type\n" " " msgstr "" "Monitor type\n" " " msgid "Name" msgstr "Name" msgid "No available certificates" msgstr "No available certificates" msgid "No available instances" msgstr "No available instances" msgid "No items to display." msgstr "No items to display." msgid "No members have been allocated" msgstr "No members have been allocated" msgid "None" msgstr "None" msgid "Offline" msgstr "Offline" msgid "Online" msgstr "Online" msgid "Operating Status" msgstr "Operating Status" msgid "Overview" msgstr "Overview" msgid "Pending Create" msgstr "Pending Create" msgid "Pending Delete" msgstr "Pending Delete" msgid "Pending Update" msgstr "Pending Update" msgid "Pool 1" msgstr "Pool 1" msgid "Pool Details" msgstr "Pool Details" msgid "Pool ID" msgstr "Pool ID" msgid "Pool Members" msgstr "Pool Members" msgid "Pool member weight has been updated." msgstr "Pool member weight has been updated." msgid "Port" msgstr "Port" msgid "" "Port\n" " " msgstr "" "Port\n" " " msgid "Port ID" msgstr "Port ID" msgid "Protocol" msgstr "Protocol" msgid "" "Protocol\n" " " msgstr "" "Protocol\n" " " msgid "Protocol Port" msgstr "Protocol Port" msgid "Provide the details for the health monitor." msgstr "Provide the details for the health monitor." msgid "Provide the details for the listener." msgstr "Provide the details for the listener." msgid "Provide the details for the load balancer." msgstr "Provide the details for the load balancer." msgid "Provide the details for the pool." msgstr "Provide the details for the pool." msgid "Provider" msgstr "Provider" msgid "Provisioning Status" msgstr "Provisioning Status" msgid "Remove" msgstr "Remove" msgid "" "Retries\n" " " msgstr "" "Retries\n" " " msgid "Round Robin" msgstr "Round Robin" msgid "SSL Certificates" msgstr "SSL Certificates" msgid "" "Select a floating IP address to associate with the load balancer or a " "floating IP pool in which to allocate a new floating IP address." msgstr "" "Select a floating IP address to associate with the load balancer or a " "floating IP pool in which to allocate a new floating IP address." msgid "Select certificates from the available certificates below" msgstr "Select certificates from the available certificates below" msgid "Select one or more SSL certificates for the listener." msgstr "Select one or more SSL certificates for the listener." msgid "Session Persistence" msgstr "Session Persistence" msgid "Source IP" msgstr "Source IP" msgid "" "Subnet\n" " " msgstr "" "Subnet\n" " " msgid "Subnet ID" msgstr "Subnet ID" msgid "Tenant ID" msgstr "Tenant ID" msgid "" "The Available Instances table contains existing compute instances that can " "be added as members\n" " of the pool. Use the \"Add external member\" button to add a member not " "found in the Available\n" " Instances table." msgstr "" "The Available Instances table contains existing compute instances that can " "be added as members\n" " of the pool. Use the \"Add external member\" button to add a member not " "found in the Available\n" " Instances table." msgid "The IP address is not valid." msgstr "The IP address is not valid." msgid "The URL path is not valid." msgstr "The URL path is not valid." msgid "The expected status code is not valid." msgstr "The expected status code is not valid." #, python-format msgid "The following health monitor could not be deleted: %s." msgstr "The following health monitor could not be deleted: %s." #, python-format msgid "" "The following listeners could not be deleted, possibly due to existing " "pools: %s." msgstr "" "The following listeners could not be deleted, possibly due to existing " "pools: %s." #, python-format msgid "The following listeners will not be deleted due to existing pools: %s." msgstr "The following listeners will not be deleted due to existing pools: %s." #, python-format msgid "The following load balancers are pending and cannot be deleted: %s." msgstr "The following load balancers are pending and cannot be deleted: %s." #, python-format msgid "" "The following load balancers could not be deleted, possibly due to existing " "listeners: %s." msgstr "" "The following load balancers could not be deleted, possibly due to existing " "listeners: %s." #, python-format msgid "The following pool could not be deleted: %s." msgstr "The following pool could not be deleted: %s." msgid "The health check interval must be greater than or equal to the timeout." msgstr "" "The health check interval must be greater than or equal to the timeout." msgid "The health monitor has been updated." msgstr "The health monitor has been updated." msgid "" "The health monitor is used to determine the health of your pool members. " "Health checks\n" " routinely run against each member within the pool and the result of the " "health check is used\n" " to determine if the member receives new connections. Each pool can only " "have one health\n" " monitor." msgstr "" "The health monitor is used to determine the health of your pool members. " "Health checks\n" " routinely run against each member within the pool and the result of the " "health check is used\n" " to determine if the member receives new connections. Each pool can only " "have one health\n" " monitor." msgid "The listener has been updated." msgstr "The listener has been updated." msgid "The load balancer has been updated." msgstr "The load balancer has been updated." msgid "" "The load balancer occupies a neutron network port and has an IP address " "assigned from a subnet." msgstr "" "The load balancer occupies a Neutron network port and has an IP address " "assigned from a subnet." msgid "The max retry count must be a number between 1 and 10." msgstr "The max retry count must be a number between 1 and 10." msgid "The pool has been updated." msgstr "The pool has been updated." msgid "The pool members have been updated." msgstr "The pool members have been updated." msgid "The port must be a number between 1 and 65535." msgstr "The port must be a number between 1 and 65535." msgid "" "The port must be unique among all listeners attached to this load balancer." msgstr "" "The port must be unique among all listeners attached to this load balancer." msgid "The timeout must be a number greater than or equal to 0." msgstr "The timeout must be a number greater than or equal to 0." msgid "The weight must be a number between 1 and 256." msgstr "The weight must be a number between 1 and 256." msgid "" "The weight of a member determines the portion of requests or connections it " "services compared to the other members of the pool." msgstr "" "The weight of a member determines the portion of requests or connections it " "services compared to the other members of the pool." msgid "Timeout" msgstr "Timeout" msgid "" "Timeout (sec)\n" " " msgstr "" "Timeout (sec)\n" " " msgid "Type" msgstr "Type" msgid "URL Path" msgstr "URL Path" msgid "URL path" msgstr "URL path" msgid "Unable to create health monitor." msgstr "Unable to create health monitor." msgid "Unable to create listener." msgstr "Unable to create listener." msgid "Unable to create load balancer." msgstr "Unable to create load balancer." msgid "Unable to create pool." msgstr "Unable to create pool." msgid "Unable to delete health monitor." msgstr "Unable to delete health monitor." msgid "Unable to delete listener." msgstr "Unable to delete listener." msgid "Unable to delete load balancer." msgstr "Unable to delete load balancer." msgid "Unable to delete pool." msgstr "Unable to delete pool." #, python-format msgid "Unable to disassociate floating IP address from load balancer: %s." msgstr "Unable to disassociate floating IP address from load balancer: %s." msgid "Unable to retrieve SSL certificates." msgstr "Unable to retrieve SSL certificates." msgid "Unable to retrieve health monitor." msgstr "Unable to retrieve health monitor." msgid "Unable to retrieve listener." msgstr "Unable to retrieve listener." msgid "Unable to retrieve listeners." msgstr "Unable to retrieve listeners." msgid "Unable to retrieve load balancer status tree." msgstr "Unable to retrieve load balancer status tree." msgid "Unable to retrieve load balancer." msgstr "Unable to retrieve load balancer." msgid "Unable to retrieve load balancers." msgstr "Unable to retrieve load balancers." msgid "Unable to retrieve member." msgstr "Unable to retrieve member." msgid "Unable to retrieve members." msgstr "Unable to retrieve members." msgid "Unable to retrieve pool." msgstr "Unable to retrieve pool." msgid "Unable to retrieve secrets." msgstr "Unable to retrieve secrets." msgid "Unable to update health monitor." msgstr "Unable to update health monitor." msgid "Unable to update listener." msgstr "Unable to update listener." msgid "Unable to update load balancer." msgstr "Unable to update load balancer." msgid "Unable to update member list." msgstr "Unable to update member list." msgid "Unable to update member." msgstr "Unable to update member." msgid "Unable to update pool." msgstr "Unable to update pool." msgid "Update" msgstr "Update" msgid "Update Health Monitor" msgstr "Update Health Monitor" msgid "Update Listener" msgstr "Update Listener" msgid "Update Load Balancer" msgstr "Update Load Balancer" msgid "Update Member Weight" msgstr "Update Member Weight" msgid "Update Pool" msgstr "Update Pool" msgid "Update Weight" msgstr "Update Weight" msgid "" "Use the key-manager service to create any certificate containers before " "creating the listener.\n" " The following documentation provides information on how to create a " "certificate container:\n" " " msgstr "" "Use the key-manager service to create any certificate containers before " "creating the listener.\n" " The following documentation provides information on how to create a " "certificate container:\n" " " msgid "Weight" msgstr "Weight" msgid "" "Weight\n" " " msgstr "" "Weight\n" " " #, python-format msgid "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." msgstr "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." msgstr "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted listeners " "are not recoverable." msgstr "" "You have selected \"%s\". Please confirm your selection. Deleted listeners " "are not recoverable." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." msgstr "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." msgstr "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/tr_TR/0000775000175100017510000000000013245512321025370 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/tr_TR/LC_MESSAGES/0000775000175100017510000000000013245512321027155 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/tr_TR/LC_MESSAGES/django.po0000666000175100017510000000125513245511613030767 0ustar zuulzuul00000000000000# işbaran akçayır , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01: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-05-23 12:37+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: 1495541313.000000\n" msgid "Load Balancers" msgstr "Yük Dengeleyiciler" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/tr_TR/LC_MESSAGES/djangojs.po0000666000175100017510000006627013245511613031334 0ustar zuulzuul00000000000000# Andreas Jaeger , 2017. #zanata # işbaran akçayır , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.0.0b2.dev5\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-05-17 11:48+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-06-19 11:58+0000\n" "Last-Translator: Andreas Jaeger \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: 1495542946.000000\n" #, python-format msgid "%(ip)s..." msgstr "%(ip)s..." msgid "" "Expected status codes:\n" " The expected HTTP status codes to get from a successful health check. Must " "be a single number,\n" " a comma separated list of numbers, or a range (two numbers separated by a " "hyphen)." msgstr "" "Beklenen durum kodu:\n" " Başarılı bir sağlık kontrolünden sonra alınması beklenen HTTP durum " "kodları. Tek bir say,\n" " virgülle ayrılmış sayılar listesi, veya bir aralık olabilir (tire ile " "ayrılmış iki sayı)." msgid "" "HTTP method:\n" " The HTTP method used to perform the health check." msgstr "" "HTTP yöntemi:\n" " Sağlık kontrolü yapılırken kullanılacak HTTP yöntemi." msgid "" "IP address:\n" " If an IP address is provided it must be a well-formed IPv4 or IPv6 " "address. The system will\n" " attempt to assign the provided IP address to the load balancer. If an IP " "address is not provided\n" " then one will be allocated for you." msgstr "" "IP adresi:\n" " Bir IP adresi sağlanmışsa iyi biçimlenmiş bir IPv4 veya IPv6 adresi " "olmalıdır. Sistem sağlanan IP\n" " adresini yük dengeleyiciye atamaya çalışacaktır. IP adresi sağlanmamışsa " "sizin için bir tane\n" " ayrılır." msgid "" "IP address:\n" " The IP address of the member to receive traffic from the load balancer. " "Must be a well-formed\n" " IPv4 or IPv6 address." msgstr "" "IP adresi:\n" " Yük dengeleyiciden trafiği alacak üyenin IP adresi. İyi biçimlendirilmiş " "IPv4 veya IPv6 adresi olmalıdır." msgid "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgstr "" "Aralık:\n" " Sağlık kontrolleri arasındaki aralık. Zaman aşımına eşit ya da zaman " "aşımından büyük olmalı." msgid "" "Method:\n" " The load balancer algorithm that distributes traffic to the pool members.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgstr "" "Yöntem:\n" " Trafiği havuz üyelerine dağıtan yük dengeleme algoritması.\n" "
    \n" "
  • \n" " EN_AZ_BAĞLANTI: İsteği en az etkin bağlantıya sahip sunucuya ayırır.\n" "
  • \n" "
  • \n" " HEPSİNİ_SIRAYLA: İstekleri birden fazla sunucu arasında eşit şekilde " "döndürür.\n" "
  • \n" "
  • \n" " KAYNAK_IP: Aynı IP adresi kaynaklı istekler sürekli aynı sunucuya " "yönlendirilir.\n" "
  • \n" "
" msgid "" "Port:\n" " The port on which the front end listens. Must be an integer from 1 to " "65535." msgstr "" "Bağlantı Noktası:\n" " Ön ucun dinleyeceği bağlantı noktası. 1 ve 65535 arasında tam sayı " "olmalıdır." msgid "" "Port:\n" " The port on which the member listens for traffic. Must be a number from 1 " "to 65535." msgstr "" "Bağlantı Noktası:\n" " Üyenin trafik dinleyeceği bağlantı noktası. 1 ve 65535 arasında bir sayı " "olmalı." msgid "" "Protocol:\n" " The protocol for which the front end listens. The TERMINATED_HTTPS " "protocol is only available if\n" " the key-manager service is enabled and you have authority to list " "certificate containers and\n" " secrets." msgstr "" "İletişim Kuralı:\n" " Ön ucun dinleyeceği iletişim kuralı. TERMINATED_HTTPS iletişim kuralı " "yalnızca anahtar-yönetici servisi\n" " etkinse ve sertifika kapsayıcıları ve gizleri listeleme yetkiniz varsa " "kullanılabilir." msgid "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgstr "" "Yeniden deneme:\n" " Üyeyi pasif olarak işaretlemeden önce izin verilen başarısız bağlantı " "sayısı. 1 ve 10 arasında bir sayı olmalıdır." msgid "" "Subnet:\n" " The network on which to allocate the load balancer's IP address." msgstr "" "Alt ağ:\n" " Yük dengeleyicinin IP adresinin ayrılacağı ağ." msgid "" "Subnet:\n" " The network which contains the IP address of the member." msgstr "" "Alt ağ:\n" " Üyenin IP adresini içeren ağ." msgid "" "Timeout:\n" " The time after which a health check times out. Must be a number greater " "than or equal to 0\n" " and less than or equal to the interval." msgstr "" "Zaman aşımı:\n" " Bir sağlık kontrolünün zaman aşımına uğrama zamanı. 0 veya 0'dan büyük, " "aralığa eşit ya da\n" " aralıktan küçük bir sayı olmalıdır." msgid "" "URL path:\n" " The target of the health check HTTP request to the member. Must be a valid " "URL path." msgstr "" "URL yolu:\n" " Üyeye yapılan sağlık kontrolü HTTP isteğinin hedefi. Geçerli bir URL yolu " "olmalı." msgid "" "Weight:\n" " The weight of a member determines the portion of requests or connections " "it services compared\n" " to the other members of the pool. A higher weight means it will receive " "more traffic. Must be\n" " a number from 1 to 256." msgstr "" "Ağırlık:\n" " Bir üyenin ağırlığı havuzun diğer üyelerine oranla ne kadar bağlantı ya da " "istek servis edeceğini\n" " belirler. Daha yüksek ağırlık daha çok trafik alacak demektir. 1 ve 256 " "arasında bir sayı olmalıdır." msgid "A new health monitor is being created." msgstr "Yeni bir sağlık izleyici oluşturuluyor." msgid "A new listener is being created." msgstr "Yeni bir dinleyici oluşturuluyor." msgid "A new load balancer is being created." msgstr "Yeni bir yük dengeleyici oluşturuluyor." msgid "A new pool is being created." msgstr "Yeni bir havuz oluşturuluyor." msgid "" "A pool represents a group of members over which the load balancing will be " "applied." msgstr "Havuz yük dengelemenin uygulanacağı bir grup üyeyi temsil eder." msgid "Actions" msgstr "Eylemler" msgid "Active" msgstr "Etkin" msgid "Add" msgstr "Ekle" msgid "Add external member" msgstr "Harici üye ekle" msgid "Add members to the load balancer pool." msgstr "Üyeleri yük dengeleyici havuzuna ekle." msgid "Add/Remove Pool Members" msgstr "Havuz Üyeleri Ekle/Çıkar" msgid "Address" msgstr "Adres" msgid "Admin State Up" msgstr "Yönetici Durumu Açık" msgid "Allocated Members" msgstr "Ayrılmış Üyeler" msgid "An error occurred. Please try again later." msgstr "Bir hata oluştu. Lütfen daha sonra tekrar deneyin." msgid "Associate" msgstr "İlişkilendir" msgid "Associate Floating IP" msgstr "Değişken IP Ata" msgid "Associate Floating IP Address" msgstr "Değişken IP Adresleri ile İlişkilendir" msgid "Associating floating IP with load balancer." msgstr "Yük dengeleyiciye değişken IP ilişkilendirme." msgid "Available Instances" msgstr "Kullanılabilir Sunucular" msgid "Cancel" msgstr "İptal" msgid "Certificate Name" msgstr "Sertifika İsmi" msgid "Confirm Delete Health Monitor" msgstr "Sağlık İzleyici Silmeyi Onayla" msgid "Confirm Delete Listeners" msgstr "Dinleyici Silmeyi Onayla" msgid "Confirm Delete Load Balancers" msgstr "Yük Dengeleyicileri Silmeyi Onayla" msgid "Confirm Delete Pool" msgstr "Havuzu Silmeyi Onayla" msgid "Confirm Disassociate Floating IP Address" msgstr "Değişken IP Adresi İlişkisini Kaldırmayı Onaylayın" msgid "Connection Limit" msgstr "Bağlantı Sınırı" msgid "Create Health Monitor" msgstr "Sağlık İzleyici Oluştur" msgid "Create Listener" msgstr "Dinleyici Oluştur" msgid "Create Load Balancer" msgstr "Yük Dengeleyici Oluştur" msgid "Create Pool" msgstr "Havuz Oluştur" msgid "Default Pool ID" msgstr "Öntanımlı Havuz Kimliği" msgid "Degraded" msgstr "Alçaltılmış" msgid "Delay" msgstr "Gecikme" msgid "Delete Health Monitor" msgstr "Sağlık İzleyiciyi Sil" msgid "Delete Listener" msgstr "Dinleyiciyi Sil" msgid "Delete Listeners" msgstr "Dinleyicileri Sil" msgid "Delete Load Balancer" msgstr "Yük Dengeleyiciyi Sil" msgid "Delete Load Balancers" msgstr "Yük Dengeleyicileri Sil" msgid "Delete Pool" msgstr "Havuzu Sil" #, python-format msgid "Deleted health monitor: %s." msgstr "Sağlık izleyici silindi: %s." #, python-format msgid "Deleted listeners: %s." msgstr "Dinleyiciler silindi: %s." #, python-format msgid "Deleted load balancers: %s." msgstr "Yük dengeleyici silindi: %s." #, python-format msgid "Deleted pool: %s." msgstr "Havuz silindi: %s." msgid "Description" msgstr "Tanım" msgid "Disassociate" msgstr "İlişkiyi Kaldır" msgid "Disassociate Floating IP" msgstr "Değişken IP İlişiğini Kes" #, python-format msgid "Disassociated floating IP address from load balancer: %s." msgstr "Değişken IP adresi yük dengeleyiciden ayrılıyor: %s." msgid "" "Each port that listens for traffic on a particular load balancer is " "configured separately and\n" " tied to the load balancer. Multiple listeners can be associated with the " "same load balancer but\n" " each must use a unique port." msgstr "" "Bir yük dengeleyici üzerinde trafik dinleyen her bağlantı noktası ayrıca " "yapılandırılır ve\n" " yük dengeleyiciye bağlanır. Birden çok dinleyici aynı yük dengeleyici ile " "ilişkilendirilebilir ama\n" " her biri benzersiz bir bağlantı noktası kullanmalıdır." msgid "Edit" msgstr "Düzenle" msgid "Edit Pool" msgstr "Havuzu Düzenle" msgid "Error" msgstr "Hata" msgid "Expected Codes" msgstr "Beklenen Kodlar" msgid "Expected status codes" msgstr "Beklenen durum kodları" msgid "Expiration Date" msgstr "Son Kullanma Tarihi" msgid "Floating IP Address" msgstr "Değişken IP Adresi" msgid "" "Floating IP address or pool\n" " " msgstr "" "Değişken IP adresi veya havuzu\n" "" msgid "Floating IP addresses" msgstr "Değişken IP adresleri" msgid "Floating IP pools" msgstr "Değişken IP havuzları" msgid "HTTP Method" msgstr "HTTP Yöntemi" msgid "HTTP method" msgstr "HTTP yöntemi" msgid "Health Monitor ID" msgstr "Sağlık İzleyici Kimliği" msgid "ID" msgstr "Kimlik" msgid "IP Address" msgstr "IP Adresi" msgid "" "IP Address\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " msgstr "" "IP Adresi\n" " 0\">\n" "\n" "\n" "Alt Ağ\n" " 0\">\n" "\n" "\n" "Bağlantı Noktası\n" " 0\">\n" "\n" "Ağırlık\n" "" #, python-format msgid "IP Addresses (%(count)s)" msgstr "IP Adresleri (%(count)s)" msgid "IP address" msgstr "IP adresi" msgid "" "If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL " "certificates must\n" " be selected. The first certificate will be the default." msgstr "" "Dinleyici TERMINATED_HTTPS iletişim kuralını kullanıyorsa, bir ya da fazla " "SSL sertifikası seçilmelidir.\n" " İlk sertifika ön tanımlı olur." msgid "" "Interval (sec)\n" " " msgstr "" "Aralık (sn)\n" "" msgid "Least Connections" msgstr "En Az Bağlantı" #, python-format msgid "Listener %(index)s" msgstr "Dinleyici %(index)s" msgid "Listener 1" msgstr "Dinleyici 1" msgid "Listener Details" msgstr "Dinleyici Ayrıntıları" msgid "Listener ID" msgstr "Dinleyici Kimliği" msgid "Listeners" msgstr "Dinleyiciler" #, python-format msgid "Load Balancer %(index)s" msgstr "Yük Dengeleyici %(index)s" msgid "Load Balancer Algorithm" msgstr "Yük Dengeleme Algoritması" msgid "Load Balancer Details" msgstr "Yük Dengeleyici Ayrıntıları" msgid "Load Balancer ID" msgstr "Yük Dengeleyici Kimliği" msgid "Load Balancers" msgstr "Yük Dengeleyiciler" msgid "Loading" msgstr "Yükleniyor" msgid "Max Retries" msgstr "Azami Deneme" msgid "Member ID" msgstr "Üye Kimliği" msgid "Members" msgstr "Üyeler" msgid "" "Members are the actual IP addresses that will receive traffic from the load " "balancer. Each\n" " member must have a unique combination of IP address and port." msgstr "" "Üyeler yük dengeleyiciden trafiği alacak asıl IP adresleridir. Her üyenin " "benzersiz bir\n" " IP adresi ve bağlantı noktası bileşimi olmalıdır." msgid "" "Method\n" " " msgstr "" "Yöntem\n" "" msgid "Monitor Details" msgstr "İzleyici Ayrıntıları" msgid "Monitor ID" msgstr "İzleyici Kimliği" msgid "" "Monitor type\n" " " msgstr "" "İzleyici türü\n" "" msgid "Name" msgstr "İsim" msgid "No available certificates" msgstr "Kullanılabilir sertifika yok" msgid "No available instances" msgstr "Kullanılabilir sunucu yok" msgid "No items to display." msgstr "Gösterilecek öge yok." msgid "No members have been allocated" msgstr "Hiçbir üye ayrılmamış" msgid "None" msgstr "Hiçbiri" msgid "Offline" msgstr "Çevrimdışı" msgid "Online" msgstr "Çevirmiçi" msgid "Operating Status" msgstr "İşletim Durumu" msgid "Overview" msgstr "Genel Görünüm" msgid "Pending Create" msgstr "Oluşturma Bekleniyor" msgid "Pending Delete" msgstr "Silme Bekleniyor" msgid "Pending Update" msgstr "Güncelleme Bekleniyor" msgid "Pool 1" msgstr "Havuz 1" msgid "Pool Details" msgstr "Havuz Ayrıntıları" msgid "Pool ID" msgstr "Havuz Kimliği" msgid "Pool Members" msgstr "Havuz Üyeleri" msgid "Pool member weight has been updated." msgstr "Havuz üye ağırlığı güncellendi." msgid "Port" msgstr "Bağlantı Noktası" msgid "" "Port\n" " " msgstr "" "Bağlantı Noktası\n" "" msgid "Port ID" msgstr "Bağlantı Noktası Kimliği" msgid "Protocol" msgstr "İletişim Kuralı" msgid "" "Protocol\n" " " msgstr "" "İletişim kuralı\n" "" msgid "Protocol Port" msgstr "İletişim Bağlantı Noktası" msgid "Provide the details for the health monitor." msgstr "Sağlık izleyici ile ilgili ayrıntıları girin." msgid "Provide the details for the listener." msgstr "Dinleyici ayrıntılarını girin." msgid "Provide the details for the load balancer." msgstr "Yük dengeleyici için ayrıntıları girin." msgid "Provide the details for the pool." msgstr "Havuz ayrıntılarını girin." msgid "Provider" msgstr "Sağlayıcı" msgid "Provisioning Status" msgstr "Hazırlama Durumu" msgid "Remove" msgstr "Kaldır" msgid "" "Retries\n" " " msgstr "" "Yeniden denemeler\n" "" msgid "Round Robin" msgstr "Hepsini Sırayla" msgid "SSL Certificates" msgstr "SSL Sertifikaları" msgid "" "Select a floating IP address to associate with the load balancer or a " "floating IP pool in which to allocate a new floating IP address." msgstr "" "Yük dengeleyici ile ilişkilendirmek ve yeni bir değişken IP adresi ayırmak " "için bir değişken IP veya değişken IP havuzu seçin." msgid "Select certificates from the available certificates below" msgstr "Aşağıdaki kullanılabilir sertifikalar içinden sertifikaları seçin" msgid "Select one or more SSL certificates for the listener." msgstr "Dinleyici için bir ya da fazla SSL sertifikası seçin." msgid "Session Persistence" msgstr "Oturum Kalıcılığı" msgid "Source IP" msgstr "Kaynak IP" msgid "" "Subnet\n" " " msgstr "" "Alt ağ\n" "" msgid "Subnet ID" msgstr "Alt Ağ Kimliği" msgid "Tenant ID" msgstr "Kiracı Kimliği" msgid "" "The Available Instances table contains existing compute instances that can " "be added as members\n" " of the pool. Use the \"Add external member\" button to add a member not " "found in the Available\n" " Instances table." msgstr "" "Kullanılabilir sunucular tablosu havuzun üyeleri olarak eklenebilecek mevcut " "hesaplama sunucularını içerir\n" " Kullanılabilir Sunucular tablosunda bulunmayan bir üye eklemek için " "\"Harici üye ekle\" düğmesini kullanın." msgid "The IP address is not valid." msgstr "IP adresi geçerli değil." msgid "The URL path is not valid." msgstr "URL yolu geçerli değil." msgid "The expected status code is not valid." msgstr "Beklenen durum kodu geçerli değil." #, python-format msgid "The following health monitor could not be deleted: %s." msgstr "Şu sağlık izleyici silinemedi: %s." #, python-format msgid "" "The following listeners could not be deleted, possibly due to existing " "pools: %s." msgstr "Şu dinleyiciler silinemedi, muhtemelen mevcut havuzlar sebebiyle: %s." #, python-format msgid "The following listeners will not be deleted due to existing pools: %s." msgstr "Şu dinleyiciler mevcut havuzlar nedeniyle silinmeyecek: %s." #, python-format msgid "The following load balancers are pending and cannot be deleted: %s." msgstr "Bu yük dengeleyiciler bekleme aşamasında ev silinemezler: %s." #, python-format msgid "" "The following load balancers could not be deleted, possibly due to existing " "listeners: %s." msgstr "" "Bu yük dengeleyiciler silinemedi, muhtemelen mevcut dinleyiciler yüzünden: " "%s." #, python-format msgid "The following pool could not be deleted: %s." msgstr "Bu havuz silinemedi: %s." msgid "The health check interval must be greater than or equal to the timeout." msgstr "" "Sağlık kontrolü aralığı zaman aşımına eşit ya da zaman aşımından yüksek " "olmalı." msgid "The health monitor has been updated." msgstr "Sağlık izleyici güncellendi." msgid "" "The health monitor is used to determine the health of your pool members. " "Health checks\n" " routinely run against each member within the pool and the result of the " "health check is used\n" " to determine if the member receives new connections. Each pool can only " "have one health\n" " monitor." msgstr "" "Sağlık izleyici havuz üyelerinizin sağlığına karar vermede kullanılır. " "Sağlık kontrolleri havuzun her\n" " üyesine aralıklarla yapılır ve sağlık kontrolü sonucuna göre üyenin yeni " "bağlantı alıp almayacağına\n" " karar verilir. Her havuzun sadece bir sağlık izleyicisi olabilir." msgid "The listener has been updated." msgstr "Dinleyici güncellendi." msgid "The load balancer has been updated." msgstr "Yük dengeleyici güncellendi." msgid "" "The load balancer occupies a neutron network port and has an IP address " "assigned from a subnet." msgstr "" "Yük dengeleyici bir neutron ağ bağlantı noktası alır ve alt ağdan bir IP " "adresi atanır." msgid "The max retry count must be a number between 1 and 10." msgstr "Azami yeniden deneme sayısı 1 ve 10 arasında bir sayı olmalı." msgid "The pool has been updated." msgstr "Havuz güncellendi." msgid "The pool members have been updated." msgstr "Havuz üyeleri güncellendi." msgid "The port must be a number between 1 and 65535." msgstr "Bağlantı noktası 1 ve 65535 arasında bir sayı olmalı." msgid "" "The port must be unique among all listeners attached to this load balancer." msgstr "" "Bağlantı noktası bu yük dengeleyiciye atanmış tüm dinleyiciler arasında " "benzersiz olmalı." msgid "The timeout must be a number greater than or equal to 0." msgstr "Zaman aşımı 0 ya da 0'dan büyük olmalı." msgid "The weight must be a number between 1 and 256." msgstr "Ağırlık 1 ve 256 arasında bir sayı olmalı." msgid "" "The weight of a member determines the portion of requests or connections it " "services compared to the other members of the pool." msgstr "" "Bir üyenin ağırlığı havuzun diğer üyelerine göre servis vereceği istek veya " "bağlantı oranını gösterir." msgid "Timeout" msgstr "Zaman aşımı" msgid "" "Timeout (sec)\n" " " msgstr "" "Zaman aşımı (sn)\n" "" msgid "Type" msgstr "Tür" msgid "URL Path" msgstr "URL Yolu" msgid "URL path" msgstr "URL yolu" msgid "Unable to create health monitor." msgstr "Sağlık izleyici oluşturulamadı." msgid "Unable to create listener." msgstr "Dinleyici oluşturulamıyor." msgid "Unable to create load balancer." msgstr "Yük dengeleyici oluşturulamıyor." msgid "Unable to create pool." msgstr "Havuz oluşturulamıyor." msgid "Unable to delete health monitor." msgstr "Sağlık izleyici silinemedi." msgid "Unable to delete listener." msgstr "Dinleyici silinemiyor." msgid "Unable to delete load balancer." msgstr "Yük dengeleyici silinemiyor." msgid "Unable to delete pool." msgstr "Havuz silinemiyor." #, python-format msgid "Unable to disassociate floating IP address from load balancer: %s." msgstr "Değişken IP adresi yük dengeleyiciden ayırılamıyor: %s." msgid "Unable to retrieve SSL certificates." msgstr "SSL Sertifikaları alınamıyor." msgid "Unable to retrieve health monitor." msgstr "Sağlık izleyici alınamadı." msgid "Unable to retrieve listener." msgstr "Dinleyici alınamıyor." msgid "Unable to retrieve listeners." msgstr "Dinleyiciler alınamıyor." msgid "Unable to retrieve load balancer." msgstr "Yük dengeleyici alınamıyor." msgid "Unable to retrieve load balancers." msgstr "Yük dengeleyiciler alınamıyor." msgid "Unable to retrieve member." msgstr "Üye alınamıyor." msgid "Unable to retrieve members." msgstr "Üyeler alınamıyor." msgid "Unable to retrieve pool." msgstr "Havuz alınamıyor." msgid "Unable to retrieve secrets." msgstr "Gizler alınamıyor." msgid "Unable to update health monitor." msgstr "Sağlık izleyici güncellenemedi." msgid "Unable to update listener." msgstr "Dinleyici güncellenemiyor." msgid "Unable to update load balancer." msgstr "Yük dengeleyici güncellenemiyor." msgid "Unable to update member list." msgstr "Üye listesi güncellenemiyor." msgid "Unable to update member." msgstr "Üye güncellenemiyor." msgid "Unable to update pool." msgstr "Havuz güncellenemiyor." msgid "Update" msgstr "Güncelle" msgid "Update Health Monitor" msgstr "Sağlık İzleyiciyi Güncelle" msgid "Update Listener" msgstr "Dinleyiciyi Güncelle" msgid "Update Load Balancer" msgstr "Yük Dengeleyiciyi Güncelle" msgid "Update Member Weight" msgstr "Üye Ağırlığını Güncelle" msgid "Update Pool" msgstr "Havuzu Güncelle" msgid "Update Weight" msgstr "Ağırlığı Güncelle" msgid "" "Use the key-manager service to create any certificate containers before " "creating the listener.\n" " The following documentation provides information on how to create a " "certificate container:\n" " " msgstr "" "Dinleyiciyi oluşturmadan önce sertifika kapsayıcıları oluşturmak için " "anahtar-yönetim servisini kullanın.\n" " Aşağıdaki belgeler nasıl sertifika kapsayıcı oluşturulacağını anlatır:\n" " " msgid "Weight" msgstr "Ağırlık" msgid "" "Weight\n" " " msgstr "" "Ağırlık\n" "" #, python-format msgid "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." msgstr "" "Değişken IP adresini \"%s\" yük dengeleyicisinden ayırmak üzeresiniz. Lütfen " "onaylayın." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." msgstr "" "\"%s\" seçtiniz. Lütfen seçiminizi onaylayın. Silinen sağlık izleyiciler " "geri getirilemez." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted listeners " "are not recoverable." msgstr "" "\"%s\" seçtiniz. Lütfen seçiminizi onaylayın. Silinen dinleyiciler geri " "getirilemez." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." msgstr "" "\"%s\" seçtiniz. Lütfen seçiminizi onaylayın. Silinen yük dengeleyiciler " "geri getirilemezler." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." msgstr "" "\"%s\" seçtiniz. Lütfen seçiminizi onaylayın. Silinen havuzlar geri " "getirilemez." neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/fr/0000775000175100017510000000000013245512321024745 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/fr/LC_MESSAGES/0000775000175100017510000000000013245512321026532 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/fr/LC_MESSAGES/django.po0000666000175100017510000000115713245511613030345 0ustar zuulzuul00000000000000# Gérald LONLAS , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01:36+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-28 03:48+0000\n" "Last-Translator: Gérald LONLAS \n" "Language-Team: French\n" "Language: fr\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" msgid "Load Balancers" msgstr "Répartiteurs de charge" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/fr/LC_MESSAGES/djangojs.po0000666000175100017510000004623113245511613030704 0ustar zuulzuul00000000000000# Cedric Savignan , 2017. #zanata # Corinne Verheyde , 2017. #zanata # Loic Nicolle , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01: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-10-05 02:15+0000\n" "Last-Translator: Cedric Savignan \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 "%(ip)s..." msgstr "%(ip)s..." msgid "" "HTTP method:\n" " The HTTP method used to perform the health check." msgstr "" "HTTP method:\n" " Méthode HTTP utilisée pour vérifier l'état de santé." msgid "" "IP address:\n" " If an IP address is provided it must be a well-formed IPv4 or IPv6 " "address. The system will\n" " attempt to assign the provided IP address to the load balancer. If an IP " "address is not provided\n" " then one will be allocated for you." msgstr "" "Adresse IP:\n" "Si une adresse IP est fournie, elle doit être une adresse IPv4 ou IPv6 au " "bon format. Le système tentera d’attribuer l’adresse IP fournie au " "répartiteur de charge. Si une adresse IP n’est pas fournie alors il en sera " "alloué une pour vous." msgid "" "IP address:\n" " The IP address of the member to receive traffic from the load balancer. " "Must be a well-formed\n" " IPv4 or IPv6 address." msgstr "" "Adresse IP:\n" " L'adresse IP du membre recevant du trafic du répartiteur de charge. Doit " "être une adresse IPv4 ou IPv6\n" " au bon format." msgid "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgstr "" "Intervalle:\n" "L'intervalle entre chaque diagnostic d'intégrité. Doit être supérieur ou " "égal au délai d'attente." msgid "" "Method:\n" " The load balancer algorithm that distributes traffic to the pool members.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgstr "" "Méthode:\n" " L'algorithme du répartiteur de charge distribuant le trafic aux membres du " "pool.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: LEAST_CONNECTIONS: Allocation des requêtes à " "l'instance \n" " possédant le moins de connexions actives. .\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotation des requêtes alternativement entre les " "différentes instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requêtes d'une même adresse IP source sont toujours " "dirigées vers la même instance.\n" "
  • \n" "
" msgid "" "Port:\n" " The port on which the front end listens. Must be an integer from 1 to " "65535." msgstr "" "Port:\n" " Le port sur lequel le front end écoute. Doit être un entier de 1 à 65535." msgid "" "Port:\n" " The port on which the member listens for traffic. Must be a number from 1 " "to 65535." msgstr "" "Port:\n" "Le port sur lequel le membre écoute le trafic. Doit être un nombre de 1 à " "65535." msgid "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgstr "" "Tentatives:\n" "Le nombre de connexions en échecs avant de définir le membre comme inactif. " "Doit être un \n" "nombre entre 1 et 10." msgid "" "Subnet:\n" " The network on which to allocate the load balancer's IP address." msgstr "" "Sous-réseau:\n" "Le réseau dans lequel allouer l'adresse IP du répartiteur de charge." msgid "" "Subnet:\n" " The network which contains the IP address of the member." msgstr "" "Sous-réseau:\n" "Le réseau contenant l'adresse IP du membre." msgid "A new health monitor is being created." msgstr "Un nouveau moniteur de santé est en cours de création." msgid "A new load balancer is being created." msgstr "Un nouveau répartiteur de charge est en cours de création." msgid "A new pool is being created." msgstr "Un nouveau pool est en cours de création." msgid "" "A pool represents a group of members over which the load balancing will be " "applied." msgstr "" "Un pool représente un groupe de membres sur lequel l'équilibrage de charge " "sera appliqué." msgid "Actions" msgstr "Actions" msgid "Active" msgstr "Actif" msgid "Add" msgstr "Ajouter" msgid "Add external member" msgstr "Ajouter un membre exterieur" msgid "Add members to the load balancer pool." msgstr "Ajouter des membres au pool du répartiteur de charge." msgid "Add/Remove Pool Members" msgstr "Ajouter/Retirer des membres du pool" msgid "Address" msgstr "Adresse" msgid "Admin State Up" msgstr "Etat Admin activé" msgid "Allocated Members" msgstr "Membres alloués" msgid "An error occurred. Please try again later." msgstr "Une erreur s'est produite. Veuillez réessayer ultérieurement." msgid "Associate" msgstr "Associer" msgid "Associate Floating IP" msgstr "Associer une adresse IP flottante" msgid "Associate Floating IP Address" msgstr "Associer une adresse IP flottante" msgid "Associating floating IP with load balancer." msgstr "Associer une adresse IP flottante au répartiteur de charge." msgid "Available Instances" msgstr "Instances disponibles" msgid "Back" msgstr "Retour" msgid "Cancel" msgstr "Annuler" msgid "Certificate Name" msgstr "Nom du certificat" msgid "Confirm Delete Health Monitor" msgstr "Confirmer la suppression du moniteur de santé" msgid "Confirm Delete Listeners" msgstr "Confirmer la suppression des Listeners" msgid "Confirm Delete Load Balancers" msgstr "Confirmer la suppression des répartiteurs de charge" msgid "Confirm Delete Pool" msgstr "Confirmer la suppression du pool" msgid "Confirm Disassociate Floating IP Address" msgstr "Confirmer la dé-association de l'adresse IP flottante" msgid "Connection Limit" msgstr "Limite de connexion" msgid "Create Health Monitor" msgstr "Créer un moniteur de santé" msgid "Create Load Balancer" msgstr "Créer un répartiteur de charge" msgid "Create Pool" msgstr "Créer un pool" msgid "Default Pool ID" msgstr "ID du pool par défaut" msgid "Degraded" msgstr "Dégradé" msgid "Delay" msgstr "Délai" msgid "Delete Health Monitor" msgstr "Supprimer un moniteur de santé" msgid "Delete Load Balancer" msgstr "Supprimer le répartiteur de charge" msgid "Delete Load Balancers" msgstr "Supprimer les répartiteurs de charge" msgid "Delete Pool" msgstr "Supprimer le pool" #, python-format msgid "Deleted health monitor: %s." msgstr "Moniteur de santé %s supprimé." #, python-format msgid "Deleted load balancers: %s." msgstr "Répartiteurs de charge supprimé: %s." #, python-format msgid "Deleted pool: %s." msgstr "Pool %s supprimé" msgid "Description" msgstr "Description" msgid "Disassociate" msgstr "Dissocier" msgid "Disassociate Floating IP" msgstr "Dissocier l'adresse IP flottante" msgid "Edit" msgstr "Editer" msgid "Edit Pool" msgstr "Editer le pool" msgid "Error" msgstr "Erreur" msgid "Expected Codes" msgstr "Codes attendus" msgid "Expected status codes" msgstr "Codes de statut attendus" msgid "Expiration Date" msgstr "Date d'expiration" msgid "Floating IP Address" msgstr "Adresse IP flottante" msgid "Floating IP addresses" msgstr "Adresses IP flottantes" msgid "Floating IP pools" msgstr "Pools d'IP flottantes" msgid "HTTP Method" msgstr "Méthode HTTP" msgid "HTTP method" msgstr "Méthode HTTP" msgid "Health Monitor ID" msgstr "ID du moniteur de santé" msgid "ID" msgstr "ID" msgid "IP Address" msgstr "Adresse IP" msgid "" "IP Address\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " msgstr "" "Adresse IP\n" " 0\">\n" " \n" " \n" " Sous-réseau\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Poids\n" " " #, python-format msgid "IP Addresses (%(count)s)" msgstr "Adresses IP (%(count)s)" msgid "IP address" msgstr "Adresse IP" msgid "Inactive" msgstr "Inactif" msgid "" "Interval (sec)\n" " " msgstr "" "Intervalle (sec)\n" " " msgid "Least Connections" msgstr "Connexions minimales" msgid "Listeners" msgstr "Listeners" #, python-format msgid "Load Balancer %(index)s" msgstr "Répartiteur de charge %(index)s" msgid "Load Balancer Algorithm" msgstr "Algorithme du répartiteur de charge" msgid "Load Balancer Details" msgstr "Détails du répartiteur de charge" msgid "Load Balancer ID" msgstr "ID de l'équilibreur de charge" msgid "Load Balancers" msgstr "Répartiteurs de charge" msgid "Loading" msgstr "Chargement..." msgid "Max Retries" msgstr "Tentatives maxi." msgid "Member ID" msgstr "ID du membre" msgid "Members" msgstr "Membres" msgid "" "Method\n" " " msgstr "" "Méthode\n" " " msgid "Monitor Details" msgstr "Détails du moniteur" msgid "Monitor ID" msgstr "ID du moniteur" msgid "" "Monitor type\n" " " msgstr "" "Type de moniteur\n" " " msgid "Name" msgstr "Nom" msgid "No available certificates" msgstr "Aucun certificat disponible" msgid "No available instances" msgstr "Aucune instance disponible" msgid "No items to display." msgstr "Aucun élément à afficher." msgid "No members have been allocated" msgstr "Aucun membre n'a été alloué" msgid "None" msgstr "Aucun" msgid "Offline" msgstr "Hors ligne" msgid "Online" msgstr "En ligne" msgid "Operating Status" msgstr "Statut opérationnel" msgid "Overview" msgstr "Vue d'ensemble" msgid "Pending Create" msgstr "Création en attente" msgid "Pending Delete" msgstr "Suppression en attente" msgid "Pending Update" msgstr "Mise à jour en attente" msgid "Pool 1" msgstr "Pool 1" msgid "Pool Details" msgstr "Détails du pool" msgid "Pool ID" msgstr "ID du pool" msgid "Pool Members" msgstr "Membres du pool" msgid "Port" msgstr "Port" msgid "" "Port\n" " " msgstr "" "Port\n" " " msgid "Port ID" msgstr "ID port" msgid "Protocol" msgstr "Protocole" msgid "" "Protocol\n" " " msgstr "" "Protocole\n" " " msgid "Protocol Port" msgstr "Port de protocole" msgid "Provide the details for the health monitor." msgstr "Spécifier les détails pour le moniteur d'état." msgid "Provide the details for the pool." msgstr "Spécifier les détails pour le pool." msgid "Provider" msgstr "Fournisseur" msgid "Provisioning Status" msgstr "Statut de Déploiement" msgid "Remove" msgstr "Retirer" msgid "" "Retries\n" " " msgstr "" "Tentatives\n" " " msgid "Round Robin" msgstr "Round Robin" msgid "SSL Certificates" msgstr "Certificats SSL" msgid "Select certificates from the available certificates below" msgstr "Sélectionner les certificats depuis la liste disponible ci dessous" msgid "Session Persistence" msgstr "Persistance de session" msgid "Source IP" msgstr "IP source" msgid "" "Subnet\n" " " msgstr "" "Sous-réseau\n" " " msgid "Subnet ID" msgstr "ID sous-réseau" msgid "Tenant ID" msgstr "ID du tenant" msgid "The IP address is not valid." msgstr "L'adresse IP n'est pas valide." msgid "The URL path is not valid." msgstr "Le chemin d'URL n'est pas valide." msgid "The expected status code is not valid." msgstr "Le code de statut attendu n'est pas valide." #, python-format msgid "The following health monitor could not be deleted: %s." msgstr "Le moniteur de santé suivant ne peut être supprimé: %s" #, python-format msgid "The following pool could not be deleted: %s." msgstr "Le pool suivant ne peut être supprimé: %s" msgid "The health check interval must be greater than or equal to the timeout." msgstr "" "Le diagnostic d'intégrité doit être supérieur ou égal au délai d'attente." msgid "The health monitor has been updated." msgstr "Le moniteur de santé a été mis à jour." msgid "The load balancer has been updated." msgstr "Le répartiteur de charge a été mis à jour." msgid "The max retry count must be a number between 1 and 10." msgstr "Le compteur max de tentatives doit être un nombre entre 1 et 10." msgid "The pool has been updated." msgstr "Le pool a été mis à jour." msgid "The pool members have been updated." msgstr "Les membres du pool ont été mis à jour." msgid "The port must be a number between 1 and 65535." msgstr "Le numéro de port doit être un nombre compris entre 1 et 65535." msgid "The timeout must be a number greater than or equal to 0." msgstr "Le délai d'attente dois être un nombre supérieur ou égal à 0." msgid "The weight must be a number between 1 and 256." msgstr "Le poids doit être un nombre compris entre 1 et 256" msgid "Timeout" msgstr "Délai d'attente" msgid "" "Timeout (sec)\n" " " msgstr "" "Délai d'attente (sec)\n" " " msgid "Type" msgstr "Type" msgid "URL Path" msgstr "Chemin d'URL" msgid "URL path" msgstr "Chemin d'URL" msgid "Unable to create health monitor." msgstr "Impossible de créer le moniteur de santé." msgid "Unable to create listener." msgstr "Impossible de créer le listener." msgid "Unable to create load balancer." msgstr "Impossible de créer le load balancer." msgid "Unable to create pool." msgstr "Impossible de créer le pool." msgid "Unable to delete health monitor." msgstr "Impossible de supprimer le moniteur de santé." msgid "Unable to delete listener." msgstr "Impossible de supprimer le listener." msgid "Unable to delete load balancer." msgstr "Impossible de supprimer le load balancer." msgid "Unable to delete pool." msgstr "Impossible de supprimer le pool." #, python-format msgid "Unable to disassociate floating IP address from load balancer: %s." msgstr "" "Impossible de dissocier les adresses IP flottantes du répartiteur de charge: " "%s." msgid "Unable to retrieve SSL certificates." msgstr "Impossible de récupérer les certificats SSL." msgid "Unable to retrieve health monitor." msgstr "Impossible de récupérer le moniteur de santé." msgid "Unable to retrieve listener." msgstr "impossible de récupérer le listener." msgid "Unable to retrieve listeners." msgstr "Impossible de récupérer les listeners." msgid "Unable to retrieve load balancer." msgstr "Impossible de récupérer le load balancer." msgid "Unable to retrieve load balancers." msgstr "Impossible de récupérer les load balancers." msgid "Unable to retrieve member." msgstr "Impossible de récupérer le membre." msgid "Unable to retrieve members." msgstr "Impossible de récupérer les membres." msgid "Unable to retrieve pool." msgstr "Impossible de récupérer le pool." msgid "Unable to retrieve secrets." msgstr "Impossible de récupérer les secrets." msgid "Unable to update health monitor." msgstr "Impossible de mettre à jour le moniteur de santé." msgid "Unable to update listener." msgstr "Impossible de mettre à jour le listener." msgid "Unable to update load balancer." msgstr "Impossible de mettre à jour le load balancer." msgid "Unable to update member list." msgstr "Impossible de mettre à jour la liste des membres." msgid "Unable to update member." msgstr "Impossible de mettre à jour le membre." msgid "Unable to update pool." msgstr "Impossible de mettre à jour le pool." msgid "Update" msgstr "Mettre à jour" msgid "Update Health Monitor" msgstr "Mettre à jour le moniteur de santé" msgid "Update Listener" msgstr "Mettre à jour le Listener" msgid "Update Load Balancer" msgstr "Mettre à jour le répartiteur de charge" msgid "Update Member Weight" msgstr "Mettre à jour le poids du membre" msgid "Update Pool" msgstr "Mettre à jour le pool" msgid "Update Weight" msgstr "Mettre à jour les poids" msgid "Weight" msgstr "Poids" msgid "" "Weight\n" " " msgstr "" "Poids\n" " " #, python-format msgid "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." msgstr "" "Vous êtes sur le point de dissocier l'adresse IP flottante de l'équilibreur " "de charge \"%s\". Veuillez confirmer." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." msgstr "" "Vous avez sélectionné \"%s\". Veuillez confirmer votre sélection. Les " "moniteurs de santé supprimés ne seront pas récupérable." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." msgstr "" "Vous avez sélectionné \"%s\". Veuillez confirmer votre sélection. Les " "répartiteurs de charge supprimés ne seront pas récupérable." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." msgstr "" "Vous avez sélectionné \"%s\". Veuillez confirmer votre sélection. Les pools " "supprimés ne sont pas récupérables." neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ru/0000775000175100017510000000000013245512321024764 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ru/LC_MESSAGES/0000775000175100017510000000000013245512321026551 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ru/LC_MESSAGES/django.po0000666000175100017510000000131013245511613030353 0ustar zuulzuul00000000000000# Artem , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01:36+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-19 02:32+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" msgid "Load Balancers" msgstr "Балансировщики нагрузки" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/ru/LC_MESSAGES/djangojs.po0000666000175100017510000007311213245511613030721 0ustar zuulzuul00000000000000# Aleksey Alekseenko <9118250541@mail.ru>, 2016. #zanata # Alexander , 2016. #zanata # Andrew , 2016. #zanata # Artem , 2016. #zanata # Artem , 2017. #zanata # Fedor Tarasenko , 2017. #zanata # Ivan Startsev , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 2.0.1.dev8\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-04-07 17:06+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-28 06:59+0000\n" "Last-Translator: Ivan Startsev \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 "%(ip)s..." msgstr "%(ip)s..." msgid "" "Expected status codes:\n" " The expected HTTP status codes to get from a successful health check. Must " "be a single number,\n" " a comma separated list of numbers, or a range (two numbers separated by a " "hyphen)." msgstr "" "Ожидаемый статус-код:\n" " Ожидаемый HTTP статус-код при успешной проверке работоспособности. Должен " "быть одним \n" "числом, списком чисел разделённых запятой или диапозоном(два чиста " "разделённых дефисом)." msgid "" "HTTP method:\n" " The HTTP method used to perform the health check." msgstr "" "HTTP метод:\n" " HTTP метод используется для проверки работоспособности." msgid "" "IP address:\n" " If an IP address is provided it must be a well-formed IPv4 or IPv6 " "address. The system will\n" " attempt to assign the provided IP address to the load balancer. If an IP " "address is not provided\n" " then one will be allocated for you." msgstr "" "IP адрес:\n" " Если предоставляется IP адрес, то он должен быть в формате IPv4 или IPv6. " "Система попытается\n" " назначить предоставленный IP адрес балансировщику нагрузки. Если IP адресс " "не предоставлен,\n" "тогда он будет выделен вам. " msgid "" "IP address:\n" " The IP address of the member to receive traffic from the load balancer. " "Must be a well-formed\n" " IPv4 or IPv6 address." msgstr "" "IP адрес:\n" " IP адрес участника для получение даннх от балансировщика нагрузки. Должен " "быть в формате \n" " IPv4 или IPv6." msgid "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgstr "" "Интервал:\n" " Интервал между проверками работоспособности. Должен быть не меньше времени " "ожидания." msgid "" "Method:\n" " The load balancer algorithm that distributes traffic to the pool members.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgstr "" "Алгоритм:\n" " Алгоритм балансировки, используемый для распределения трафика среди " "участников пула.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Направляет запросы инстансу с наименьшим " "количеством соединений.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Равномерно распределяет запросы между инстансами.\n" "
  • \n" "
  • \n" " SOURCE_IP: Запросы от одинаковых IP адресов последовательно " "направляются на один и тот же инстанс.\n" "
  • \n" "
" msgid "" "Port:\n" " The port on which the front end listens. Must be an integer from 1 to " "65535." msgstr "" "Порт:\n" " Порт который слушает фронтэнд. Должно быть числом от 1 до 65535." msgid "" "Port:\n" " The port on which the member listens for traffic. Must be a number from 1 " "to 65535." msgstr "" "Порт:\n" " Порт, через который участник пула ожидает трафик. Должен быть в диапазоне " "между 1 и 65535." msgid "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgstr "" "Повторы:\n" " Количество допустимых ошибок соединения перед изменением состояния " "участника на неактивное. Значение должно\n" " быть в диапазоне между 1 и 10." msgid "" "Subnet:\n" " The network on which to allocate the load balancer's IP address." msgstr "" "Подсеть:\n" " Сеть в которой выделяется IP адрес балансировщику нагрузки." msgid "" "Subnet:\n" " The network which contains the IP address of the member." msgstr "" "Подсеть:\n" " Сеть содержащая IP адрес участников." msgid "" "Weight:\n" " The weight of a member determines the portion of requests or connections " "it services compared\n" " to the other members of the pool. A higher weight means it will receive " "more traffic. Must be\n" " a number from 1 to 256." msgstr "" "Вес:\n" " Вес участника определяет долю обслуживаемых запросов или соединений по " "отношению к другим участникам пула.\n" " Больший вес означает, что участник пула получит больше трафика. Должен быть " "в диапазоне между 1 и 256." msgid "A new health monitor is being created." msgstr "Новый монитор работоспособности создается." msgid "A new listener is being created." msgstr "Новый получатель запросов создается." msgid "A new load balancer is being created." msgstr "Новый балансировщик нагрузки создается." msgid "A new pool is being created." msgstr "Новый пул создается." msgid "" "A pool represents a group of members over which the load balancing will be " "applied." msgstr "" "Пул представляет собой группу участников, среди которых распределяется " "нагрузка." msgid "Actions" msgstr "Действия" msgid "Active" msgstr "Активный" msgid "Add" msgstr "Добавить" msgid "Add external member" msgstr "Добавить внешнего участника" msgid "Add members to the load balancer pool." msgstr "Добавить участников в пул балансировщика нагрузки." msgid "Add/Remove Pool Members" msgstr "Добавить/Удалить участников пула" msgid "Address" msgstr "Адрес" msgid "Admin State Up" msgstr "Административное состояние UP" msgid "Allocated Members" msgstr "Выделенные участники" msgid "An error occurred. Please try again later." msgstr "Произошла ошибка. Повторите попытку." msgid "Associate" msgstr "Назначить" msgid "Associate Floating IP" msgstr "Связать назначаемый IP" msgid "Associate Floating IP Address" msgstr "Привязать назначаемый IP адрес" msgid "Associating floating IP with load balancer." msgstr "Связывание назначаемого IP с балансировщиком нагрузки." msgid "Available Instances" msgstr "Доступные инстансы" msgid "Cancel" msgstr "Отмена" msgid "Certificate Name" msgstr "Имя сертификата" msgid "Confirm Delete Health Monitor" msgstr "Подтвердите Удаление Монитора Работоспособности" msgid "Confirm Delete Listeners" msgstr "Подтвердите удаление получателей" msgid "Confirm Delete Load Balancers" msgstr "Подтвердите Удаление Балансировщиков Нагрузки" msgid "Confirm Delete Pool" msgstr "Подтвердите удаление пула" msgid "Confirm Disassociate Floating IP Address" msgstr "Подтвердите отвязку назначаемых IP адресов" msgid "Connection Limit" msgstr "Лимит соединений" msgid "Create Health Monitor" msgstr "Создать Монитор Работоспособности." msgid "Create Listener" msgstr "Создать Получателя" msgid "Create Load Balancer" msgstr "Создать Балансировщик Нагрузки" msgid "Create Pool" msgstr "Создать Пул" msgid "Default Pool ID" msgstr "ИД Пула по умолчанию" msgid "Degraded" msgstr "Деградировавший" msgid "Delay" msgstr "Задержка" msgid "Delete Health Monitor" msgstr "Удалить Монитор Работоспособности" msgid "Delete Listener" msgstr "Удалить получателя" msgid "Delete Listeners" msgstr "Удалить Получателей" msgid "Delete Load Balancer" msgstr "Удалить Балансировщик Нагрузки" msgid "Delete Load Balancers" msgstr "Удалить Балансировщики Нагрузки" msgid "Delete Pool" msgstr "Удалить пул" #, python-format msgid "Deleted health monitor: %s." msgstr "Удаленный монитор работоспособности: %s." #, python-format msgid "Deleted listeners: %s." msgstr "Удаленные получатели: %s." #, python-format msgid "Deleted load balancers: %s." msgstr "Удаленные балансировщики нагрузки: %s." #, python-format msgid "Deleted pool: %s." msgstr "Удален пул: %s." msgid "Description" msgstr "Описание" msgid "Disassociate" msgstr "Снять назначение" msgid "Disassociate Floating IP" msgstr "Отвязать Назначаемый IP" msgid "Edit" msgstr "Редактировать" msgid "Edit Pool" msgstr "Редактировать пул" msgid "Error" msgstr "Ошибка" msgid "Expected Codes" msgstr "Ожидаемые коды" msgid "Expected status codes" msgstr "Ожидаемые статус-коды" msgid "Expiration Date" msgstr "Дата окончания действия" msgid "Floating IP Address" msgstr "Нефиксированный IP Адресс" msgid "" "Floating IP address or pool\n" " " msgstr "" "Назначаемый IP адрес или пул\n" " " msgid "Floating IP addresses" msgstr "Назначаемые IP-адреса" msgid "Floating IP pools" msgstr "Пул назначаемых IP адресов" msgid "HTTP Method" msgstr "Метод HTTP" msgid "HTTP method" msgstr "Метод HTTP" msgid "Health Monitor ID" msgstr "ИД Монитора Работоспособности" msgid "ID" msgstr "ID" msgid "IP Address" msgstr "IP адрес" msgid "" "IP Address\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " msgstr "" "IP адрес\n" " 0\">\n" " \n" " \n" " Подсеть\n" " 0\">\n" " \n" " \n" " Порт\n" " 0\">\n" " \n" " Вес\n" " " #, python-format msgid "IP Addresses (%(count)s)" msgstr "IP адрес (%(count)s)" msgid "IP address" msgstr "IP адрес" msgid "" "If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL " "certificates must\n" " be selected. The first certificate will be the default." msgstr "" "Один или более SSL сертификат должны быть выбраны если слушатель использует " "TERMINATED_HTTPS протокол. Первый сертификат будет использоваться по " "умолчанию." msgid "" "Interval (sec)\n" " " msgstr "" "Интервал (сек)\n" " " msgid "Least Connections" msgstr "Меньше соединений" #, python-format msgid "Listener %(index)s" msgstr "Слушатель %(index)s" msgid "Listener 1" msgstr "Слушатель 1" msgid "Listener Details" msgstr "Информация о слушателе" msgid "Listener ID" msgstr "ИД получателя" msgid "Listeners" msgstr "Получатели" #, python-format msgid "Load Balancer %(index)s" msgstr "Балансировщика нагрузки %(index)s" msgid "Load Balancer Algorithm" msgstr "Алгоритм балансировки" msgid "Load Balancer Details" msgstr "Информация о балансировщике нагрузки" msgid "Load Balancer ID" msgstr "ИД балансировщика нагрузки" msgid "Load Balancers" msgstr "Балансировщики нагрузки" msgid "Loading" msgstr "Загрузка" msgid "Max Retries" msgstr "Максимальное количество повторных попыток" msgid "Member ID" msgstr "ИД Участника" msgid "Members" msgstr "Участники" msgid "" "Members are the actual IP addresses that will receive traffic from the load " "balancer. Each\n" " member must have a unique combination of IP address and port." msgstr "" "Участники - IP адреса, принимающие трафик от балансировщика нагрузки. IP " "адрес и порт каждого участника должны быть уникальны." msgid "" "Method\n" " " msgstr "" "Метод\n" " " msgid "Monitor Details" msgstr "Детали Монитора" msgid "Monitor ID" msgstr "ИД монитора" msgid "" "Monitor type\n" " " msgstr "" "Тип монитора\n" " " msgid "Name" msgstr "Имя" msgid "No available certificates" msgstr "Нет доступных сертификатов" msgid "No available instances" msgstr "Нет доступных инстансов" msgid "No items to display." msgstr "Нет элементов для отображения." msgid "No members have been allocated" msgstr "Участники не были выбраны" msgid "None" msgstr "Нет" msgid "Offline" msgstr "Вне сети" msgid "Online" msgstr "В сети" msgid "Operating Status" msgstr "Рабочий Статус" msgid "Overview" msgstr "Обзор" msgid "Pending Create" msgstr "Ожидает создание" msgid "Pending Delete" msgstr "Ожидает удаления" msgid "Pending Update" msgstr "Ожидает обновления" msgid "Pool 1" msgstr "Пул 1" msgid "Pool Details" msgstr "Информация о пуле" msgid "Pool ID" msgstr "ИД пула" msgid "Pool Members" msgstr "Участники пула" msgid "Pool member weight has been updated." msgstr "Весь элемента пула был изменен." msgid "Port" msgstr "Порт" msgid "" "Port\n" " " msgstr "" "Порт\n" " " msgid "Port ID" msgstr "ID порта" msgid "Protocol" msgstr "Протокол" msgid "" "Protocol\n" " " msgstr "" "Протокол\n" " " msgid "Protocol Port" msgstr "Порт протокола" msgid "Provide the details for the health monitor." msgstr "Предоставить детали для монитора состояния." msgid "Provide the details for the listener." msgstr "Предоставить детали для слушателя." msgid "Provide the details for the load balancer." msgstr "Предоставить детали для балансировщика нагрузки." msgid "Provide the details for the pool." msgstr "Предоставить детали для пула." msgid "Provider" msgstr "Провайдер" msgid "Provisioning Status" msgstr "Статус развертывания" msgid "Remove" msgstr "Удалить" msgid "" "Retries\n" " " msgstr "" "Повторные попытки\n" " " msgid "Round Robin" msgstr "Циклический" msgid "SSL Certificates" msgstr "SSL сертификаты" msgid "" "Select a floating IP address to associate with the load balancer or a " "floating IP pool in which to allocate a new floating IP address." msgstr "" "Выберите назначаемый IP адрес для балансировщика нагрузки или пул " "назначаемых IP адресов для выделения нового назначаемого IP адреса." msgid "Select certificates from the available certificates below" msgstr "Выберите сертификаты из числа доступных указанных ниже" msgid "Select one or more SSL certificates for the listener." msgstr "Выберите один или более SSL сертификатов для службы отчётов." msgid "Session Persistence" msgstr "Постоянство сессии" msgid "Source IP" msgstr "IP-адрес источника" msgid "" "Subnet\n" " " msgstr "" "Подсеть\n" " " msgid "Subnet ID" msgstr "ID подсети" msgid "Tenant ID" msgstr "ИД арендатора" msgid "The IP address is not valid." msgstr "IP адрес не действителен." msgid "The URL path is not valid." msgstr "URL не является действительным." msgid "The expected status code is not valid." msgstr "Ожидаемый код состояния невалиден." #, python-format msgid "The following health monitor could not be deleted: %s." msgstr "Следующий монитор работоспособности не может быть удален: %s." #, python-format msgid "" "The following listeners could not be deleted, possibly due to existing " "pools: %s." msgstr "" "Следующие получатели не могут быть удалены, возможно из за существующих " "пулов: %s." #, python-format msgid "The following listeners will not be deleted due to existing pools: %s." msgstr "Следующие получатели не будут удалены из за существующих пулов: %s." #, python-format msgid "The following load balancers are pending and cannot be deleted: %s." msgstr "" "Следующие балансировщики нагрузки в состоянии ожидания и не могут быть " "удалены: %s." #, python-format msgid "" "The following load balancers could not be deleted, possibly due to existing " "listeners: %s." msgstr "" "Следующие балансировщики нагрузки не могут быть удалены, возможно из за " "существующих получателей: %s." #, python-format msgid "The following pool could not be deleted: %s." msgstr "Данный пул не может быть удален: %s." msgid "The health check interval must be greater than or equal to the timeout." msgstr "" "Интервал проверки работоспособности должен быть не меньше времени ожидания." msgid "The health monitor has been updated." msgstr "Монитор работоспособности был обновлен." msgid "The listener has been updated." msgstr "Получатель был обновлен." msgid "The load balancer has been updated." msgstr "Балансировщик нагрузки был обновлен." msgid "" "The load balancer occupies a neutron network port and has an IP address " "assigned from a subnet." msgstr "" "Балансировщик нагрузки занимает порт в сети Neutron и имеет IP адрес, " "выделенный из подсети" msgid "The max retry count must be a number between 1 and 10." msgstr "Количество попыток должно быть в диапазон между 1 и 10." msgid "The pool has been updated." msgstr "Пул был обновлен." msgid "The pool members have been updated." msgstr "Элементы пула были изменены." msgid "The port must be a number between 1 and 65535." msgstr "Значение для порта должно быть в диапозоне между 1 и 65535." msgid "" "The port must be unique among all listeners attached to this load balancer." msgstr "" "Порт должен быть уникален среди приемников, присоединенных к балансировщику " "нагрузки." msgid "The timeout must be a number greater than or equal to 0." msgstr "Значение таймаута должно быть больше или рано 0." msgid "The weight must be a number between 1 and 256." msgstr "Значение веса должно быть в диапозоне между 1 и 256." msgid "" "The weight of a member determines the portion of requests or connections it " "services compared to the other members of the pool." msgstr "" "Вес участника определяет долю обслуживаемых запросов или соединений по " "отношению к другим участникам пула." msgid "Timeout" msgstr "Таймаут" msgid "" "Timeout (sec)\n" " " msgstr "" "Таймаут (сек)\n" " " msgid "Type" msgstr "Тип" msgid "URL Path" msgstr "Путь URL" msgid "URL path" msgstr "Путь URL" msgid "Unable to create health monitor." msgstr "Не удалось создать монитор работоспособности." msgid "Unable to create listener." msgstr "Не удалось создать получателя." msgid "Unable to create load balancer." msgstr "Не удалось создать балансировщик нагрузки." msgid "Unable to create pool." msgstr "Не удалось создать пул." msgid "Unable to delete health monitor." msgstr "Не удалось удалить монитор работоспособности." msgid "Unable to delete listener." msgstr "Не удалось удалить получателя." msgid "Unable to delete load balancer." msgstr "Не удалось удалить балансировщик нагрузки." msgid "Unable to delete pool." msgstr "Не удалось удалить пул." #, python-format msgid "Unable to disassociate floating IP address from load balancer: %s." msgstr "" "Не удаётся отвязать назначаемый IP адрес от балансировщика нагрузки: %s." msgid "Unable to retrieve SSL certificates." msgstr "Не удалось получить SSL сертификаты." msgid "Unable to retrieve health monitor." msgstr "Не удалось получить монитор работоспособности." msgid "Unable to retrieve listener." msgstr "Не удалось получить получателя." msgid "Unable to retrieve listeners." msgstr "Не удалось получить получателей." msgid "Unable to retrieve load balancer." msgstr "Не удалось получить данные балансировщика нагрузки." msgid "Unable to retrieve load balancers." msgstr "Не удалось получить список балансировщиков нагрузки." msgid "Unable to retrieve member." msgstr "Не удалось получить участника." msgid "Unable to retrieve members." msgstr "Не удалось получить участников." msgid "Unable to retrieve pool." msgstr "Не удалось получить пул." msgid "Unable to retrieve secrets." msgstr "Невозможно получить секретные ключи." msgid "Unable to update health monitor." msgstr "Не удалось обновить монитор работоспособности." msgid "Unable to update listener." msgstr "Не удалось обновить получателя." msgid "Unable to update load balancer." msgstr "Не удалось обновить балансировщик нагрузки." msgid "Unable to update member list." msgstr "Не удалось обновить список участников." msgid "Unable to update member." msgstr "Не удалось обновить участника." msgid "Unable to update pool." msgstr "Не удалось обновить пул." msgid "Update" msgstr "Обновить" msgid "Update Health Monitor" msgstr "Обновить Монитор Работоспособности" msgid "Update Listener" msgstr "Обновить получатель" msgid "Update Load Balancer" msgstr "Обновить Балансировщик Нагрузки" msgid "Update Member Weight" msgstr "Обновить весь участника" msgid "Update Pool" msgstr "Обновить пул" msgid "Update Weight" msgstr "Обновить вес" msgid "Weight" msgstr "Вес" msgid "" "Weight\n" " " msgstr "" "Вес\n" " " #, python-format msgid "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." msgstr "" "Вы собираетесь отвязать назначаемые IP адреса от балансировщика нагрузки \"%s" "\". Пожалуйста подтвердите." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." msgstr "" "Вы выбрали \"%s\". Пожалуйста подтвердите ваш выбор. Удаление монитора " "работоспособности необратимо." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted listeners " "are not recoverable." msgstr "" "Вы выбрали \"%s\". Пожалуйста подтвердите ваш выбор. Удаление получателей " "необратимо." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." msgstr "" "Вы выбрали \"%s\". Пожалуйста подтвердите ваш выбор. Удаление " "балансировщиков нагрузки необратимо." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." msgstr "" "Вы выбрали \"%s\". Пожалуйста подтвердите ваш выбор. Удаление пулов " "необратимо." neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/de/0000775000175100017510000000000013245512321024726 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/de/LC_MESSAGES/0000775000175100017510000000000013245512321026513 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/de/LC_MESSAGES/django.po0000666000175100017510000000114113245511613030317 0ustar zuulzuul00000000000000# Frank Kloeker , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.1.dev6\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-09-28 01: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-01-24 10:07+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 "Load Balancers" msgstr "Loadbalancer" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/de/LC_MESSAGES/djangojs.po0000666000175100017510000007055113245511613030667 0ustar zuulzuul00000000000000# Frank Kloeker , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard 3.0.0.0b4.dev3\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2017-08-11 03:11+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 08:06+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" #, python-format msgid "%(ip)s..." msgstr "%(ip)s..." msgid "" "Expected status codes:\n" " The expected HTTP status codes to get from a successful health check. Must " "be a single number,\n" " a comma separated list of numbers, or a range (two numbers separated by a " "hyphen)." msgstr "" "Erwartete Statuscodes:\n" " Die erwarteten Statuscodes zu empfangen von einem erfolgreichen " "Gesundheitscheck. Muss eine einzelne Nummer,\n" " eine kommaseparierte Liste von Nummern oder ein Bereich (zwei Zahlen, " "getrennt durch einen Bindestrich) sein." msgid "" "HTTP method:\n" " The HTTP method used to perform the health check." msgstr "" "HTTP Methode:\n" " Die HTTP Methode, mit der der Gesundheitscheck durchgeführt wird." msgid "" "IP address:\n" " If an IP address is provided it must be a well-formed IPv4 or IPv6 " "address. The system will\n" " attempt to assign the provided IP address to the load balancer. If an IP " "address is not provided\n" " then one will be allocated for you." msgstr "" "IP-Adresse:\n" " Wird eine IP-Adresse angegeben, so muss sie eine ordentlich formatierte " "IPv4 oder IPv6 Adresse sein. Das System wird\n" " versuchen, die bereitgestellte IP-Adresse dem Loadbalancer zuzuweisen. " "Wird keine IP-Adresse angegeben, wird eine für\n" " Sie reserviert." msgid "" "IP address:\n" " The IP address of the member to receive traffic from the load balancer. " "Must be a well-formed\n" " IPv4 or IPv6 address." msgstr "" "IP-Adresse:\n" " Die IP-Adresse eines Mitglieds empfängt Datenverkehr vom Loadbalancer. Es " "muss eine ordentlich formatierte\n" " IPv4 oder IPv6 Adresse sein." msgid "" "Interval:\n" " The interval between health checks. Must be greater than or equal to the " "timeout." msgstr "" "Intervall:\n" " Das Intervall zwischen Gesundheitschecks. Es muss größer oder gleich dem " "Zeitlimit sein." msgid "" "Method:\n" " The load balancer algorithm that distributes traffic to the pool members.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: Allocates requests to the instance with the least " "number of active\n" " connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Rotates requests evenly between multiple instances.\n" "
  • \n" "
  • \n" " SOURCE_IP: Requests from a unique source IP address are consistently " "directed to the same instance.\n" "
  • \n" "
" msgstr "" "Methode:\n" " Der Loadbalancer-Algorithmus, der den Datenverkehr an die Pool-Mitglieder " "verteilt.\n" "
    \n" "
  • \n" " LEAST_CONNECTIONS: verweise Anfragen an die Instanz mit der geringsten " "Anzahl von\n" " aktiven Verbindungen connections.\n" "
  • \n" "
  • \n" " ROUND_ROBIN: Zirkuliert Anfragen gleichmäßig zwischen multiplen " "Instanzen.\n" "
  • \n" "
  • \n" " SOURCE_IP: Anfragen einer bestimmten Quell-IP-Adresse werden beständig " "an die gleiche Instanz geleitet.\n" "
  • \n" "
" msgid "" "Port:\n" " The port on which the front end listens. Must be an integer from 1 to " "65535." msgstr "" "Port:\n" " Der Port, auf den das Frontend hört. Es muss eine Ganzzahl zwischen 1 und " "65535 sein." msgid "" "Port:\n" " The port on which the member listens for traffic. Must be a number from 1 " "to 65535." msgstr "" "Port:\n" " Der Port, auf dem das Mitglied auf Datenverkehr wartet. Es muss eine Zahl " "zwischen 1 und 65535 sein." msgid "" "Protocol:\n" " The protocol for which the front end listens. The TERMINATED_HTTPS " "protocol is only available if\n" " the key-manager service is enabled and you have authority to list " "certificate containers and\n" " secrets." msgstr "" "Protokoll:\n" " Das Protokoll, auf dass das Frontend hört. Das TERMINATED_HTTPS Protokoll " "ist nur verfügbar,\n" " wenn der Schlüsselmanager aktiviert ist und Sie die Berechtigung haben, " "Zertifikatcontainer\n" " und Secrets aufzulisten." msgid "" "Retries:\n" " The number of allowed connection failures before marking the member as " "inactive. Must be a\n" " number from 1 to 10." msgstr "" "Erneute Versuche:\n" " Die Anzahl der erlaubten Verbindungsfehler, bevor das Mitglied als inaktiv " "markiert wird.\n" " Es muss eine Zahl zwischen 1 und 10 sein." msgid "" "Subnet:\n" " The network on which to allocate the load balancer's IP address." msgstr "" "Subnetz:\n" " Das Netzwerk, aus welchem dem Loadbalancer eine IP-Adresse zugewiesen wird." msgid "" "Subnet:\n" " The network which contains the IP address of the member." msgstr "" "Subnetz:\n" " Das Netzwerk, welches die IP-Adresse des Mitgliedes enthält." msgid "" "Timeout:\n" " The time after which a health check times out. Must be a number greater " "than or equal to 0\n" " and less than or equal to the interval." msgstr "" "Zeitlimit:\n" " Die Zeit, nach der ein Gesundheitscheck abläuft.\n" " Es muss eine Zahl größer oder gleich 0 sein und kleiner oder gleich dem " "Intervall." msgid "" "URL path:\n" " The target of the health check HTTP request to the member. Must be a valid " "URL path." msgstr "" "URL Pfad:\n" " Das Ziel der Gesundheitscheck-HTTP-Anfrage an das Mitglied. Muss ein " "gültiger URL-Pfad sein." msgid "" "Weight:\n" " The weight of a member determines the portion of requests or connections " "it services compared\n" " to the other members of the pool. A higher weight means it will receive " "more traffic. Must be\n" " a number from 1 to 256." msgstr "" "Gewicht:\n" " Das Gewicht eines Mitgliedes bestimmt die Menge an Anfragen oder " "Verbindungen, die es bedient,\n" " verglichen mit den anderen Mitgliedern des Pools. Ein höheres Gewicht " "bedeutet es empfängt mehr\n" " Datenverkehr. Muss eine Zahl zwischen 1 und 256 sein." msgid "A new health monitor is being created." msgstr "Ein neuer Gesundheitsmonitor wurde erstellt." msgid "A new listener is being created." msgstr "Ein neuer Listener wird erstellt." msgid "A new load balancer is being created." msgstr "Ein neuer Loadbalancer wird erstellt." msgid "A new pool is being created." msgstr "Ein neuer Pool wird erstellt." msgid "" "A pool represents a group of members over which the load balancing will be " "applied." msgstr "" "Ein Pool repräsentiert eine Gruppe von Mitgliedern, auf die die " "Lastverteilung angewendet wird." msgid "Actions" msgstr "Aktionen" msgid "Active" msgstr "Aktiv" msgid "Add" msgstr "Hinzufügen" msgid "Add external member" msgstr "Externes Mitglied hinzufügen" msgid "Add members to the load balancer pool." msgstr "Mitglieder zum Loadbalancer-Pool hinzufügen." msgid "Add/Remove Pool Members" msgstr "Pool-Mitglieder hinzufügen/entfernen" msgid "Address" msgstr "Adresse" msgid "Admin State Up" msgstr "Adminstatus aktiv" msgid "Allocated Members" msgstr "Zugewiesene Mitglieder" msgid "An error occurred. Please try again later." msgstr "Ein Fehler ist aufgetreten. Bitte versuchen Sie es später noch einmal." msgid "Associate" msgstr "Zuweisen" msgid "Associate Floating IP" msgstr "Floating IP zuweisen" msgid "Associate Floating IP Address" msgstr "Floating-IP-Adresse zuweisen" msgid "Associating floating IP with load balancer." msgstr "Floating-IP mit Loadbalancer verbinden." msgid "Available Instances" msgstr "Verfügbare Instanzen" msgid "Back" msgstr "Zurück" msgid "Cancel" msgstr "Abbrechen" msgid "Certificate Name" msgstr "Zertifikatname" msgid "Confirm Delete Health Monitor" msgstr "Gesundheitsmonitor löschen bestätigen" msgid "Confirm Delete Listeners" msgstr "Listener löschen bestätigen" msgid "Confirm Delete Load Balancers" msgstr "Loadbalancer löschen bestätigen" msgid "Confirm Delete Pool" msgstr "Pool löschen bestätigen" msgid "Confirm Disassociate Floating IP Address" msgstr "Ablösung der Floating-IP-Adresse bestätigen" msgid "Connection Limit" msgstr "Verbindungsgrenze" msgid "Create Health Monitor" msgstr "Gesundheitsmonitor erzeugen" msgid "Create Listener" msgstr "Listener erstellen" msgid "Create Load Balancer" msgstr "Loadbalancer erstellen" msgid "Create Pool" msgstr "Pool erstellen" msgid "Default Pool ID" msgstr "Standard Pool-ID" msgid "Degraded" msgstr "Degradiert" msgid "Delay" msgstr "Verzögerung" msgid "Delete Health Monitor" msgstr "Gesundheitsmonitor löschen" msgid "Delete Listener" msgstr "Listener löschen" msgid "Delete Listeners" msgstr "Listener löschen" msgid "Delete Load Balancer" msgstr "Loadbalancer löschen" msgid "Delete Load Balancers" msgstr "Gelöschte Loadbalancer" msgid "Delete Pool" msgstr "Pool löschen" #, python-format msgid "Deleted health monitor: %s." msgstr "Gelöschter Gesundheitsmonitor: %s." #, python-format msgid "Deleted listeners: %s." msgstr "Gelöschte Listener: %s." #, python-format msgid "Deleted load balancers: %s." msgstr "Gelöschte Loadbalancer: %s." #, python-format msgid "Deleted pool: %s." msgstr "Gelöschter Pool: %s." msgid "Description" msgstr "Beschreibung" msgid "Disassociate" msgstr "Trennen" msgid "Disassociate Floating IP" msgstr "Floating IP trennen" #, python-format msgid "Disassociated floating IP address from load balancer: %s." msgstr "Verbindung der Floating-IP zum Loadbalancer lösen: %s." msgid "" "Each port that listens for traffic on a particular load balancer is " "configured separately and\n" " tied to the load balancer. Multiple listeners can be associated with the " "same load balancer but\n" " each must use a unique port." msgstr "" "Jeder Port, der an einem bestimmten Loadbalancer auf Datenverkehr wartet, " "wird separat konfiguriert und\n" " an den Loadbalancer gebunden. Multiple Listener können dem selben " "Loadbalancer zugewiesen werden aber\n" " jeder muss seinen einmaligen Port haben." msgid "Edit" msgstr "Bearbeiten" msgid "Edit Pool" msgstr "Pool bearbeiten" msgid "Error" msgstr "Fehler" msgid "Expected Codes" msgstr "Erwartete Codes" msgid "Expected status codes" msgstr "Erwartete Statuscodes" msgid "Expiration Date" msgstr "Ablaufdatum" msgid "Floating IP Address" msgstr "Floating IP-Adresse" msgid "" "Floating IP address or pool\n" " " msgstr "" "Floating-IP-Adresse oder Pool\n" " " msgid "Floating IP addresses" msgstr "Floating-IP-Adressen" msgid "Floating IP pools" msgstr "Floating-IP-Pools" msgid "HTTP Method" msgstr "HTTP-Methode" msgid "HTTP method" msgstr "HTTP-Methode" msgid "Health Monitor ID" msgstr "Gesundheitsmonitor-ID" msgid "ID" msgstr "ID" msgid "IP Address" msgstr "IP-Adresse" msgid "" "IP Address\n" " 0\">\n" " \n" " \n" " Subnet\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Weight\n" " " msgstr "" "IP Adresse\n" " 0\">\n" " \n" " \n" " Subnetz\n" " 0\">\n" " \n" " \n" " Port\n" " 0\">\n" " \n" " Gewicht\n" " " #, python-format msgid "IP Addresses (%(count)s)" msgstr "IP-Adressen (%(count)s)" msgid "IP address" msgstr "IP-Adresse" msgid "" "If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL " "certificates must\n" " be selected. The first certificate will be the default." msgstr "" "Wenn der Listener das TERMINATED_HTTPS Protokoll verwendet, müssen ein oder " "mehrere Zertifikate ausgewählt sein.\n" " Das erste Zertifikat wird der Standard." msgid "Inactive" msgstr "Inaktiv" msgid "" "Interval (sec)\n" " " msgstr "" "Intervall (Sek)\n" " " msgid "Least Connections" msgstr "Letzte Verbindungen" #, python-format msgid "Listener %(index)s" msgstr "Listener %(index)s" msgid "Listener 1" msgstr "Listener 1" msgid "Listener Details" msgstr "Listener Details" msgid "Listener ID" msgstr "Listener-ID" msgid "Listeners" msgstr "Listener" #, python-format msgid "Load Balancer %(index)s" msgstr "Loadbalancer %(index)s" msgid "Load Balancer Algorithm" msgstr "Loadbalancer-Algorithmus" msgid "Load Balancer Details" msgstr "Loadbalancer-Details" msgid "Load Balancer ID" msgstr "Loadbalancer-ID" msgid "Load Balancers" msgstr "Loadbalancer" msgid "Loading" msgstr "Ladevorgang" msgid "Max Retries" msgstr "Max Wiederholungen" msgid "Member ID" msgstr "Mitglied-ID" msgid "Members" msgstr "Mitglieder" msgid "" "Members are the actual IP addresses that will receive traffic from the load " "balancer. Each\n" " member must have a unique combination of IP address and port." msgstr "" "Mitglieder sind die aktuellen IP-Adressen, die Datenverkehr vom Loadbalancer " "empfangen. Jedes Mitglied\n" " muss eine einmalige Kombination aus IP-Adresse und Port haben." msgid "" "Method\n" " " msgstr "" "Methode\n" " " msgid "Monitor Details" msgstr "Monitordetails" msgid "Monitor ID" msgstr "Monitor-ID" msgid "" "Monitor type\n" " " msgstr "" "Monitortyp\n" " " msgid "Name" msgstr "Name" msgid "No available certificates" msgstr "Keine Zertifikate verfügbar" msgid "No available instances" msgstr "Keine Instanzen verfügbar" msgid "No items to display." msgstr "Keine Einträge zum Anzeigen." msgid "No members have been allocated" msgstr "Es wurden keine Mitglieder zugewiesen" msgid "None" msgstr "Keine" msgid "Offline" msgstr "Offline" msgid "Online" msgstr "Online" msgid "Operating Status" msgstr "Betriebsstatus" msgid "Overview" msgstr "Übersicht" msgid "Pending Create" msgstr "Geplante Erstellung" msgid "Pending Delete" msgstr "Geplante Löschung" msgid "Pending Update" msgstr "Geplante Aktualisierung" msgid "Pool 1" msgstr "Pool 1" msgid "Pool Details" msgstr "Pool-Details" msgid "Pool ID" msgstr "Pool-ID" msgid "Pool Members" msgstr "Pool-Mitglieder" msgid "Pool member weight has been updated." msgstr "Pool-Mitglied Gewicht wurde aktualisiert." msgid "Port" msgstr "Port" msgid "" "Port\n" " " msgstr "" "Port\n" " " msgid "Port ID" msgstr "Port-ID" msgid "Protocol" msgstr "Protokoll" msgid "" "Protocol\n" " " msgstr "" "Protokoll\n" " " msgid "Protocol Port" msgstr "Protokollport" msgid "Provide the details for the health monitor." msgstr "Geben Sie die Details zum Gesundheitsmonitor an." msgid "Provide the details for the listener." msgstr "Geben Sie die Details für den Listener an." msgid "Provide the details for the load balancer." msgstr "Geben Sie die Details zum Loadbalancer an." msgid "Provide the details for the pool." msgstr "Geben Sie die Details zum Pool an." msgid "Provider" msgstr "Anbieter" msgid "Provisioning Status" msgstr "Provisionierungsstatus" msgid "Remove" msgstr "Entfernen" msgid "" "Retries\n" " " msgstr "" "Anzahl Wiederholungen\n" " " msgid "Round Robin" msgstr "Rundlauf-Verfahren" msgid "SSL Certificates" msgstr "SSL-Zertifikate" msgid "" "Select a floating IP address to associate with the load balancer or a " "floating IP pool in which to allocate a new floating IP address." msgstr "" "Wählen Sie eine Floating-IP-Adresse, um sie dem Loadbalancer zuzuweisen, " "oder einen Floating-IP-Pool, in welchem eine Floating-IP-Adresse belegt " "werden kann." msgid "Select certificates from the available certificates below" msgstr "" "Wählen Sie Zertifikate aus den unten stehenden verfügbaren Zertifikaten aus" msgid "Select one or more SSL certificates for the listener." msgstr "Wählen Sie ein oder mehrere Zertifikate für den Listener." msgid "Session Persistence" msgstr "Sitzungspersistenz" msgid "Source IP" msgstr "Quell-IP" msgid "" "Subnet\n" " " msgstr "" "Subnetz\n" " " msgid "Subnet ID" msgstr "Subnetz-ID" msgid "Tenant ID" msgstr "Mandanten-ID" msgid "" "The Available Instances table contains existing compute instances that can " "be added as members\n" " of the pool. Use the \"Add external member\" button to add a member not " "found in the Available\n" " Instances table." msgstr "" "Die Tabelle Verfügbare Instanzen enthält existierende Compute Instanzen, die " "als Mitglieder des Pools hinzugefügt werden \n" "können. Verwenden Sie \"Externes Mitglied hinzufügen\", um ein Mitglied " "hinzuzufügen, dass sich nicht in der Tabelle \n" "befindet." msgid "The IP address is not valid." msgstr "Die IP-Adresse ist ungültig." msgid "The URL path is not valid." msgstr "Der URL-Pfad ist ungültig." msgid "The expected status code is not valid." msgstr "Der erwartete Statuscode ist ungültig." #, python-format msgid "The following health monitor could not be deleted: %s." msgstr "Die folgenden Gesundheitsmonitore konnten nicht gelöscht werden: %s" #, python-format msgid "" "The following listeners could not be deleted, possibly due to existing " "pools: %s." msgstr "" "Die folgenden Listener können nicht gelöscht werden, möglicherweise auf " "Grund der vorhandenen Pools: %s." #, python-format msgid "The following listeners will not be deleted due to existing pools: %s." msgstr "" "Die folgenden Listener werden auf Grund der vorhandenen Pools nicht " "gelöscht: %s." #, python-format msgid "The following load balancers are pending and cannot be deleted: %s." msgstr "" "Die folgenden Loadbalancer sind anhängig und können nicht gelöscht werden: " "%s." #, python-format msgid "" "The following load balancers could not be deleted, possibly due to existing " "listeners: %s." msgstr "" "Die folgenden Loadbalancer können nicht gelöscht werden, möglicherweise auf " "Grund der vorhandenen Listener: %s." #, python-format msgid "The following pool could not be deleted: %s." msgstr "Der folgende Pool konnte nicht gelöscht werden: %s" msgid "The health check interval must be greater than or equal to the timeout." msgstr "" "Das Gesundheitscheck-Intervall muss größer oder gleich dem Zeitlimit sein." msgid "The health monitor has been updated." msgstr "Der Gesundheitsmonitor wurde aktualisiert." msgid "" "The health monitor is used to determine the health of your pool members. " "Health checks\n" " routinely run against each member within the pool and the result of the " "health check is used\n" " to determine if the member receives new connections. Each pool can only " "have one health\n" " monitor." msgstr "" "Der Gesundheitsmonitor wird verwendet, um den Zustand Ihrer Pool-Mitglieder " "zu bestimmen. Gesundheitschecks\n" " laufen routinemäßig für alle Mitglieder im Pool und das Ergebnis\n" " wird verwendet um zu bestimmen, \n" "ob das Mitglied neue Verbindungen empfängt. Jeder Pool kann seinen eigenen " "Gesundheitsmonitor haben." msgid "The listener has been updated." msgstr "Der Listener wurde aktualisiert." msgid "The load balancer has been updated." msgstr "Der Loadbalancer wurde aktualisiert." msgid "" "The load balancer occupies a neutron network port and has an IP address " "assigned from a subnet." msgstr "" "Der Loadbalancer belegt einen Neutron-Port und bekommt eine IP-Adresse aus " "einem Subnetz zugewiesen." msgid "The max retry count must be a number between 1 and 10." msgstr "Die maximale Wiederholungszahl muss eine Zahl zwischen 1 und 10 sein." msgid "The pool has been updated." msgstr "Der Pool wurde aktualisiert." msgid "The pool members have been updated." msgstr "Die Pool-Mitglieder wurden aktualisiert." msgid "The port must be a number between 1 and 65535." msgstr "Der Port muss eine Zahl zwischen 1 und 65535 sein." msgid "" "The port must be unique among all listeners attached to this load balancer." msgstr "" "Der Port muss über alle Listener, die diesem Loadbalancer zugewiesen sind, " "einmalig sein. " msgid "The timeout must be a number greater than or equal to 0." msgstr "Das Zeitlimit muss eine Zahl größer oder gleich 0 sein." msgid "The weight must be a number between 1 and 256." msgstr "Das Gewicht muss eine Zahl zwischen 1 und 256 sein." msgid "" "The weight of a member determines the portion of requests or connections it " "services compared to the other members of the pool." msgstr "" "Das Gewicht eines Mitglieds bestimmt die Menge an Anfragen oder " "Verbindungen, die es bedient, verglichen mit den anderen Mitgliedern des " "Pools." msgid "Timeout" msgstr "Zeitlimit" msgid "" "Timeout (sec)\n" " " msgstr "" "Zeitlimit (Sek)\n" " " msgid "Type" msgstr "Typ" msgid "URL Path" msgstr "URL Pfad" msgid "URL path" msgstr "URL-Pfad" msgid "Unable to create health monitor." msgstr "Gesundheitsmonitor kann nicht erzeugt werden." msgid "Unable to create listener." msgstr "Listener kann nicht erstellt werden" msgid "Unable to create load balancer." msgstr "Loadbalancer kann nicht erstellt werden." msgid "Unable to create pool." msgstr "Pool kann nicht erzeugt werden." msgid "Unable to delete health monitor." msgstr "Gesundheitsmonitor kann nicht gelöscht werden." msgid "Unable to delete listener." msgstr "Listener kann nicht gelöscht werden." msgid "Unable to delete load balancer." msgstr "Loadbalancer kann nicht gelöscht werden." msgid "Unable to delete pool." msgstr "Pool kann nicht gelöscht werden." #, python-format msgid "Unable to disassociate floating IP address from load balancer: %s." msgstr "" "Verbindung der Floating-IP zum Loadbalancer kann nicht gelöst werden: %s." msgid "Unable to retrieve SSL certificates." msgstr "SSL-Zertifikate können nicht abgerufen werden." msgid "Unable to retrieve health monitor." msgstr "Gesundheitsmonitor kann nicht abgerufen werden." msgid "Unable to retrieve listener." msgstr "Listener kann nicht abgerufen werden." msgid "Unable to retrieve listeners." msgstr "Listener können nicht abgerufen werden." msgid "Unable to retrieve load balancer status tree." msgstr "Loadbalancer Statusbaum kann nicht abgerufen werden." msgid "Unable to retrieve load balancer." msgstr "Loadbalancer kann nicht abgerufen werden." msgid "Unable to retrieve load balancers." msgstr "Loadbalancer können nicht abgerufen werden." msgid "Unable to retrieve member." msgstr "Mitglied kann nicht abgerufen werden." msgid "Unable to retrieve members." msgstr "Mitglieder können nicht abgerufen werden." msgid "Unable to retrieve pool." msgstr "Pool kann nicht abgerufen werden." msgid "Unable to retrieve secrets." msgstr "Geheimdaten können nicht abgerufen werden." msgid "Unable to update health monitor." msgstr "Gesundheitsmonitor kann nicht aktualisiert werden." msgid "Unable to update listener." msgstr "Listener kann nicht aktualisiert werden." msgid "Unable to update load balancer." msgstr "Loadbalancer kann nicht aktualisiert werden." msgid "Unable to update member list." msgstr "Mitgliederliste kann nicht aktualisiert werden." msgid "Unable to update member." msgstr "Mitglied kann nicht aktualisiert werden." msgid "Unable to update pool." msgstr "Pool kann nicht aktualisiert werden." msgid "Update" msgstr "Aktualisieren" msgid "Update Health Monitor" msgstr "Gesundheitsmonitor aktualisieren" msgid "Update Listener" msgstr "Listener aktualisieren" msgid "Update Load Balancer" msgstr "Loadbalancer aktualisieren" msgid "Update Member Weight" msgstr "Mitglied-Gewicht aktualisieren" msgid "Update Pool" msgstr "Pool aktualisieren" msgid "Update Weight" msgstr "Gewicht aktualisieren" msgid "" "Use the key-manager service to create any certificate containers before " "creating the listener.\n" " The following documentation provides information on how to create a " "certificate container:\n" " " msgstr "" "Verwenden Sie den Key-Manager Dienst zum Erzeugen von Zertifikatcontainern, " "bevor Sie den Listener erstellen.\n" " Die folgende Dokumentation gibt Ihnen Informationen, wie man einen " "Zertifikatcontainer erstellt:\n" " " msgid "Weight" msgstr "Gewicht" msgid "" "Weight\n" " " msgstr "" "Gewicht\n" " " #, python-format msgid "" "You are about to disassociate the floating IP address from load balancer \"%s" "\". Please confirm." msgstr "" "Sie sind im Begriff, die Verbindung der Floating-IP-Adresse vom Loadbalancer " "%s zu lösen. Bitte bestätigen Sie." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted health " "monitors are not recoverable." msgstr "" "Sie haben \"%s\" ausgewählt. Bitte bestätigen Sie die Auswahl. Gelöschte " "Gesundheitsmonitore können nicht mehr hergestellt werden." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted listeners " "are not recoverable." msgstr "" "Sie haben \"%s\" ausgewählt. Bitte bestätigen Sie die Auswahl. Gelöschte " "Listener können nicht mehr hergestellt werden." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted load " "balancers are not recoverable." msgstr "" "Sie haben \"%s\" ausgewählt. Bitte bestätigen Sie die Auswahl. Gelöschte " "Loadbalancer können nicht mehr hergestellt werden." #, python-format msgid "" "You have selected \"%s\". Please confirm your selection. Deleted pools are " "not recoverable." msgstr "" "Sie haben \"%s\" ausgewählt. Bitte bestätigen Sie die Auswahl. Gelöschte " "Pools können nicht mehr hergestellt werden." neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/pt_BR/0000775000175100017510000000000013245512321025344 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/pt_BR/LC_MESSAGES/0000775000175100017510000000000013245512321027131 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/locale/pt_BR/LC_MESSAGES/django.po0000666000175100017510000000120613245511613030737 0ustar zuulzuul00000000000000# Rodrigo Loures , 2018. #zanata msgid "" msgstr "" "Project-Id-Version: neutron-lbaas-dashboard VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" "POT-Creation-Date: 2018-01-20 01:54+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-18 10:01+0000\n" "Last-Translator: Rodrigo Loures \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" msgid "Load Balancers" msgstr "Balanceadores de carga" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/0000775000175100017510000000000013245512321024241 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/0000775000175100017510000000000013245512321030006 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/0000775000175100017510000000000013245512321031105 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/project/0000775000175100017510000000000013245512321032553 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/project/__init__.pyneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/project/__init__0000666000175100017510000000000013245511613034230 0ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/0000775000175100017510000000000013245512321034244 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/loadbalancerspage.pyneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/0000666000175100017510000000155513245511613034261 0ustar zuulzuul00000000000000# 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.integration_tests.pages import basepage class LoadbalancersPage(basepage.BaseNavigationPage): TABLE_IMAGE_COLUMN = 'name' def __init__(self, driver, conf): super(LoadbalancersPage, self).__init__(driver, conf) self._page_title = "Load Balancers" ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/__init__.pyneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/0000666000175100017510000000000013245511613034241 0ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/pages/__init__.py0000666000175100017510000000000013245511613033211 0ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/__init__.py0000666000175100017510000000000013245511613032112 0ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/tests/0000775000175100017510000000000013245512321031150 5ustar zuulzuul00000000000000././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/tests/test_loadbalancers.pyneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/tests/test_loadbalance0000666000175100017510000000174313245511613034371 0ustar zuulzuul00000000000000# 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.integration_tests import helpers class TestLoadbalancers(helpers.TestCase): def setUp(self): super(TestLoadbalancers, self).setUp() self.home_pg.go_to_network_loadbalancerspage() def test_loadbalancers(self): self._save_screenshot(None) # TODO(MRV): Place holder for tests def tearDown(self): super(TestLoadbalancers, self).tearDown() neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/tests/__init__.py0000666000175100017510000000000013245511613033254 0ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/integration_tests/horizon.conf0000666000175100017510000000403313245511613032352 0ustar zuulzuul00000000000000# # Configuration filed based on Tempest's tempest.conf.sample # [dashboard] # Where the dashboard can be found (string value) dashboard_url=http://localhost/dashboard/ # Login page for the dashboard (string value) login_url=http://localhost/dashboard/auth/login/ # Dashboard help page url (string value) help_url=http://docs.openstack.org/ [selenium] # Timeout in seconds to wait for a page to become available # (integer value) page_timeout=30 # Output directory for screenshots. # (string value) screenshots_directory=integration_tests_screenshots # Implicit timeout to wait until element become available, # this timeout is used for every find_element, find_elements call. # (integer value) implicit_wait=10 # Explicit timeout is used for long lasting operations, # methods using explicit timeout are usually prefixed with 'wait', # those methods ignore implicit_wait when looking up web elements. # (integer value) explicit_wait=300 [image] # http accessible image (string value) http_image=http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-uec.tar.gz [identity] # Username to use for non-admin API requests. (string value) username=demo # API key to use when authenticating. (string value) password=secretadmin # Administrative Username to use for admin API requests. # (string value) admin_username=admin # API key to use when authenticating as admin. (string value) admin_password=secretadmin [scenario] # ssh username for image file (string value) ssh_user=cirros [launch_instances] #available zone to launch instances available_zone=nova #image_name to launch instances image_name=cirros-0.3.4-x86_64-uec (24.0 MB) [plugin] is_plugin=True plugin_page_path=neutron_lbaas_dashboard.tests.integration_tests.pages plugin_page_structure={ "Project": { "Network": { "-": [ "Load Balancers" ] } } } neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/test_neutron_lbaas_dashboard.py0000666000175100017510000000150013245511613032516 0ustar zuulzuul00000000000000# -*- 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. """ test_neutron_lbaas_dashboard ---------------------------------- Tests for `neutron_lbaas_dashboard` module. """ from neutron_lbaas_dashboard.tests import base class TestNeutron_lbaas_dashboard(base.TestCase): def test_something(self): pass neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/urls.py0000666000175100017510000000132613245511613025607 0ustar zuulzuul00000000000000# # 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 openstack_dashboard import urls as dashboard_urls urlpatterns = [ urls.url(r'', urls.include(dashboard_urls)) ] neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/settings.py0000666000175100017510000001226713245511613026470 0ustar zuulzuul00000000000000# # 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 importlib import os import six from horizon.test.settings import * # noqa from horizon.utils import secret_key from openstack_dashboard import exceptions DEBUG = True TEMPLATE_DEBUG = DEBUG TEST_DIR = os.path.dirname(os.path.abspath(__file__)) ROOT_PATH = os.path.abspath(os.path.join(TEST_DIR, "..")) MEDIA_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'media')) MEDIA_URL = '/media/' STATIC_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'static')) STATIC_URL = '/static/' SECRET_KEY = secret_key.generate_or_read_from_file( os.path.join(TEST_DIR, '.secret_key_store')) ROOT_URLCONF = 'neutron_lbaas_dashboard.tests.urls' TEMPLATE_DIRS = ( os.path.join(TEST_DIR, 'templates'), ) TEMPLATE_CONTEXT_PROCESSORS += ( 'openstack_dashboard.context_processors.openstack', ) INSTALLED_APPS = ( 'django.contrib.contenttypes', 'django.contrib.auth', 'django.contrib.sessions', 'django.contrib.staticfiles', 'django.contrib.messages', 'django.contrib.humanize', 'django_nose', 'openstack_auth', 'compressor', 'horizon', 'openstack_dashboard', 'openstack_dashboard.dashboards', ) AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',) SITE_BRANDING = 'OpenStack' HORIZON_CONFIG = { "password_validator": { "regex": '^.{8,18}$', "help_text": "Password must be between 8 and 18 characters." }, 'user_home': None, 'help_url': "http://docs.openstack.org", 'exceptions': {'recoverable': exceptions.RECOVERABLE, 'not_found': exceptions.NOT_FOUND, 'unauthorized': exceptions.UNAUTHORIZED}, 'angular_modules': [], 'js_files': [], } # Load the pluggable dashboard settings from openstack_dashboard.utils import settings dashboard_module_names = [ 'openstack_dashboard.enabled', 'openstack_dashboard.local.enabled', 'neutron_lbaas_dashboard.enabled', ] dashboard_modules = [] # All dashboards must be enabled for the namespace to get registered, which is # needed by the unit tests. for module_name in dashboard_module_names: module = importlib.import_module(module_name) dashboard_modules.append(module) for submodule in six.itervalues(settings.import_submodules(module)): if getattr(submodule, 'DISABLED', None): delattr(submodule, 'DISABLED') INSTALLED_APPS = list(INSTALLED_APPS) # Make sure it's mutable settings.update_dashboards(dashboard_modules, HORIZON_CONFIG, INSTALLED_APPS) # Set to True to allow users to upload images to glance via Horizon server. # When enabled, a file form field will appear on the create image form. # See documentation for deployment considerations. HORIZON_IMAGES_ALLOW_UPLOAD = True AVAILABLE_REGIONS = [ ('http://localhost/identity', 'local'), ('http://remote/identity', 'remote'), ] OPENSTACK_API_VERSIONS = { "identity": 3 } OPENSTACK_KEYSTONE_URL = "http://localhost/identity" OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_" OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'test_domain' OPENSTACK_KEYSTONE_BACKEND = { 'name': 'native', 'can_edit_user': True, 'can_edit_group': True, 'can_edit_project': True, 'can_edit_domain': True, 'can_edit_role': True } OPENSTACK_CINDER_FEATURES = { 'enable_backup': True, } OPENSTACK_NEUTRON_NETWORK = { 'enable_lb': False, 'enable_firewall': False, 'enable_vpn': False } OPENSTACK_HYPERVISOR_FEATURES = { 'can_set_mount_point': True, # NOTE: as of Grizzly this is not yet supported in Nova so enabling this # setting will not do anything useful 'can_encrypt_volumes': False } LOGGING['loggers']['openstack_dashboard'] = { 'handlers': ['test'], 'propagate': False, } LOGGING['loggers']['selenium'] = { 'handlers': ['test'], 'propagate': False, } LOGGING['loggers']['neutron_lbaas_dashboard'] = { 'handlers': ['test'], 'propagate': False, } SECURITY_GROUP_RULES = { 'all_tcp': { 'name': 'ALL TCP', 'ip_protocol': 'tcp', 'from_port': '1', 'to_port': '65535', }, 'http': { 'name': 'HTTP', 'ip_protocol': 'tcp', 'from_port': '80', 'to_port': '80', }, } NOSE_ARGS = ['--nocapture', '--nologcapture', '--cover-package=openstack_dashboard', '--cover-inclusive', '--all-modules'] POLICY_FILES_PATH = os.path.join(ROOT_PATH, "conf") POLICY_FILES = { 'identity': 'keystone_policy.json', 'compute': 'nova_policy.json' } # The openstack_auth.user.Token object isn't JSON-serializable ATM SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/base.py0000666000175100017510000000143213245511613025532 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # Copyright 2010-2011 OpenStack Foundation # 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. from oslotest import base class TestCase(base.BaseTestCase): """Test case base class for all unit tests.""" neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/tests/__init__.py0000666000175100017510000000000013245511613026345 0ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/karma.conf.js0000666000175100017510000001176513245511613025473 0ustar zuulzuul00000000000000/* * Copyright 2015 IBM Corp. * * 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. */ 'use strict'; var fs = require('fs'); var path = require('path'); module.exports = function (config) { // This tox venv is setup in the post-install npm step var toxPath = '../.tox/py27/lib/python2.7/site-packages/'; config.set({ preprocessors: { // Used to collect templates for preprocessing. // NOTE: the templates must also be listed in the files section below. './static/**/*.html': ['ng-html2js'], // Used to indicate files requiring coverage reports. './static/**/!(*.spec).js': ['coverage'], }, // Sets up module to process templates. ngHtml2JsPreprocessor: { prependPrefix: '/', moduleName: 'templates' }, basePath: './', // Contains both source and test files. files: [ /* * shim, partly stolen from /i18n/js/horizon/ * Contains expected items not provided elsewhere (dynamically by * Django or via jasmine template. */ '../test-shim.js', // from jasmine.html toxPath + 'xstatic/pkg/jquery/data/jquery.js', toxPath + 'xstatic/pkg/angular/data/angular.js', toxPath + 'xstatic/pkg/angular/data/angular-route.js', toxPath + 'xstatic/pkg/angular/data/angular-mocks.js', toxPath + 'xstatic/pkg/angular/data/angular-cookies.js', toxPath + 'xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js', toxPath + 'xstatic/pkg/angular_gettext/data/angular-gettext.js', toxPath + 'xstatic/pkg/angular_fileupload/data/ng-file-upload-all.js', toxPath + 'xstatic/pkg/angular/data/angular-sanitize.js', toxPath + 'xstatic/pkg/d3/data/d3.js', toxPath + 'xstatic/pkg/rickshaw/data/rickshaw.js', toxPath + 'xstatic/pkg/angular_smart_table/data/smart-table.js', toxPath + 'xstatic/pkg/angular_lrdragndrop/data/lrdragndrop.js', toxPath + 'xstatic/pkg/angular_schema_form/data/schema-form.js', toxPath + 'xstatic/pkg/spin/data/spin.js', toxPath + 'xstatic/pkg/spin/data/spin.jquery.js', // TODO: These should be mocked. toxPath + '/horizon/static/horizon/js/horizon.js', /** * Include framework source code from horizon that we need. * Otherwise, karma will not be able to find them when testing. * These files should be mocked in the foreseeable future. */ toxPath + 'horizon/static/framework/**/*.module.js', toxPath + 'horizon/static/framework/**/!(*.spec|*.mock).js', toxPath + 'openstack_dashboard/static/**/*.module.js', toxPath + 'openstack_dashboard/static/**/!(*.spec|*.mock).js', toxPath + 'openstack_dashboard/dashboards/**/static/**/*.module.js', toxPath + 'openstack_dashboard/dashboards/**/static/**/!(*.spec|*.mock).js', /** * First, list all the files that defines application's angular modules. * Those files have extension of `.module.js`. The order among them is * not significant. */ './static/**/*.module.js', /** * Followed by other JavaScript files that defines angular providers * on the modules defined in files listed above. And they are not mock * files or spec files defined below. The order among them is not * significant. */ './static/**/!(*.spec|*.mock).js', /** * Then, list files for mocks with `mock.js` extension. The order * among them should not be significant. */ toxPath + 'openstack_dashboard/static/**/*.mock.js', //'./static/**/*.mock.js', /** * Finally, list files for spec with `spec.js` extension. The order * among them should not be significant. */ './static/**/*.spec.js', /** * Angular external templates */ './static/**/*.html' ], autoWatch: true, frameworks: ['jasmine'], browsers: ['PhantomJS'], phantomjsLauncher: { // Have phantomjs exit if a ResourceError is encountered // (useful if karma exits without killing phantom) exitOnResourceError: true }, reporters: ['progress', 'coverage', 'threshold'], plugins: [ 'karma-phantomjs-launcher', 'karma-jasmine', 'karma-ng-html2js-preprocessor', 'karma-coverage', 'karma-threshold-reporter' ], coverageReporter: { type: 'html', dir: '../coverage-karma/' }, // Coverage threshold values. thresholdReporter: { statements: 100, branches: 100, functions: 100, lines: 100 } }); }; neutron-lbaas-dashboard-4.0.0/HACKING.rst0000666000175100017510000000025713245511613020043 0ustar zuulzuul00000000000000neutron-lbaas-dashboard Style Commandments =============================================== Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/ neutron-lbaas-dashboard-4.0.0/tox.ini0000666000175100017510000000377013245511613017563 0ustar zuulzuul00000000000000[tox] minversion = 1.6 envlist = py27,pep8,eslint,karma skipsdist = True [testenv] usedevelop = True install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} setenv = VIRTUAL_ENV={envdir} NOSE_WITH_OPENSTACK=1 NOSE_OPENSTACK_COLOR=1 NOSE_OPENSTACK_RED=0.05 NOSE_OPENSTACK_YELLOW=0.025 NOSE_OPENSTACK_SHOW_ELAPSED=1 CLIENT_NAME=neutron-lbaas-dashboard deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt whitelist_externals = npm bash commands = python manage.py test [testenv:pep8] commands = flake8 [testenv:venv] commands = {posargs} [testenv:py27integration] basepython = python2.7 setenv = {[testenv]setenv} INTEGRATION_TESTS=1 SELENIUM_HEADLESS=1 HORIZON_INTEGRATION_TESTS_CONFIG_FILE=neutron_lbaas_dashboard/tests/integration_tests/horizon.conf DJANGO_SETTINGS_MODULE=neutron_lbaas_dashboard.tests.settings commands = nosetests neutron_lbaas_dashboard/tests/integration_tests/tests {posargs} [testenv:cover] commands = python setup.py test --coverage --testr-args='{posargs}' [testenv:docs] whitelist_externals = rm deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/doc/requirements.txt commands = rm -rf doc/build sphinx-build -W -b html doc/source doc/build/html [testenv:debug] commands = oslo_debug_helper {posargs} [testenv:eslint] # npm must be installed on the system, for example # sudo apt-get install npm commands = npm install npm run lint [testenv:karma] # npm must be installed on the system, for example # sudo apt-get install npm commands = npm install npm test [flake8] # E123, E125 skipped as they are invalid PEP-8. show-source = True ignore = E123,E125 builtins = _ exclude=.venv,.git,.tox,.tmp,dist,doc,*lib/python*,*egg,build,node_modules neutron-lbaas-dashboard-4.0.0/.mailmap0000666000175100017510000000013113245511613017655 0ustar zuulzuul00000000000000# Format is: # # neutron-lbaas-dashboard-4.0.0/tools/0000775000175100017510000000000013245512321017374 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/tools/gate/0000775000175100017510000000000013245512321020314 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/tools/gate/integration/0000775000175100017510000000000013245512321022637 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/tools/gate/integration/post_test_hook.sh0000777000175100017510000000070513245511613026251 0ustar zuulzuul00000000000000#!/bin/bash # This script will be executed inside post_test_hook function in devstack gate set -x DIR=${BASH_SOURCE%/*} source $DIR/commons $@ set +e cd /opt/stack/new/neutron-lbaas-dashboard sudo -H -u stack tox -e py27integration retval=$? set -e if [ -d ${NEUTRON_LBAAS_DASHBOARD_SCREENSHOTS_DIR}/ ]; then cp -r ${NEUTRON_LBAAS_DASHBOARD_SCREENSHOTS_DIR}/ /home/jenkins/workspace/gate-neutron-lbaas-dashboard-dsvm-integration/ fi exit $retval neutron-lbaas-dashboard-4.0.0/tools/gate/integration/pre_test_hook.sh0000777000175100017510000000214613245511613026053 0ustar zuulzuul00000000000000#!/bin/bash # This script will be executed inside pre_test_hook function in devstack gate set -ex DIR=${BASH_SOURCE%/*} source $DIR/commons $@ # Enable LBaaS V2 Neutron plugin DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin neutron-lbaas https://git.openstack.org/openstack/neutron-lbaas" ENABLED_SERVICES+=",q-lbaasv2" DISABLED_SERVICES+="q-lbaas" # Enable default recommended implementation for LBaaS v2, Octavia ENABLED_SERVICES+=",octavia,o-cw,o-hk,o-hm,o-api" DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin octavia https://git.openstack.org/openstack/octavia" DEVSTACK_LOCAL_CONFIG+=$'\n'"[[post-config|/etc/octavia/octavia.conf]]" DEVSTACK_LOCAL_CONFIG+=$'\n'"[controller_worker]" DEVSTACK_LOCAL_CONFIG+=$'\n'"amphora_driver = amphora_noop_driver" DEVSTACK_LOCAL_CONFIG+=$'\n'"compute_driver = compute_noop_driver" DEVSTACK_LOCAL_CONFIG+=$'\n'"network_driver = network_noop_driver" # Enable LBaaS v2 Horizon plugin DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin neutron-lbaas-dashboard https://git.openstack.org/openstack/neutron-lbaas-dashboard" export DEVSTACK_LOCAL_CONFIG export ENABLED_SERVICES export DISABLED_SERVICES neutron-lbaas-dashboard-4.0.0/tools/gate/integration/commons0000666000175100017510000000032613245511613024243 0ustar zuulzuul00000000000000#!/bin/bash set -ex export NEUTRON_LBAAS_DASHBOARD_SCREENSHOTS_DIR=/opt/stack/new/neutron-lbaas-dashboard/.tox/py27integration/src/horizon/openstack_dashboard/test/integration_tests/integration_tests_screenshots neutron-lbaas-dashboard-4.0.0/tools/tox_install.sh0000777000175100017510000000730013245511613022300 0ustar zuulzuul00000000000000#!/usr/bin/env bash # Many of horizon's repos suffer from the problem of depending on horizon, # but it not existing on pypi. # This wrapper for tox's package installer will use the existing package # if it exists, else use zuul-cloner if that program exists, else grab it # from horizon master via a hard-coded URL. That last case should only # happen with devs running unit tests locally. # From the tox.ini config page: # install_command=ARGV # default: # pip install {opts} {packages} ZUUL_CLONER=/usr/zuul-env/bin/zuul-cloner BRANCH_NAME=master install_project() { local project=$1 local branch=${2:-$BRANCH_NAME} local PROJECT_DIR=$HOME/$project local ZUULV3_PROJECT_DIR=$HOME/src/git.openstack.org/openstack/$project set +e project_installed=$(echo "import $project" | python 2>/dev/null ; echo $?) set -e # The devstack based functional tests have project checked out in # $PROJECT_DIR on the test systems - with the change to test in it. # Use this directory if it exists, so that this script installs the # project version to test here. # Note that the functional tests use sudo to run tox and thus # variables used for zuul-cloner to check out the correct version are # lost. if [ -d "$ZUULV3_PROJECT_DIR" ]; then echo "FOUND $project code at $ZUULV3_PROJECT_DIR - using" $install_cmd -U $ZUULV3_PROJECT_DIR elif [ -d "$PROJECT_DIR" ]; then echo "FOUND $project code at $PROJECT_DIR - using" $install_cmd -U $PROJECT_DIR elif [ $project_installed -eq 0 ]; then echo "ALREADY INSTALLED" > /tmp/tox_install.txt location=$(python -c "import $project; print($project.__file__)") echo "ALREADY INSTALLED at $location" echo "$project already installed; using existing package" elif [ -x "$ZUUL_CLONER" ]; then echo "ZUUL CLONER" > /tmp/tox_install.txt # Make this relative to current working directory so that # git clean can remove it. We cannot remove the directory directly # since it is referenced after $install_cmd mkdir -p .tmp PROJECT_DIR=$(/bin/mktemp -d -p $(pwd)/.tmp) pushd $PROJECT_DIR $ZUUL_CLONER --cache-dir \ /opt/git \ --branch $branch \ http://git.openstack.org \ openstack/$project cd openstack/$project $install_cmd . popd else echo "PIP HARDCODE" > /tmp/tox_install.txt if [ -z "$PIP_LOCATION" ]; then PIP_LOCATION="git+https://git.openstack.org/openstack/$project@$branch#egg=$project" fi $install_cmd -U ${PIP_LOCATION} fi } # Client constraint file contains this client version pin that is in conflict # with installing the client from source. We should remove the version pin in # the constraints file before applying it for from-source installation. CONSTRAINTS_FILE="$1" shift 1 set -e set -x # NOTE(tonyb): Place this in the tox enviroment's log dir so it will get # published to logs.openstack.org for easy debugging. localfile="$VIRTUAL_ENV/log/upper-constraints.txt" if [[ "$CONSTRAINTS_FILE" != http* ]]; then CONSTRAINTS_FILE="file://$CONSTRAINTS_FILE" fi # NOTE(tonyb): need to add curl to bindep.txt if the project supports bindep curl "$CONSTRAINTS_FILE" --insecure --progress-bar --output "$localfile" pip install -c"$localfile" openstack-requirements # This is the main purpose of the script: Allow local installation of # the current repo. It is listed in constraints file and thus any # install will be constrained and we need to unconstrain it. edit-constraints "$localfile" -- "$CLIENT_NAME" install_cmd="pip install -c$localfile" install_project horizon $install_cmd -U $* exit $? neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard.egg-info/0000775000175100017510000000000013245512321024571 5ustar zuulzuul00000000000000neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard.egg-info/SOURCES.txt0000664000175100017510000004317513245512321026467 0ustar zuulzuul00000000000000.coveragerc .eslintrc .mailmap .testr.conf AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE README.rst babel-django.cfg babel-djangojs.cfg manage.py package.json requirements.txt setup.cfg setup.py test-requirements.txt tox.ini devstack/README.rst devstack/plugin.sh devstack/settings doc/requirements.txt doc/source/conf.py doc/source/contributing.rst doc/source/index.rst doc/source/installation.rst doc/source/readme.rst doc/source/reference.rst doc/source/usage.rst neutron_lbaas_dashboard/__init__.py neutron_lbaas_dashboard/karma.conf.js neutron_lbaas_dashboard/post_install.sh neutron_lbaas_dashboard.egg-info/PKG-INFO neutron_lbaas_dashboard.egg-info/SOURCES.txt neutron_lbaas_dashboard.egg-info/dependency_links.txt neutron_lbaas_dashboard.egg-info/not-zip-safe neutron_lbaas_dashboard.egg-info/pbr.json neutron_lbaas_dashboard.egg-info/requires.txt neutron_lbaas_dashboard.egg-info/top_level.txt neutron_lbaas_dashboard/api/__init__.py neutron_lbaas_dashboard/api/rest/__init__.py neutron_lbaas_dashboard/api/rest/barbican.py neutron_lbaas_dashboard/api/rest/lbaasv2.py neutron_lbaas_dashboard/dashboards/__init__.py neutron_lbaas_dashboard/dashboards/project/__init__.py neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/__init__.py neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/panel.py neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/urls.py neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/views.py neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ngloadbalancersv2/index.html neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.py neutron_lbaas_dashboard/enabled/__init__.py neutron_lbaas_dashboard/locale/de/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/de/LC_MESSAGES/djangojs.po neutron_lbaas_dashboard/locale/en_GB/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/en_GB/LC_MESSAGES/djangojs.po neutron_lbaas_dashboard/locale/fr/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/fr/LC_MESSAGES/djangojs.po neutron_lbaas_dashboard/locale/id/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/id/LC_MESSAGES/djangojs.po neutron_lbaas_dashboard/locale/ja/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/ja/LC_MESSAGES/djangojs.po neutron_lbaas_dashboard/locale/ko_KR/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/ko_KR/LC_MESSAGES/djangojs.po neutron_lbaas_dashboard/locale/pt_BR/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/ru/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/ru/LC_MESSAGES/djangojs.po neutron_lbaas_dashboard/locale/tr_TR/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/tr_TR/LC_MESSAGES/djangojs.po neutron_lbaas_dashboard/locale/zh_CN/LC_MESSAGES/django.po neutron_lbaas_dashboard/locale/zh_CN/LC_MESSAGES/djangojs.po neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican.service.js neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican.service.spec.js neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.js neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.scss neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/detail.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/detail.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/detail.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/healthmonitors.module.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/healthmonitors.module.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/row-actions.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/row-actions.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/create/create.action.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/create/create.action.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/create/wizard.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/create/wizard.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/edit/edit.action.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/edit/edit.action.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/edit/wizard.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/edit/wizard.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/detail.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/detail.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/detail.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/listeners.module.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/listeners.module.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/table.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/table.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/table.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/batch-actions.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/batch-actions.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/row-actions.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/row-actions.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/create/wizard.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/create/wizard.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/delete/delete.action.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/delete/delete.action.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/edit/wizard.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/listeners/actions/edit/wizard.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/row-actions.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/row-actions.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/associate-ip/modal.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/delete/delete.action.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/delete/delete.action.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/disassociate-ip/modal.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/disassociate-ip/modal.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/edit/wizard.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/edit/wizard.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detail.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detail.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detail.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/members.module.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/members.module.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/members.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/members.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/batch-actions.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/batch-actions.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/row-actions.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/row-actions.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/update-member-list.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/update-member-list.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/wizard.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/wizard.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/detail.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/detail.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/detail.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/pools.module.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/pools.module.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/row-actions.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/row-actions.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/create.action.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/create.action.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/edit/edit.action.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/edit/edit.action.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/edit/wizard.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/pools/actions/edit/wizard.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/util/validators/validate-unique.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/util/validators/validate-unique.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detail/detail-status.directive.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detail/detail-status.directive.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/detail/detail-status.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table/table-status.directive.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table/table-status.directive.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/widgets/table/table-status.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/modal.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/modal.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/workflow.service.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/workflow.service.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.help.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.help.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.help.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.help.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.controller.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.controller.spec.js neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.help.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.help.html neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.html neutron_lbaas_dashboard/tests/__init__.py neutron_lbaas_dashboard/tests/base.py neutron_lbaas_dashboard/tests/settings.py neutron_lbaas_dashboard/tests/test_neutron_lbaas_dashboard.py neutron_lbaas_dashboard/tests/urls.py neutron_lbaas_dashboard/tests/integration_tests/__init__.py neutron_lbaas_dashboard/tests/integration_tests/horizon.conf neutron_lbaas_dashboard/tests/integration_tests/pages/__init__.py neutron_lbaas_dashboard/tests/integration_tests/pages/project/__init__.py neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/__init__.py neutron_lbaas_dashboard/tests/integration_tests/pages/project/network/loadbalancerspage.py neutron_lbaas_dashboard/tests/integration_tests/tests/__init__.py neutron_lbaas_dashboard/tests/integration_tests/tests/test_loadbalancers.py releasenotes/notes/bp-horizon-lbaas-v2-ui-ba7e4c97a0460f85.yaml releasenotes/notes/neutron-lbaas-dashboard-deprecation-a3c910ababba8e78.yaml tools/tox_install.sh tools/gate/integration/commons tools/gate/integration/post_test_hook.sh tools/gate/integration/pre_test_hook.shneutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard.egg-info/dependency_links.txt0000664000175100017510000000000113245512316030643 0ustar zuulzuul00000000000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard.egg-info/not-zip-safe0000664000175100017510000000000113245512207027022 0ustar zuulzuul00000000000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard.egg-info/requires.txt0000664000175100017510000000014613245512316027176 0ustar zuulzuul00000000000000oslo.log>=3.36.0 pbr!=2.1.0,>=2.0.0 Babel!=2.4.0,>=2.3.4 python-barbicanclient!=4.5.0,!=4.5.1,>=4.0.0 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard.egg-info/pbr.json0000664000175100017510000000005613245512316026254 0ustar zuulzuul00000000000000{"git_version": "c56d3f3", "is_release": true}neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard.egg-info/top_level.txt0000664000175100017510000000003013245512316027320 0ustar zuulzuul00000000000000neutron_lbaas_dashboard neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard.egg-info/PKG-INFO0000664000175100017510000000570313245512316025677 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: neutron-lbaas-dashboard Version: 4.0.0 Summary: Horizon panels for Neutron LBaaS Home-page: http://docs.openstack.org/developer/neutron-lbaas-dashboard/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/badges/neutron-lbaas-dashboard.svg :target: https://governance.openstack.org/reference/tags/index.html .. Change things from this point on .. warning:: Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation ======================= neutron-lbaas-dashboard ======================= Horizon panels for Neutron LBaaS v2 * Free software: Apache license * Documentation: https://docs.openstack.org/neutron-lbaas-dashboard/latest/ * Source: https://git.openstack.org/cgit/openstack/neutron-lbaas-dashboard * Bugs: https://storyboard.openstack.org/#!/project/907 Features -------- * Please see neutron-lbaas repository Howto ----- 1. Package the neutron_lbaas_dashboard by running:: python setup.py sdist This will create a python egg in the dist folder, which can be used to install on the horizon machine or within horizon's python virtual environment. 2. Copy ``_1481_project_ng_loadbalancersv2_panel.py`` in ``neutron_lbaas_dashboard/enabled`` directory to ``openstack_dashboard/local/enabled``. 3. (Optional) Copy the policy file into horizon's policy files folder, and add this config ``POLICY_FILES``:: 'neutron_lbaas': 'neutron_lbaas_policy.json', 4. Django has a compressor feature that performs many enhancements for the delivery of static files. If the compressor feature is enabled in your environment (``COMPRESS_OFFLINE = True``), run the following commands:: $ ./manage.py collectstatic $ ./manage.py compress 5. Finally restart your web server to enable neutron-lbaas-dashboard in your Horizon:: $ sudo service apache2 restart Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 neutron-lbaas-dashboard-4.0.0/AUTHORS0000664000175100017510000000225013245512316017307 0ustar zuulzuul00000000000000Akihiro Motoki Akihiro Motoki Andreas Jaeger Corey Bryant Diana Whitten Dirk Mueller Doug Fish Doug Wiegley Elena Ezhova Erik Olof Gunnar Andersson Flavio Percoco Jacky Hu Justin Pomeroy Kyle Mestery Lucas Palm M V P Nitesh Mark Vanderwiel Matt Borland Michael Johnson Monty Taylor Praveen Yalagandula Rajiv Kumar Rob Cresswell Swapnil Kulkarni (coolsvap) Vivek Jain Zuul avnish coco-Gao <419546439@qq.com> howardlee leiyashuai lilintan qiaomin neutron-lbaas-dashboard-4.0.0/README.rst0000666000175100017510000000340113245511613017726 0ustar zuulzuul00000000000000======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/badges/neutron-lbaas-dashboard.svg :target: https://governance.openstack.org/reference/tags/index.html .. Change things from this point on .. warning:: Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation ======================= neutron-lbaas-dashboard ======================= Horizon panels for Neutron LBaaS v2 * Free software: Apache license * Documentation: https://docs.openstack.org/neutron-lbaas-dashboard/latest/ * Source: https://git.openstack.org/cgit/openstack/neutron-lbaas-dashboard * Bugs: https://storyboard.openstack.org/#!/project/907 Features -------- * Please see neutron-lbaas repository Howto ----- 1. Package the neutron_lbaas_dashboard by running:: python setup.py sdist This will create a python egg in the dist folder, which can be used to install on the horizon machine or within horizon's python virtual environment. 2. Copy ``_1481_project_ng_loadbalancersv2_panel.py`` in ``neutron_lbaas_dashboard/enabled`` directory to ``openstack_dashboard/local/enabled``. 3. (Optional) Copy the policy file into horizon's policy files folder, and add this config ``POLICY_FILES``:: 'neutron_lbaas': 'neutron_lbaas_policy.json', 4. Django has a compressor feature that performs many enhancements for the delivery of static files. If the compressor feature is enabled in your environment (``COMPRESS_OFFLINE = True``), run the following commands:: $ ./manage.py collectstatic $ ./manage.py compress 5. Finally restart your web server to enable neutron-lbaas-dashboard in your Horizon:: $ sudo service apache2 restart neutron-lbaas-dashboard-4.0.0/.coveragerc0000666000175100017510000000017713245511613020367 0ustar zuulzuul00000000000000[run] branch = True source = neutron_lbaas_dashboard omit = neutron_lbaas_dashboard/openstack/* [report] ignore_errors = True neutron-lbaas-dashboard-4.0.0/.eslintrc0000666000175100017510000000263413245511613020072 0ustar zuulzuul00000000000000# Set up globals globals: angular: false extends: openstack # Most environment options are not explicitly enabled or disabled, only # included here for completeness' sake. They are commented out, because the # global updates.py script would otherwise override them during a global # requirements synchronization. # # Individual projects should choose which platforms they deploy to. env: # browser global variables. browser: true # Adds all of the Jasmine testing global variables for version 1.3 and 2.0. jasmine: true # Enable eslint-plugin-angular plugins: - angular # Below we adjust rules specific to horizon's usage of openstack's linting # rules, and its own plugin inclusions. rules: ############################################################################# # Disabled Rules from eslint-config-openstack ############################################################################# valid-jsdoc: 1 brace-style: 1 no-extra-parens: 1 consistent-return: 1 callback-return: 1 guard-for-in: 1 block-scoped-var: 1 semi-spacing: 1 no-redeclare: 1 no-new: 1 ############################################################################# # Angular Plugin Customization ############################################################################# angular/controller-as-vm: - 1 - "ctrl" # Remove after migrating to angular 1.4 or later. angular/no-cookiestore: - 1 neutron-lbaas-dashboard-4.0.0/setup.cfg0000666000175100017510000000234313245512321020061 0ustar zuulzuul00000000000000[metadata] name = neutron-lbaas-dashboard summary = Horizon panels for Neutron LBaaS description-file = README.rst author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = http://docs.openstack.org/developer/neutron-lbaas-dashboard/ 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 [files] packages = neutron_lbaas_dashboard [build_sphinx] source-dir = doc/source build-dir = doc/build all_files = 1 [upload_sphinx] upload-dir = doc/build/html [pbr] autodoc_tree_index_modules = False autodoc_tree_excludes = setup.py neutron_lbaas_dashboard/tests neutron_lbaas_dashboard/enabled neutron_lbaas_dashboard/locale neutron_lbaas_dashboard/static neutron_lbaas_dashboard/post_install.sh neutron_lbaas_dashboard/karma.conf.js autodoc_index_modules = False warnerrors = True autodoc_exclude_modules = neutron_lbaas_dashboard.tests.* neutron_lbaas_dashboard.enabled.* api_doc_dir = contributor/modules [egg_info] tag_build = tag_date = 0 neutron-lbaas-dashboard-4.0.0/CONTRIBUTING.rst0000666000175100017510000000144313245511613020704 0ustar zuulzuul00000000000000 .. warning:: Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation If you would like to contribute to the development of OpenStack, you must follow the steps in this page: http://docs.openstack.org/infra/manual/developers.html If you already have a good understanding of how the system works and your OpenStack accounts are set up, you can skip to the development workflow section of this documentation to learn how changes to OpenStack should be submitted for review via the Gerrit tool: http://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://storyboard.openstack.org/#!/project/907 neutron-lbaas-dashboard-4.0.0/PKG-INFO0000664000175100017510000000570313245512321017336 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: neutron-lbaas-dashboard Version: 4.0.0 Summary: Horizon panels for Neutron LBaaS Home-page: http://docs.openstack.org/developer/neutron-lbaas-dashboard/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/badges/neutron-lbaas-dashboard.svg :target: https://governance.openstack.org/reference/tags/index.html .. Change things from this point on .. warning:: Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation ======================= neutron-lbaas-dashboard ======================= Horizon panels for Neutron LBaaS v2 * Free software: Apache license * Documentation: https://docs.openstack.org/neutron-lbaas-dashboard/latest/ * Source: https://git.openstack.org/cgit/openstack/neutron-lbaas-dashboard * Bugs: https://storyboard.openstack.org/#!/project/907 Features -------- * Please see neutron-lbaas repository Howto ----- 1. Package the neutron_lbaas_dashboard by running:: python setup.py sdist This will create a python egg in the dist folder, which can be used to install on the horizon machine or within horizon's python virtual environment. 2. Copy ``_1481_project_ng_loadbalancersv2_panel.py`` in ``neutron_lbaas_dashboard/enabled`` directory to ``openstack_dashboard/local/enabled``. 3. (Optional) Copy the policy file into horizon's policy files folder, and add this config ``POLICY_FILES``:: 'neutron_lbaas': 'neutron_lbaas_policy.json', 4. Django has a compressor feature that performs many enhancements for the delivery of static files. If the compressor feature is enabled in your environment (``COMPRESS_OFFLINE = True``), run the following commands:: $ ./manage.py collectstatic $ ./manage.py compress 5. Finally restart your web server to enable neutron-lbaas-dashboard in your Horizon:: $ sudo service apache2 restart Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 neutron-lbaas-dashboard-4.0.0/ChangeLog0000664000175100017510000001326613245512316020022 0ustar zuulzuul00000000000000CHANGES ======= 4.0.0 ----- * Mark neutron-lbaas-dashboard as deprecated * Updated from global requirements 4.0.0.0b3 --------- * Updated from global requirements * Imported Translations from Zanata * Updating for new sphinx docs jobs * Updated from global requirements * Fix the wrong urls in README.rst * Move user guide from horizon to LBaaS dashboard * Update gitignore * Make whitelist externals os agnostic * Imported Translations from Zanata * Use standard nodejs4 tests * Imported Translations from Zanata 4.0.0.0b2 --------- * Updated from global requirements * Move neutron-lbaas-dashboard zuulv3 config in repo 4.0.0.0b1 --------- * Set package.json version to 4.0.0.0b1 Queens MS1 * Imported Translations from Zanata * Updated from global requirements * Imported Translations from Zanata * Remove old unused code * Modify the '.gitignore' file 3.0.0 ----- * Imported Translations from Zanata * Imported Translations from Zanata * Updated from global requirements 3.0.0.0b3 --------- * Imported Translations from Zanata * Add loading and error status to detail pages * Show the member status properties * Move FIP api from network to neutron * Get rid of removed Django code * Make it work with devstack * Updated from global requirements * Exclude node\_modules from pep8 checking * Fix npm test * Imported Translations from Zanata 3.0.0.0b2 --------- * Updated from global requirements * Replace SortedDict with OrderedDict * Updated from global requirements * Updated from global requirements * Optimize the link address * Imported Translations from Zanata 3.0.0.0b1 --------- * Updated from global requirements * Fixes the installation documentation page * Updated from global requirements * Updated from global requirements * Imported Translations from Zanata * Fix bugs URL for project ownership change 2.0.0 ----- * Imported Translations from Zanata * Added link to modindex * Updated from global requirements * Imported Translations from Zanata * Allow hacking 0.12.x * Imported Translations from Zanata * Imported Translations from Zanata * Update for ui bootstrap changes * Imported Translations from Zanata * Add Constraints support * Imported Translations from Zanata * Imported Translations from Zanata * Show team and repo badges on README * Using horizon's templateview instead of generic one from django * Imported Translations from Zanata * Updated from global requirements * Using oslo\_log instead of logging * Imported Translations from Zanata * Updated from global requirements * Drop MANIFEST.in - it's not needed by pbr * modify the home-page info with the developer documentation * Translation preparation for neutron-lbaas-dashboard * Don't include openstack/common in flake8 exclude list * Remove unused logging * Subnet dropdown list has empty fields * Remove discover from test-requirements * Fix list\_loadbalancers function * LBaaS dashboard resepects OPENSTACK\_SSL settings * Updated from global requirements * Fix devstack plugin clean-up * Updated from global requirements * Make Barbican client respect OPENSTACK\_ENDPOINT\_TYPE * Update load balancer wizard help * Updated from global requirements * Updated from global requirements * Updated from global requirements * fix unit tests * Improve the technique for generating default resource names * Indicate table loading, error, and empty states 1.0.0 ----- * Move to post versioning * Add release note for LBaaS v2 dashboard work in Mitaka * Do not allow deleting a listener that has a default pool * Hide load balancers v2 panel if not enabled * Add the Angular LBaaS V2 'Update Member List' Table Action * Reload route after performing actions * Add trailing slash to all URLs calling the REST API * Fix gate scripts to use script dir for sourcing commons * Add action for updating pool member weight * Add edit health monitor action * Add create health monitor action * Add health monitor delete action * Add the Angular LBaaS V2 'Edit Pool' Workflow * Add the Angular LBaaS V2 'Create Pool' workflow * Add pool delete action * Handle missing key-manager service in workflow * Add listener delete actions * Add the Angular LBaaS V2 'Create Listener' workflow * Update styles to match latest horizon * Add associate and disassociate floating IP actions * Add delete load balancer actions * Make workflow enforce all required fields * Clean up create load balancer workflow * Add support for TERMINATED\_HTTPS protocol * Add the angular LBaaS V2 Edit Action for Listeners * Remove page header from pages on tabs * Adding integration test support * Update install instruction for LBaaS v2 dashboard * Use the horizon limit filter for connection limit * Add general load balancer service * Use static file auto-discovery * Update URL routing * Updated from global requirements * Support external members when creating load balancer * Add the angular LBaaS V2 health monitor detail page * Add the angular LBaaS V2 members table and detail pages * Add the angular LBaaS V2 pools detail page * Fix typo in enable file * Add angular LBaaS V2 Listeners table and detail pages * Add support for editing a load balancer * Make create load balancer workflow generic * Add monitor tab to create load balancer workflow * Update npm dependencies * Add members tab to create load balancer workflow * Add listener and pool to create load balancer workflow * Include javascript lint and unit test in tox * Add initial workflow for creating load balancer * devstack plugin for neutron-lbaas-dashboard * Add routing and load balancer detail page * Add angular Load Balancers V2 panel * Initial commit for horizon lbaas v2 dashboard * Make sure django env var is set * Add requirement for testing * Open Mitaka development * Change ignore-errors to ignore\_errors * Initial cookiecutter commit * Added .gitreview neutron-lbaas-dashboard-4.0.0/test-requirements.txt0000666000175100017510000000117713245511613022510 0ustar zuulzuul00000000000000# 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. 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 python-subunit>=1.0.0 # Apache-2.0/BSD nose-exclude>=0.3.0 # LGPL selenium>=2.50.1 # Apache-2.0 oslotest>=3.2.0 # Apache-2.0 testrepository>=0.0.18 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD testtools>=2.2.0 # MIT # This also needs xvfb library installed on your OS xvfbwrapper>=0.1.3 #license: MIT neutron-lbaas-dashboard-4.0.0/manage.py0000666000175100017510000000150613245511613020045 0ustar zuulzuul00000000000000#!/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 # noqa if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "openstack_dashboard.settings") execute_from_command_line(sys.argv) neutron-lbaas-dashboard-4.0.0/babel-django.cfg0000666000175100017510000000020513245511613021224 0ustar zuulzuul00000000000000[extractors] django = django_babel.extract:extract_django [python: **.py] [django: templates/**.html] [django: **/templates/**.csv] neutron-lbaas-dashboard-4.0.0/requirements.txt0000666000175100017510000000054613245511613021532 0ustar zuulzuul00000000000000# 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. oslo.log>=3.36.0 # Apache-2.0 pbr!=2.1.0,>=2.0.0 # Apache-2.0 Babel!=2.4.0,>=2.3.4 # BSD python-barbicanclient!=4.5.0,!=4.5.1,>=4.0.0 # Apache-2.0 neutron-lbaas-dashboard-4.0.0/setup.py0000666000175100017510000000200613245511613017751 0ustar zuulzuul00000000000000# 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) neutron-lbaas-dashboard-4.0.0/.testr.conf0000666000175100017510000000047713245511613020337 0ustar zuulzuul00000000000000[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=--list