From a1e2d1e1830c79144658c047157ce10abc59ae68 Mon Sep 17 00:00:00 2001 From: Kristine Bujold Date: Mon, 1 Apr 2019 15:39:10 -0400 Subject: [PATCH] Remove wrs-configutilities SDK Module Remove configutilities and move what is being used in other components to controllerconfig. Tested with a clean install on AIO-DX and running config_controller. With the StarlingX move to supporting pure upstream OpenStack, the majority of the SDK Modules are related to functionality no longer supported. The remaining SDK Modules will be moved to StarlingX documentation. Story: 2005275 Task: 30262 Change-Id: Ie496548dfc6efee677a501c98c227c586df0a7d6 Signed-off-by: Kristine Bujold --- .zuul.yaml | 26 - centos_iso_image.inc | 3 - centos_pike_wheels.inc | 1 - centos_pkg_dirs | 1 - centos_stable_wheels.inc | 1 - configutilities/.gitignore | 6 - configutilities/PKG-INFO | 13 - configutilities/centos/build_srpm.data | 3 - configutilities/centos/configutilities.spec | 78 - configutilities/configutilities/LICENSE | 202 --- .../configutilities/configutilities/LICENSE | 202 --- .../configutilities/configutilities/README | 76 - .../configutilities/__init__.py | 35 - .../configutilities/common/__init__.py | 5 - .../configutilities/common/exceptions.py | 25 - .../configutilities/common/guicomponents.py | 295 ---- .../configutilities/common/utils.py | 367 ---- .../configutilities/common/wrs_ico.py | 37 - .../configutilities/config_validator.py | 103 -- .../configutilities/configfiletool.py | 1495 ----------------- .../configutilities/configgui.py | 114 -- .../configutilities/hostfiletool.py | 515 ------ .../configutilities/configutilities/setup.py | 30 - configutilities/configutilities/favicon.ico | Bin 32988 -> 0 bytes configutilities/configutilities/pylint.rc | 233 --- configutilities/configutilities/setup.py | 27 - .../configutilities/test-requirements.txt | 4 - configutilities/configutilities/tox.ini | 46 - controllerconfig/centos/build_srpm.data | 2 +- .../controllerconfig/__init__.py | 31 +- .../controllerconfig}/common/configobjects.py | 16 +- .../controllerconfig}/common/crypt.py | 20 +- .../controllerconfig/common/dcmanager.py | 4 +- .../controllerconfig/common/exceptions.py | 23 +- .../controllerconfig}/common/validator.py | 50 +- .../controllerconfig/config_management.py | 20 +- .../controllerconfig/configassistant.py | 28 +- .../controllerconfig/regionconfig.py | 39 +- .../controllerconfig/systemconfig.py | 22 +- .../tests/test_region_config.py | 8 +- .../tests/test_system_config.py | 8 +- .../controllerconfig/upgrades/utils.py | 4 +- .../controllerconfig/utils.py | 353 +++- controllerconfig/controllerconfig/tox.ini | 1 - devstack/lib/stx-config | 14 +- sysinv/sysinv/centos/build_srpm.data | 2 +- .../sysinv/sysinv/api/controllers/v1/host.py | 5 +- sysinv/sysinv/sysinv/tox.ini | 1 - 48 files changed, 504 insertions(+), 4090 deletions(-) delete mode 100644 configutilities/.gitignore delete mode 100755 configutilities/PKG-INFO delete mode 100755 configutilities/centos/build_srpm.data delete mode 100755 configutilities/centos/configutilities.spec delete mode 100755 configutilities/configutilities/LICENSE delete mode 100755 configutilities/configutilities/configutilities/LICENSE delete mode 100755 configutilities/configutilities/configutilities/README delete mode 100755 configutilities/configutilities/configutilities/__init__.py delete mode 100644 configutilities/configutilities/configutilities/common/__init__.py delete mode 100644 configutilities/configutilities/configutilities/common/exceptions.py delete mode 100755 configutilities/configutilities/configutilities/common/guicomponents.py delete mode 100644 configutilities/configutilities/configutilities/common/utils.py delete mode 100755 configutilities/configutilities/configutilities/common/wrs_ico.py delete mode 100755 configutilities/configutilities/configutilities/config_validator.py delete mode 100755 configutilities/configutilities/configutilities/configfiletool.py delete mode 100755 configutilities/configutilities/configutilities/configgui.py delete mode 100755 configutilities/configutilities/configutilities/hostfiletool.py delete mode 100755 configutilities/configutilities/configutilities/setup.py delete mode 100755 configutilities/configutilities/favicon.ico delete mode 100755 configutilities/configutilities/pylint.rc delete mode 100755 configutilities/configutilities/setup.py delete mode 100644 configutilities/configutilities/test-requirements.txt delete mode 100644 configutilities/configutilities/tox.ini rename {configutilities/configutilities/configutilities => controllerconfig/controllerconfig/controllerconfig}/common/configobjects.py (96%) rename {configutilities/configutilities/configutilities => controllerconfig/controllerconfig/controllerconfig}/common/crypt.py (92%) rename {configutilities/configutilities/configutilities => controllerconfig/controllerconfig/controllerconfig}/common/validator.py (97%) diff --git a/.zuul.yaml b/.zuul.yaml index b1e8dfddb2..c86da4d099 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -15,8 +15,6 @@ - controllerconfig-tox-flake8 - controllerconfig-tox-py27 - controllerconfig-tox-pylint - - configutilities-tox-flake8 - - configutilities-tox-pylint - cgtsclient-tox-py27 - cgtsclient-tox-pep8 - cgtsclient-tox-pylint @@ -35,8 +33,6 @@ - controllerconfig-tox-flake8 - controllerconfig-tox-py27 - controllerconfig-tox-pylint - - configutilities-tox-flake8 - - configutilities-tox-pylint - cgtsclient-tox-py27 - cgtsclient-tox-pep8 - cgtsclient-tox-pylint @@ -142,28 +138,6 @@ tox_envlist: pylint tox_extra_args: -c controllerconfig/controllerconfig/tox.ini -- job: - name: configutilities-tox-flake8 - parent: tox - description: Run flake8 tests for configutilities - files: - - configutilities/* - vars: - tox_envlist: flake8 - tox_extra_args: -c configutilities/configutilities/tox.ini - -- job: - name: configutilities-tox-pylint - parent: tox - description: Run pylint tests for configutilities - required-projects: - - openstack/stx-update - files: - - configutilities/* - vars: - tox_envlist: pylint - tox_extra_args: -c configutilities/configutilities/tox.ini - - job: name: flock-devstack-config parent: flock-devstack-base diff --git a/centos_iso_image.inc b/centos_iso_image.inc index cbf86b0f48..dcbd2a2b6a 100644 --- a/centos_iso_image.inc +++ b/centos_iso_image.inc @@ -10,9 +10,6 @@ workerconfig workerconfig-standalone workerconfig-subfunction -# configutilities -configutilities - # controllerconfig controllerconfig diff --git a/centos_pike_wheels.inc b/centos_pike_wheels.inc index e3e0c0b29c..e5bc269940 100644 --- a/centos_pike_wheels.inc +++ b/centos_pike_wheels.inc @@ -1,4 +1,3 @@ cgts-client-wheels -configutilities-wheels controllerconfig-wheels sysinv-wheels diff --git a/centos_pkg_dirs b/centos_pkg_dirs index 58b9cf7978..20467f16b3 100644 --- a/centos_pkg_dirs +++ b/centos_pkg_dirs @@ -1,7 +1,6 @@ kubernetes/applications/stx-openstack/stx-openstack-helm worker-utils workerconfig -configutilities controllerconfig storageconfig sysinv/cgts-client diff --git a/centos_stable_wheels.inc b/centos_stable_wheels.inc index e3e0c0b29c..e5bc269940 100644 --- a/centos_stable_wheels.inc +++ b/centos_stable_wheels.inc @@ -1,4 +1,3 @@ cgts-client-wheels -configutilities-wheels controllerconfig-wheels sysinv-wheels diff --git a/configutilities/.gitignore b/configutilities/.gitignore deleted file mode 100644 index ad7061c2ea..0000000000 --- a/configutilities/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -!.distro -.distro/centos7/rpmbuild/RPMS -.distro/centos7/rpmbuild/SRPMS -.distro/centos7/rpmbuild/BUILD -.distro/centos7/rpmbuild/BUILDROOT -.distro/centos7/rpmbuild/SOURCES/configutilities*tar.gz diff --git a/configutilities/PKG-INFO b/configutilities/PKG-INFO deleted file mode 100755 index 04153f1838..0000000000 --- a/configutilities/PKG-INFO +++ /dev/null @@ -1,13 +0,0 @@ -Metadata-Version: 1.1 -Name: configutilities -Version: 1.2.0 -Summary: Titanium Cloud configuration utilities -Home-page: -Author: Windriver -Author-email: info@windriver.com -License: Apache-2.0 - -Description: Titanium Cloud configuration utilities - - -Platform: UNKNOWN diff --git a/configutilities/centos/build_srpm.data b/configutilities/centos/build_srpm.data deleted file mode 100755 index 262bcfec5b..0000000000 --- a/configutilities/centos/build_srpm.data +++ /dev/null @@ -1,3 +0,0 @@ -SRC_DIR="configutilities" -COPY_LIST="$SRC_DIR/LICENSE" -TIS_PATCH_VER=2 diff --git a/configutilities/centos/configutilities.spec b/configutilities/centos/configutilities.spec deleted file mode 100755 index 3a7269af3d..0000000000 --- a/configutilities/centos/configutilities.spec +++ /dev/null @@ -1,78 +0,0 @@ -Summary: configutilities -Name: configutilities -Version: 3.1.0 -Release: %{tis_patch_ver}%{?_tis_dist} -License: Apache-2.0 -Group: base -Packager: Wind River -URL: unknown -Source0: %{name}-%{version}.tar.gz -Source1: LICENSE - -%define debug_package %{nil} - -BuildRequires: python-setuptools -BuildRequires: python2-pip -BuildRequires: python2-wheel -Requires: python-netaddr -#Requires: wxPython - -%description -Titanium Cloud Controller configuration utilities - -%package -n %{name}-cgts-sdk -Summary: configutilities sdk files -Group: devel - -%description -n %{name}-cgts-sdk -SDK files for configutilities - -%define local_bindir /usr/bin -%define pythonroot /usr/lib64/python2.7/site-packages -%define cgcs_sdk_deploy_dir /opt/deploy/cgcs_sdk -%define cgcs_sdk_tarball_name wrs-%{name}-%{version}.tgz - -%prep -%setup - -%build -%{__python} setup.py build -%py2_build_wheel - -%install -%{__python} setup.py install --root=$RPM_BUILD_ROOT \ - --install-lib=%{pythonroot} \ - --prefix=/usr \ - --install-data=/usr/share \ - --single-version-externally-managed -mkdir -p $RPM_BUILD_ROOT/wheels -install -m 644 dist/*.whl $RPM_BUILD_ROOT/wheels/ - -sed -i "s#xxxSW_VERSIONxxx#%{platform_release}#" %{name}/common/validator.py -tar czf %{cgcs_sdk_tarball_name} %{name} -mkdir -p $RPM_BUILD_ROOT%{cgcs_sdk_deploy_dir} -install -m 644 %{cgcs_sdk_tarball_name} $RPM_BUILD_ROOT%{cgcs_sdk_deploy_dir} - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root,-) -%doc LICENSE -%{local_bindir}/* -%dir %{pythonroot}/%{name} -%{pythonroot}/%{name}/* -%dir %{pythonroot}/%{name}-%{version}-py2.7.egg-info -%{pythonroot}/%{name}-%{version}-py2.7.egg-info/* - -%files -n %{name}-cgts-sdk -%{cgcs_sdk_deploy_dir}/%{cgcs_sdk_tarball_name} - -%package wheels -Summary: %{name} wheels - -%description wheels -Contains python wheels for %{name} - -%files wheels -/wheels/* diff --git a/configutilities/configutilities/LICENSE b/configutilities/configutilities/LICENSE deleted file mode 100755 index d645695673..0000000000 --- a/configutilities/configutilities/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - 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. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/configutilities/configutilities/configutilities/LICENSE b/configutilities/configutilities/configutilities/LICENSE deleted file mode 100755 index d645695673..0000000000 --- a/configutilities/configutilities/configutilities/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - 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. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/configutilities/configutilities/configutilities/README b/configutilities/configutilities/configutilities/README deleted file mode 100755 index 4d36291e0b..0000000000 --- a/configutilities/configutilities/configutilities/README +++ /dev/null @@ -1,76 +0,0 @@ -Copyright © 2017 Wind River Systems, Inc. - -SPDX-License-Identifier: Apache-2.0 ------------------------------------------------------------------------ - - -Titanium Cloud Configuration Utilities ---------------------------------------- - -To facilitate various aspects of Titanium Cloud installation and -configuration, utilities have been created to generate and validate -configuration and setup files which are utilized by the system. - - -Installing the Configuration Utilities --------------------------------------- - -This tarball includes several utilities which can be used to aid in the -configuration of Titanium Cloud. Note that these are optional tools which are run prior -to installation, and not run on the target system. - -To install the utilities on a Linux machine follow these steps: - -1. Ensure you have the tools necessary to install new python packages (pip and setuptools) - If you do not, you must install them using the appropriate commands for - your version of linux, such as: - sudo apt-get install python-pip # e.g. for Ubuntu or Debian - -2. The config_gui tool makes use of external tools which must be - installed as follows: - - if using Ubuntu/Debian: - sudo apt-get install python-wxtools - - if using Fedora: - sudo yum install wxPython python-setuptools - - if using CentOS/RedHat, the appropriate rpm can be obtained from EPEL - sudo yum install epel-release - sudo yum install wxPython - - Note, if epel-release is not available, it can be obtained as such (specific to - your version) - wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm - sudo rpm -Uvh epel-release-6*.rpm - sudo yum install wxPython python-pip - -3. Copy wrs-configutilities-3.1.0.tgz to the python install directory - (i.e. /usr/lib/python2.7/dist-packages or /usr/lib/python2.7/site-packages) - -4. Cd to this python install directory - -5. Untar the file: - sudo tar xfv wrs-configutilities-3.1.0.tgz - -6. Cd configutilities - -7. Run setup: - sudo python setup.py install - - -Using the Configuration Utilities ---------------------------------- - -There are two tools installed: config_validator and config_gui. - -config_validator is a commandline tool which takes a 'controller configuration -input' file of the INI type and does preliminary analysis to ensure its validity. -It can be called as follows: - config_validator --system-config - -config_gui is a GUI-based tool which provides tools for creating a 'controller -configuration input' INI file and/or a 'bulk host' XML file. It can be launched -by calling 'config_gui' from the command line and will walk you through the process -of generating the desired configuration files. - diff --git a/configutilities/configutilities/configutilities/__init__.py b/configutilities/configutilities/configutilities/__init__.py deleted file mode 100755 index a694fc1a6c..0000000000 --- a/configutilities/configutilities/configutilities/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright (c) 2015-2016 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -# - -from configutilities.common.validator import validate # noqa: F401 -from configutilities.common.configobjects import Network # noqa: F401 -from configutilities.common.configobjects import DEFAULT_CONFIG # noqa: F401 -from configutilities.common.configobjects import REGION_CONFIG # noqa: F401 -from configutilities.common.configobjects import DEFAULT_NAMES # noqa: F401 -from configutilities.common.configobjects import HP_NAMES # noqa: F401 -from configutilities.common.configobjects import SUBCLOUD_CONFIG # noqa: F401 -from configutilities.common.configobjects import MGMT_TYPE # noqa: F401 -from configutilities.common.configobjects import INFRA_TYPE # noqa: F401 -from configutilities.common.configobjects import OAM_TYPE # noqa: F401 -from configutilities.common.configobjects import NETWORK_PREFIX_NAMES # noqa: F401 -from configutilities.common.configobjects import HOST_XML_ATTRIBUTES # noqa: F401 -from configutilities.common.configobjects import DEFAULT_DOMAIN_NAME # noqa: F401 -from configutilities.common.exceptions import ConfigError # noqa: F401 -from configutilities.common.exceptions import ConfigFail # noqa: F401 -from configutilities.common.exceptions import ValidateFail # noqa: F401 -from configutilities.common.utils import is_valid_vlan # noqa: F401 -from configutilities.common.utils import is_mtu_valid # noqa: F401 -from configutilities.common.utils import validate_network_str # noqa: F401 -from configutilities.common.utils import validate_address_str # noqa: F401 -from configutilities.common.utils import validate_address # noqa: F401 -from configutilities.common.utils import is_valid_url # noqa: F401 -from configutilities.common.utils import is_valid_domain_or_ip # noqa: F401 -from configutilities.common.utils import ip_version_to_string # noqa: F401 -from configutilities.common.utils import lag_mode_to_str # noqa: F401 -from configutilities.common.utils import validate_openstack_password # noqa: F401 -from configutilities.common.utils import validate_nameserver_address_str # noqa: F401 -from configutilities.common.utils import extract_openstack_password_rules_from_file # noqa: F401 diff --git a/configutilities/configutilities/configutilities/common/__init__.py b/configutilities/configutilities/configutilities/common/__init__.py deleted file mode 100644 index 1d58fc700e..0000000000 --- a/configutilities/configutilities/configutilities/common/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# -# Copyright (c) 2015 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# diff --git a/configutilities/configutilities/configutilities/common/exceptions.py b/configutilities/configutilities/configutilities/common/exceptions.py deleted file mode 100644 index 24e27264e4..0000000000 --- a/configutilities/configutilities/configutilities/common/exceptions.py +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2015 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# - - -class ConfigError(Exception): - """Base class for configuration exceptions.""" - - def __init__(self, message=None): - self.message = message - - def __str__(self): - return self.message or "" - - -class ConfigFail(ConfigError): - """General configuration error.""" - pass - - -class ValidateFail(ConfigError): - """Validation of data failed.""" - pass diff --git a/configutilities/configutilities/configutilities/common/guicomponents.py b/configutilities/configutilities/configutilities/common/guicomponents.py deleted file mode 100755 index 443b677155..0000000000 --- a/configutilities/configutilities/configutilities/common/guicomponents.py +++ /dev/null @@ -1,295 +0,0 @@ -# -# Copyright (c) 2016 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# - -import wx - -from configutilities.common.exceptions import ValidateFail -from configutilities.common import wrs_ico - -TEXT_BOX_SIZE = (150, -1) -TEXT_WIDTH = 450 -DEBUG = False -VGAP = 5 -HGAP = 10 - - -def debug(msg): - if DEBUG: - print(msg) - - -# Tracks what type of controls will implement a config question -class TYPES(object): - string = 1 - int = 2 - radio = 3 - choice = 4 - checkbox = 5 - help = 6 - separator = 7 - - -class Field(object): - def __init__(self, text="", type=TYPES.string, transient=False, - initial="", choices=[], shows=[], reverse=False, - enabled=True): - """Represent a configuration question - - :param text: Question prompt text - - :param type: The type of wxWidgets control(s) used to implement this - field - - :param transient: Whether this field should be written automatically - to the INI file - - :param enabled: Whether this field should be enabled or - disabled (greyed-out) - - :param initial: Initial value used to populate the control - - :param choices: A string list of choices to populate selection-based - fields - - :param shows: A list of field key strings that this field should show - when checked. Only checkboxes implement this functionality atm - - :param reverse: Switches the 'shows' logic -> checked - will hide fields instead of showing them - - :return: the Field object - """ - - self.text = text - self.type = type - self.transient = transient - self.initial = initial - self.choices = choices - self.shows = shows - self.reverse = reverse - self.enabled = enabled - - # Controls used to implement this field - self.prompt = None - self.input = None - - if type is TYPES.help: - self.transient = True - - # Sanity to make sure fields are being utilized correctly - if self.shows and self.type is TYPES.help: - raise NotImplementedError() - - if not self.shows and self.reverse: - raise NotImplementedError() - - def get_value(self): - # Return value of the control (a string or int) - if not self.input: - value = None - elif not self.input.IsShown() or not self.input.IsEnabled(): - value = None - elif self.type is TYPES.string: - value = self.input.GetLineText(0) - elif self.type is TYPES.int: - try: - value = self.input.GetLineText(0) - int(value) - except ValueError: - raise ValidateFail( - "Invalid entry for %s. Must enter a numeric value" % - self.text) - elif self.type is TYPES.radio: - value = self.input.GetString(self.input.GetSelection()) - elif self.type is TYPES.choice: - value = self.input.GetString(self.input.GetSelection()) - elif self.type is TYPES.checkbox: - value = "N" - if self.input.GetValue(): - value = "Y" - else: - raise NotImplementedError() - - return value - - def set_value(self, value): - # Set value of the control (string or int) - if not self.input: - # Can't 'set' help text etc. - raise NotImplementedError() - elif self.type is TYPES.string or self.type is TYPES.int: - self.input.SetValue(value) - elif self.type is TYPES.radio or self.type is TYPES.choice: - index = self.input.FindString(value) - if index == wx.NOT_FOUND: - raise ValidateFail("Invalid value %s for field %s" % - (value, self.text)) - self.input.SetSelection(index) - elif self.type is TYPES.checkbox: - self.input.SetValue(value == "Y") - else: - raise NotImplementedError() - - def destroy(self): - if self.prompt: - self.prompt.Destroy() - if self.input: - self.input.Destroy() - - def show(self, visible): - debug("Setting visibility to %s for field %s prompt=%s" % - (visible, self.text, self.prompt)) - if visible: - if self.prompt: - self.prompt.Show() - if self.input: - self.input.Show() - else: - if self.prompt: - self.prompt.Hide() - if self.input: - self.input.Hide() - - -def prepare_fields(parent, fields, sizer, change_hdlr): - for row, (name, field) in enumerate(fields.items()): - initial = field.initial - # if config.has_option(parent.section, name): - # initial = config.get(parent.section, name) - - add_attributes = wx.ALIGN_CENTER_VERTICAL - width = 1 - field.prompt = wx.StaticText(parent, label=field.text, name=name) - - # Generate different control based on field type - if field.type is TYPES.string or field.type is TYPES.int: - field.input = wx.TextCtrl(parent, value=initial, name=name, - size=TEXT_BOX_SIZE) - - elif field.type is TYPES.radio: - field.input = wx.RadioBox( - parent, choices=field.choices, majorDimension=1, - style=wx.RA_SPECIFY_COLS, name=name, id=wx.ID_ANY) - - elif field.type is TYPES.choice: - field.input = wx.Choice( - parent, choices=field.choices, name=name) - if initial: - field.input.SetSelection(field.input.FindString(initial)) - elif field.type is TYPES.checkbox: - width = 2 - field.input = wx.CheckBox(parent, name=name, label=field.text, - ) # style=wx.ALIGN_RIGHT) - field.input.SetValue(initial == 'Y') - if field.prompt: - field.prompt.Hide() - field.prompt = None - - elif field.type is TYPES.help: - width = 2 - field.prompt.Wrap(TEXT_WIDTH) - field.input = None - - elif field.type is TYPES.separator: - width = 2 - field.prompt = wx.StaticLine(parent, -1) - add_attributes = wx.EXPAND | wx.ALL - field.input = None - - else: - raise NotImplementedError() - - col = 0 - if field.prompt: - sizer.Add(field.prompt, (row, col), span=(1, width), - flag=add_attributes) - col += 1 - if field.input: - field.input.Enable(field.enabled) - sizer.Add(field.input, (row, col), - flag=add_attributes) - - # Go through again and set show/hide relationships - for name, field in fields.items(): - if field.shows: - # Add display handlers - field.input.Bind(wx.EVT_CHECKBOX, change_hdlr) - # todo tsmith add other evts - - # Start by hiding target prompt/input controls - for target_name in field.shows: - target = fields[target_name] - if target.prompt: - target.prompt.Hide() - if target.input: - target.input.Hide() - - -def on_change(parent, fields, event): - obj = event.GetEventObject() - - # debug("Checked: " + str(event.Checked()) + - # ", Reverse: " + str(parent.fields[obj.GetName()].reverse) + - # ", Will show: " + str(event.Checked() is not - # parent.fields[obj.GetName()].reverse)) - - # Hide/Show the targets of the control - # Note: the "is not" implements switching the show logic around - handle_sub_show( - fields, - fields[obj.GetName()].shows, - event.Checked() is not fields[obj.GetName()].reverse) - - parent.Layout() - event.Skip() - - -def handle_sub_show(fields, targets, show): - """ Recursive function to handle showing/hiding of a list of fields - :param targets: [String] - :param show: bool - """ - - sub_handled = [] - for tgt in targets: - if tgt in sub_handled: - # Handled by newly shown control - continue - - tgt_field = fields[tgt] - # Show or hide this field as necessary - tgt_field.show(show) - - # If it shows others (checkbox) and is now shown, - # apply it's value decide on showing it's children, not the - # original show - if tgt_field.shows and show: - sub_handled.extend(tgt_field.shows) - handle_sub_show( - fields, - tgt_field.shows, - (tgt_field.get_value() is 'Y') is not fields[tgt].reverse) - - -def set_icons(parent): - # Icon setting - # todo Make higher resolution icons, verify on different linux desktops - icons = wx.IconBundle() - for sz in [16, 32, 48]: - # try: - # icon = wx.Icon(wrs_ico.windriver_favicon.getIcon(), - # width=sz, height=sz) - icon = wrs_ico.favicon.getIcon() - icons.AddIcon(icon) - # except: - # pass - parent.SetIcons(icons) - - # ico = wrs_ico.windriver_favicon.getIcon() - # self.SetIcon(ico) - - # self.tbico = wx.TaskBarIcon() - # self.tbico.SetIcon(ico, '') diff --git a/configutilities/configutilities/configutilities/common/utils.py b/configutilities/configutilities/configutilities/common/utils.py deleted file mode 100644 index 319aa53ed7..0000000000 --- a/configutilities/configutilities/configutilities/common/utils.py +++ /dev/null @@ -1,367 +0,0 @@ -""" -Copyright (c) 2015-2016 Wind River Systems, Inc. - -SPDX-License-Identifier: Apache-2.0 - -""" - -from six.moves import configparser -import re -import six -from netaddr import IPNetwork -from netaddr import IPAddress -from netaddr import AddrFormatError -from netaddr import valid_ipv4 -from netaddr import valid_ipv6 - -from configutilities.common.exceptions import ValidateFail - -EXPECTED_SERVICE_NAME_AND_TYPE = ( - {"KEYSTONE_SERVICE_NAME": "keystone", - "KEYSTONE_SERVICE_TYPE": "identity", - "SYSINV_SERVICE_NAME": "sysinv", - "SYSINV_SERVICE_TYPE": "platform", - "PATCHING_SERVICE_NAME": "patching", - "PATCHING_SERVICE_TYPE": "patching", - "NFV_SERVICE_NAME": "vim", - "NFV_SERVICE_TYPE": "nfv", - "FM_SERVICE_NAME": "fm", - "FM_SERVICE_TYPE": "faultmanagement", - "BARBICAN_SERVICE_NAME": "barbican", - "BARBICAN_SERVICE_TYPE": "key-manager", - }) - - -def is_valid_vlan(vlan): - """Determine whether vlan is valid.""" - try: - if 0 < int(vlan) < 4095: - return True - else: - return False - except (ValueError, TypeError): - return False - - -def is_mtu_valid(mtu): - """Determine whether a mtu is valid.""" - try: - if int(mtu) < 576: - return False - elif int(mtu) > 9216: - return False - else: - return True - except (ValueError, TypeError): - return False - - -def is_valid_hostname(hostname): - """Determine whether a hostname is valid as per RFC 1123.""" - - # Maximum length of 255 - if not hostname or len(hostname) > 255: - return False - # Allow a single dot on the right hand side - if hostname[-1] == ".": - hostname = hostname[:-1] - # Create a regex to ensure: - # - hostname does not begin or end with a dash - # - each segment is 1 to 63 characters long - # - valid characters are A-Z (any case) and 0-9 - valid_re = re.compile("(?!-)[A-Z\d-]{1,63}(? Validate a system configuration file\n" - "--region-config Validate a region configuration file\n" - % sys.argv[0]) - exit(1) - - -def main(): - config_file = None - system_config = False - region_config = False - - arg = 1 - while arg < len(sys.argv): - if sys.argv[arg] == "--system-config": - arg += 1 - if arg < len(sys.argv): - config_file = sys.argv[arg] - else: - print("--system-config requires the filename of the config " - "file") - exit(1) - system_config = True - elif sys.argv[arg] == "--region-config": - arg += 1 - if arg < len(sys.argv): - config_file = sys.argv[arg] - else: - print("--region-config requires the filename of the config " - "file") - exit(1) - region_config = True - elif sys.argv[arg] in ["--help", "-h", "-?"]: - show_help() - else: - print("Invalid option.") - show_help() - arg += 1 - - if [system_config, region_config].count(True) != 1: - print("Invalid combination of options selected") - show_help() - - if system_config: - config_type = DEFAULT_CONFIG - else: - config_type = REGION_CONFIG - - if not os.path.isfile(config_file): - print("Config file %s does not exist" % config_file) - exit(1) - - # Parse the system config file - print("Parsing configuration file... ", end=' ') - system_config = parse_config(config_file) - print("DONE") - - # Validate the system config file - print("Validating configuration file... ", end=' ') - try: - # we use the presence of tsconfig to determine if we are onboard or - # not since it will not be available in the offboard case - offboard = False - try: - from tsconfig.tsconfig import SW_VERSION # noqa: F401 - except ImportError: - offboard = True - validate(system_config, config_type, None, offboard) - except configparser.Error as e: - print("Error parsing configuration file %s: %s" % (config_file, e)) - except (ConfigFail, ValidateFail) as e: - print("\nValidation failed: %s" % e) - print("DONE") diff --git a/configutilities/configutilities/configutilities/configfiletool.py b/configutilities/configutilities/configutilities/configfiletool.py deleted file mode 100755 index bd85d8d7bb..0000000000 --- a/configutilities/configutilities/configutilities/configfiletool.py +++ /dev/null @@ -1,1495 +0,0 @@ -""" -Copyright (c) 2015-2017 Wind River Systems, Inc. - -SPDX-License-Identifier: Apache-2.0 - -""" - -from collections import OrderedDict -from six.moves import configparser -import wx -import wx.wizard as wiz -import wx.lib.dialogs -import wx.lib.scrolledpanel - -from configutilities.common.configobjects import REGION_CONFIG -from configutilities.common.configobjects import DEFAULT_CONFIG -from configutilities.common.exceptions import ValidateFail -from configutilities.common.guicomponents import Field -from configutilities.common.guicomponents import TYPES -from configutilities.common.guicomponents import prepare_fields -from configutilities.common.guicomponents import on_change -from configutilities.common.guicomponents import debug -from configutilities.common.guicomponents import set_icons -from configutilities.common.guicomponents import TEXT_WIDTH -from configutilities.common.guicomponents import VGAP -from configutilities.common.guicomponents import HGAP -from configutilities.common.validator import ConfigValidator -from configutilities.common.validator import TiS_VERSION - -PADDING = 5 -CONFIG_TYPE = DEFAULT_CONFIG - -# Config parser to hold current configuration -filename = None -filedir = None -config = configparser.RawConfigParser() -config.optionxform = str - - -def print_config(conf=config): - debug('======CONFIG CONTENTS======') - debug(get_config(config)) - debug('======END CONFIG======') - - -def get_config(conf=config): - result = "" - for section in conf.sections(): - result += "\n[" + section + "]" + "\n" - for option in config.options(section): - result += option + "=" + config.get(section, option) + "\n" - return result - - -def get_opt(section, option): - if config.has_section(section): - if config.has_option(section, option): - return config.get(section, option) - return None - - -class ConfigWizard(wx.wizard.Wizard): - """Titanium Cloud configuration wizard, contains pages and more specifically - ConfigPages, which have a structure for populating/processing - configuration fields (questions) - """ - def __init__(self): - wx.wizard.Wizard.__init__(self, None, -1, - "Titanium Cloud Configuration File " - "Creator v" + TiS_VERSION) - - set_icons(self) - - self.pages = [] - # Catch wizard events - self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.on_page_changed) - self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.on_page_changing) - self.Bind(wiz.EVT_WIZARD_CANCEL, self.on_cancel) - self.Bind(wiz.EVT_WIZARD_FINISHED, self.on_finished) - - self.add_page(STARTPage(self)) - self.add_page(REGIONPage(self)) - self.add_page(SHAREDSERVICESPage(self)) - self.add_page(REG2SERVICESPage(self)) - self.add_page(REG2SERVICESPage2(self)) - self.add_page(SYSTEMPage(self)) - self.add_page(PXEBootPage(self)) - self.add_page(MGMTPage(self)) - self.add_page(INFRAPage(self)) - self.add_page(OAMPage(self)) - self.add_page(AUTHPage(self)) - self.add_page(ENDPage(self)) - - size = self.GetBestSize() - - # Deprecated, from before scroll panel - # for page in self.pages: - # if issubclass(type(page), ConfigPage): - # # Must create fields for the page and show them all - # # to get max possible size - # page.load() - # page.GetSizer().ShowItems(True) - # page_size = page.GetBestSize() - # if page_size.GetHeight() > size.GetHeight(): - # size.SetHeight(page_size.GetHeight()) - # if page_size.GetWidth() > size.GetWidth(): - # size.SetWidth(page_size.GetWidth()) - # page.DestroyChildren() - - size.SetWidth(560) - size.SetHeight(530) - self.SetPageSize(size) - self.GetSizer().Layout() - - def add_page(self, page): - """Add a new page""" - if self.pages: - previous_page = self.pages[-1] - page.SetPrev(previous_page) - previous_page.SetNext(page) - self.pages.append(page) - - def run(self): - """Start the wizard""" - self.RunWizard(self.pages[0]) - - def on_page_changed(self, evt): - """Executed after the page has changed.""" - page = evt.GetPage() - if evt.GetDirection(): - page.DestroyChildren() - page.load() - - def on_page_changing(self, evt): - """Executed before the page changes, can be blocked (vetoed)""" - page = evt.GetPage() - # Perform the page validation - if evt.GetDirection(): - try: - page.validate_page() - except Exception as ex: - dlg = wx.MessageDialog( # ScrolledMessageDialog( - self, - ex.message, - "Error on page") - dlg.ShowModal() - # Do not allow progress if errors were raised - evt.Veto() - # raise ex - - def on_cancel(self, evt): - """On cancel button press, not used for now""" - pass - - def on_finished(self, evt): - """On finish button press, not used for now""" - pass - - def skip_page(self, page, skip): - for p in self.pages: - if p.__class__.__name__ == page.__name__: - p.skip = skip - - -class WizardPage(wiz.PyWizardPage): - """ An extended panel obj with a few methods to keep track of its siblings. - This should be modified and added to the wizard. Season to taste.""" - def __init__(self, parent): - wx.wizard.PyWizardPage.__init__(self, parent) - self.parent = parent - self.title = "" - self.next = self.prev = None - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.SetSizer(self.sizer) - self.skip = False - - def set_title(self, title_text): - title = wx.StaticText(self, -1, title_text) - title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)) - self.sizer.AddWindow(title, 0, wx.ALIGN_LEFT | wx.ALL, PADDING) - self.add_line() - - def add_content(self, content, proportion=0): - """Add aditional widgets to the bottom of the page""" - self.sizer.Add(content, proportion, wx.EXPAND | wx.ALL, PADDING) - - def add_line(self): - self.sizer.AddWindow(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.ALL, - PADDING) - - def SetNext(self, next): - """Set the next page""" - self.next = next - - def SetPrev(self, prev): - """Set the previous page""" - self.prev = prev - - def GetNext(self): - """Return the next page""" - if self.next and self.next.skip: - return self.next.GetNext() - return self.next - - def GetPrev(self): - """Return the previous page""" - if self.prev and self.prev.skip: - return self.prev.GetPrev() - return self.prev - - def load(self): - # Run every time a page is visited (from prev or next page) - pass - - def validate_page(self): - # Validate the config related to this specific page before advancing - pass - - -class ConfigPage(WizardPage): - """ A Page of the wizard with questions/answers - """ - def __init__(self, *args, **kwargs): - super(ConfigPage, self).__init__(*args, **kwargs) - # Section header to put in the INI file - self.section = "" - # Methods of the config_validator to be called for this section - self.validator_methods = [] - self.title = "" - self.help_text = "" - self.fields = OrderedDict() - - def load(self): - self.title = "" - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.SetSizer(self.sizer) - - self.section = "" - self.title = "" - self.help_text = "" - for field in self.fields.values(): - field.destroy() - self.fields = OrderedDict() - - def do_setup(self): - # Reset page, in case fields have changed - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.SetSizer(self.sizer) - - # Set up title and help text - self.set_title(self.title) - - if self.help_text: - help_text = wx.StaticText(self, -1, self.help_text) - help_text.Wrap(TEXT_WIDTH) - self.add_content(help_text) - self.add_line() - - self.spanel = wx.lib.scrolledpanel.ScrolledPanel(self, -1) - # to view spanel: , style=wx.SIMPLE_BORDER) - self.add_content(self.spanel, 3) - - # Add fields to page - # gridSizer = wx.FlexGridSizer(rows=6, cols=2, vgap=10, - # hgap=10) - self.gridSizer = wx.GridBagSizer(vgap=VGAP, hgap=HGAP) - # gridSizer.SetFlexibleDirection(wx.VERTICAL) - # gridSizer.SetFlexibleDirection(wx.BOTH) - - self.spanel.SetSizer(self.gridSizer) - self.spanel.SetupScrolling() - - # self.add_content(gridSizer) - - prepare_fields(self.spanel, self.fields, self.gridSizer, - self.on_change) - - self.Layout() - self.spanel.Layout() - - def on_change(self, event): - on_change(self, self.fields, event) - - def validate_page(self): - # Gets the config from the current page, then sends to the validator - self.get_config() - - print_config(config) - - validator = ConfigValidator(config, None, CONFIG_TYPE, True) - - mode = get_opt('SYSTEM', 'SYSTEM_MODE') - if mode: - validator.set_system_mode(mode) - - dc_role = get_opt('SYSTEM', 'DISTRIBUTED_CLOUD_ROLE') - if dc_role: - validator.set_system_dc_role(dc_role) - - for method in self.validator_methods: - getattr(validator, method)() - - def get_config(self): - # Removes possibly out-dated config section so it can be over-written - if config.has_section(self.section): - config.remove_section(self.section) - - self.add_fields() - - def add_fields(self): - # Adds the page's section to the config object if necessary - if not config.has_section(self.section): - config.add_section(self.section) - - # Add all of the non-transient fields (straight-forward mapping) - for name, field in self.fields.items(): - if not field.transient and field.get_value(): - config.set(self.section, name, field.get_value()) - - def bind_events(self): - pass - - -class STARTPage(WizardPage): - def load(self): - super(STARTPage, self).load() - - self.set_title("Start") - help_text = wx.StaticText( - self, -1, - "Welcome to the Titanium Cloud Configuration File " - "Creator.\n\n" - "This wizard will walk you through the steps of creating a " - "configuration file which can be used to automate the " - "installation of Titanium Cloud. Note this utility can only be " - "used to create configuration files compatible with version " + - TiS_VERSION + " of Titanium Cloud.\n\n" - "NOTE: Moving backwards in the wizard will result in loss of the " - "current page's configuration and will need to be reentered\n\n" - "Press next to begin.\n\n\n\n") - help_text.Wrap(TEXT_WIDTH) - self.add_content(help_text) - - # self.add_line() - - # To implement this, would need special mapping for every page... - # (from config to control) - # putting this on the long(er)-term todo list for now - # self.add_content(wx.StaticText( - # self, -1, - # 'You may optionally pre-populate this utility by reading in an ' - # 'existing Titanium Cloud configuration file')) - - # self.load_button = wx.Button(self, -1, "Load Configuration File " - # "(Optional)") - # self.Bind(wx.EVT_BUTTON, self.on_read, self.load_button) - # self.add_content(self.load_button) - - def on_read(self, event): - reader = wx.FileDialog( - self, "Open Existing Titanium Cloud Configuration File", - "", "", "INI file (*.ini)|*.ini", - wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) - - if reader.ShowModal() == wx.ID_CANCEL: - return - - # Read in the config file - global filename, filedir, config - try: - config.read(reader.GetPath()) - filename = reader.GetFilename() - filedir = reader.GetDirectory() - except Exception as ex: - wx.LogError("Cannot parse configuration file, Error: %s." % ex) - config = configparser.RawConfigParser() - config.optionxform = str - return - - # todo tsmith - # Do validation of the imported file - - -class REGIONPage(ConfigPage): - def load(self): - super(REGIONPage, self).load() - - # Header in INI file - self.section = "SHARED_SERVICES" - self.validator_methods = [] - self.title = "Region Configuration" - self.help_text = ( - "Configuring this system in region mode provides the ability to " - "operate as a secondary independent region to an existing " - "Openstack cloud deployment (Certain restrictions apply, refer to " - "system documentation).\n\n" - "Keystone (and optionally Glance) " - "services can be configured as shared services, which " - "prevents them from being configured on the secondary region and " - "instead those services already configured in the primary region " - "will be accessed.") - - self.set_fields() - self.do_setup() - self.bind_events() - - # Skip region pages by default - self.skip_region(True) - - def set_fields(self): - self.fields['is_region'] = Field( - text="Configure as a secondary region", - type=TYPES.checkbox, - transient=True, - shows=["REGION_NAME", - "ADMIN_TENANT_NAME", - "ADMIN_USER_NAME", - "ADMIN_PASSWORD", - "SERVICE_TENANT_NAME", - "keystone_help", - "KEYSTONE_ADMINURL", - "sep1", - "keystone_note", - ] - ) - - self.fields['REGION_NAME'] = Field( - text="Name of the primary region", - type=TYPES.string, - initial="RegionOne" - ) - self.fields["sep1"] = Field(type=TYPES.separator) - self.fields['keystone_help'] = Field( - text="Primary Keystone Configuration\n\nThis information " - "is needed for the primary " - "region in order to validate or create the shared " - "services.", - type=TYPES.help, - ) - self.fields['SERVICE_TENANT_NAME'] = Field( - text="Name of the service tenant", - type=TYPES.string, - initial="RegionTwo_services" - ) - self.fields['ADMIN_TENANT_NAME'] = Field( - text="Name of the admin tenant", - type=TYPES.string, - initial="admin" - ) - self.fields['ADMIN_USER_NAME'] = Field( - text="Username of the keystone admin account", - type=TYPES.string, - initial="admin" - ) - self.fields['ADMIN_PASSWORD'] = Field( - text="Password of the keystone admin account", - type=TYPES.string, - initial="" - ) - self.fields['KEYSTONE_ADMINURL'] = Field( - text="Authentication URL of the keystone service", - type=TYPES.string, - initial="http://192.168.204.2:5000/v3" - ) - self.fields['keystone_note'] = Field( - text="NOTE: If 'Automatically configure shared keystone' " - "is checked in the upcoming 'Secondary Region Services' page," - " then the service tenant (above) will be created " - "if not present.", - type=TYPES.help, - ) - - def validate_page(self): - super(REGIONPage, self).validate_page() - # Do page specific validation here - if self.fields['is_region'].get_value() == 'Y' and \ - not config.has_option(self.section, "ADMIN_PASSWORD"): - raise ValidateFail("The keystone admin password is mandatory") - - def get_config(self): - super(REGIONPage, self).get_config() - - if len(config.items(self.section)) == 0: - config.remove_section(self.section) - config.remove_section("REGION_2_SERVICES") - config.remove_section("REGION2_PXEBOOT_NETWORK") - else: - # Add service name which doesn't change - config.set(self.section, "KEYSTONE_SERVICE_NAME", "keystone") - config.set(self.section, "KEYSTONE_SERVICE_TYPE", "identity") - - def bind_events(self): - self.fields['is_region'].input.Bind(wx.EVT_CHECKBOX, self.on_region) - - def on_region(self, event): - # Set the region pages to be skipped or not - self.skip_region(event.GetInt() == 0) - event.Skip() - - def skip_region(self, skip): - debug("Setting region skips to %s" % skip) - self.next.skip = skip - self.next.next.skip = skip - self.next.next.next.skip = skip - self.parent.skip_page(AUTHPage, not skip) - - # Set the config type appropriately - global CONFIG_TYPE - if skip: - CONFIG_TYPE = DEFAULT_CONFIG - else: - CONFIG_TYPE = REGION_CONFIG - - # Remove any sections that aren't handled in region-config mode - config.remove_section("PXEBOOT_NETWORK") - config.remove_section("AUTHENTICATION") - - -class SHAREDSERVICESPage(ConfigPage): - def load(self): - super(SHAREDSERVICESPage, self).load() - - self.section = "SHARED_SERVICES" - self.validator_methods = [] - self.title = "Regions - Shared Services" - self.help_text = ( - "Keystone is always configured as a shared service. " - "Glance may also optionally be configured as " - "shared services.") - - self.set_fields() - self.do_setup() - self.bind_events() - - def set_fields(self): - # GLANCE - self.fields['share_glance'] = Field( - text="Share the primary region's glance service", - type=TYPES.checkbox, - transient=True - ) - - def validate_page(self): - # do previous pages validation as well to refresh config, since they - # share a section - self.prev.validate_page() - super(SHAREDSERVICESPage, self).validate_page() - - # Do page specific validation here - - def get_config(self): - # Skip the parent get_config so the section isn't removed - # (since it's shared we want the old info) - self.add_fields() - - # Add Static service types - if self.fields['share_glance'].get_value() == 'Y': - config.set(self.section, "GLANCE_SERVICE_NAME", "glance") - config.set(self.section, "GLANCE_SERVICE_TYPE", "image") - - -class REG2SERVICESPage(ConfigPage): - - def load(self): - super(REG2SERVICESPage, self).load() - self.section = "REGION_2_SERVICES" - # Validation is only done on last of region pages - self.validator_methods = [] - self.title = "Secondary Region Services (1/2)" - self.help_text = ( - "Secondary region services are not shared with the primary " - "region, during installation they will be configured to run " - "in this region.") - - self.set_fields() - self.do_setup() - self.bind_events() - - def set_fields(self): - - self.fields['create_help'] = Field( - text="During configuration, the Primary Region's Keystone " - "can be automatically " - "provisioned to accommodate this region, including if " - "necessary the services tenant, users, services, " - "and endpoints. If this is not " - "enabled, manual configuration of the Primary Region's " - "Keystone must be done and " - "only validation will be performed during this secondary " - "region's configuration.\n\n" - "Note: passwords are optional if this option is selected.", - type=TYPES.help, - ) - self.fields['CREATE'] = Field( - text="Automatically configure shared keystone", - type=TYPES.checkbox, - initial='Y', - ) - self.fields['REGION_NAME'] = Field( - text="Name for this system's region", - type=TYPES.string, - initial="RegionTwo" - ) - self.fields['sep1'] = Field(type=TYPES.separator) - - if not config.has_option('SHARED_SERVICES', 'GLANCE_SERVICE_NAME'): - # GLANCE - self.fields['GLANCE_USER_NAME'] = Field( - text="Glance username", - type=TYPES.string, - initial="glance") - self.fields['GLANCE_PASSWORD'] = Field( - text="Glance user password", - type=TYPES.string, - initial="") - self.fields['sep2'] = Field(type=TYPES.separator) - - self.fields['NOVA_USER_NAME'] = Field( - text="Nova username", - type=TYPES.string, initial="nova") - self.fields['NOVA_PASSWORD'] = Field( - text="Nova user password", - type=TYPES.string, initial="") - - def validate_page(self): - super(REG2SERVICESPage, self).validate_page() - - if self.fields['CREATE'].get_value() == 'N': - if (('GLANCE_PASSWORD' in self.fields and - not self.fields['GLANCE_PASSWORD'].get_value()) or - not self.fields['NOVA_PASSWORD'].get_value()): - raise ValidateFail("Passwords are mandatory when automatic " - "keystone configuration is not enabled.") - - def get_config(self): - super(REG2SERVICESPage, self).get_config() - - -class REG2SERVICESPage2(ConfigPage): - - def load(self): - super(REG2SERVICESPage2, self).load() - - self.section = "REGION_2_SERVICES" - # Validation is only done on last page - self.validator_methods = ["validate_network", "validate_region"] - self.title = "Secondary Region Services (2/2)" - - self.set_fields() - self.do_setup() - self.bind_events() - - def set_fields(self): - self.fields['NEUTRON_USER_NAME'] = Field( - text="Neutron username", - type=TYPES.string, initial="neutron") - self.fields['NEUTRON_PASSWORD'] = Field( - text="Neutron user password", - type=TYPES.string, initial="") - - self.fields['SYSINV_USER_NAME'] = Field( - text="Sysinv username", - type=TYPES.string, initial="sysinv") - self.fields['SYSINV_PASSWORD'] = Field( - text="Sysinv user password", - type=TYPES.string, initial="") - - self.fields['PATCHING_USER_NAME'] = Field( - text="Patching username", - type=TYPES.string, initial="patching") - self.fields['PATCHING_PASSWORD'] = Field( - text="Patching user password", - type=TYPES.string, initial="") - - self.fields['HEAT_USER_NAME'] = Field( - text="Heat username", - type=TYPES.string, initial="heat") - self.fields['HEAT_PASSWORD'] = Field( - text="Heat user password", - type=TYPES.string, initial="") - self.fields['HEAT_ADMIN_DOMAIN'] = Field( - text="Heat admin domain", - type=TYPES.string, initial="heat") - self.fields['HEAT_ADMIN_USER_NAME'] = Field( - text="Heat admin username", - type=TYPES.string, initial="heat_stack_admin") - self.fields['HEAT_ADMIN_PASSWORD'] = Field( - text="Password of the heat admin user", - type=TYPES.string, initial="") - - self.fields['CEILOMETER_USER_NAME'] = Field( - text="Ceilometer username", - type=TYPES.string, initial="ceilometer") - self.fields['CEILOMETER_PASSWORD'] = Field( - text="Ceilometer user password", - type=TYPES.string, initial="") - - self.fields['AODH_USER_NAME'] = Field( - text="Aodh username", - type=TYPES.string, initial="aodh") - self.fields['AODH_PASSWORD'] = Field( - text="Aodh user password", - type=TYPES.string, initial="") - - self.fields['NFV_USER_NAME'] = Field( - text="NFV username", - type=TYPES.string, initial="vim") - self.fields['NFV_PASSWORD'] = Field( - text="NFV user password", - type=TYPES.string, initial="") - - self.fields['MTCE_USER_NAME'] = Field( - text="MTCE username", - type=TYPES.string, initial="mtce") - self.fields['MTCE_PASSWORD'] = Field( - text="MTCE user password", - type=TYPES.string, initial="") - - self.fields['PANKO_USER_NAME'] = Field( - text="PANKO username", - type=TYPES.string, initial="panko") - self.fields['PANKO_PASSWORD'] = Field( - text="PANKO user password", - type=TYPES.string, initial="") - - self.fields['PLACEMENT_USER_NAME'] = Field( - text="Placement username", - type=TYPES.string, initial="placement") - self.fields['PLACEMENT_PASSWORD'] = Field( - text="Placement user password", - type=TYPES.string, initial="") - - self.fields['GNOCCHI_USER_NAME'] = Field( - text="GNOCCHI username", - type=TYPES.string, initial="gnocchi") - self.fields['GNOCCHI_PASSWORD'] = Field( - text="GNOCCHI user password", - type=TYPES.string, initial="") - - self.fields['FM_USER_NAME'] = Field( - text="FM username", - type=TYPES.string, initial="fm") - self.fields['FM_PASSWORD'] = Field( - text="FM user password", - type=TYPES.string, initial="") - - self.fields['BARBICAN_USER_NAME'] = Field( - text="Barbican username", - type=TYPES.string, initial="barbican") - self.fields['BARBICAN_PASSWORD'] = Field( - text="Barbican user password", - type=TYPES.string, initial="") - - def validate_page(self): - self.prev.validate_page() - super(REG2SERVICESPage2, self).validate_page() - - def get_config(self): - # Special handling for all region sections is done here - self.add_fields() - - -class SYSTEMPage(ConfigPage): - def load(self): - super(SYSTEMPage, self).load() - - self.section = "SYSTEM" - self.validator_methods = [] - self.title = "System" - self.help_text = ( - "All-in-one System Mode Configuration\n\nAvailable options are: \n" - "duplex-direct: two node redundant configuration. Management and " - "infrastructure networks are directly connected to peer ports\n" - "duplex: two node redundant configuration\n" - "simplex: single node non-redundant configuration") - - self.system_mode = ['duplex-direct', 'duplex', 'simplex'] - - self.set_fields() - self.do_setup() - self.bind_events() - - self.skip_not_required_pages(False) - - def set_fields(self): - self.fields['use_mode'] = Field( - text="Configure as an All-in-one system", - type=TYPES.checkbox, - transient=True, - shows=["SYSTEM_MODE"] - ) - self.fields['SYSTEM_MODE'] = Field( - text="System redundant configuration", - type=TYPES.radio, - choices=self.system_mode, - ) - - def validate_page(self): - super(SYSTEMPage, self).validate_page() - - def get_config(self): - super(SYSTEMPage, self).get_config() - if len(config.items(self.section)) == 0: - config.remove_section(self.section) - else: - config.set(self.section, 'SYSTEM_TYPE', 'All-in-one') - - def bind_events(self): - self.fields['SYSTEM_MODE'].input.Bind(wx.EVT_RADIOBOX, self.on_mode) - self.fields['use_mode'].input.Bind(wx.EVT_CHECKBOX, self.on_use_mode) - - def on_mode(self, event): - # Set the pages to be skipped or not - self.skip_not_required_pages( - self.system_mode[event.GetInt()] == 'simplex') - event.Skip() - - def on_use_mode(self, event): - # Set the pages to be skipped or not - if event.GetInt() == 0: - # If set to not in use, ensure the pages are not skipped - self.skip_not_required_pages(False) - # And reset to the default selection - self.fields['SYSTEM_MODE'].set_value('duplex-direct') - event.Skip() - - def skip_not_required_pages(self, skip): - # Skip PXEBOOT, BMC and INFRA pages - self.parent.skip_page(PXEBootPage, skip) - self.parent.skip_page(INFRAPage, skip) - - # Remove the sections that are not required - config.remove_section("PXEBOOT_NETWORK") - config.remove_section("BOARD_MANAGEMENT_NETWORK") - config.remove_section("INFRA_NETWORK") - - -class PXEBootPage(ConfigPage): - - def load(self): - super(PXEBootPage, self).load() - self.section = "PXEBOOT_NETWORK" - self.validator_methods = ["validate_pxeboot"] - self.title = "PXEBoot Network" - self.help_text = ( - "The PXEBoot network is used for initial booting and installation " - "of each node. IP addresses on this network are reachable only " - "within the data center.\n\n" - "The default configuration combines the PXEBoot network and the " - "management network. If a separate PXEBoot network is used, it " - "will share the management interface, which requires the " - "management network to be placed on a VLAN.") - - self.set_fields() - self.do_setup() - self.bind_events() - - def set_fields(self): - if config.has_section("REGION_2_SERVICES"): - self.fields['mandatory'] = Field( - text="A PXEBoot network is mandatory for secondary" - " region deployments.", - type=TYPES.help - ) - self.section = "REGION2_PXEBOOT_NETWORK" - else: - self.fields['use_pxe'] = Field( - text="Configure a separate PXEBoot network", - type=TYPES.checkbox, - transient=True, - shows=["PXEBOOT_CIDR", "use_entire_subnet"] - ) - self.fields['PXEBOOT_CIDR'] = Field( - text="PXEBoot subnet", - type=TYPES.string, - initial="192.168.202.0/24" - ) - - # Start/end ranges - self.fields['use_entire_subnet'] = Field( - text="Restrict PXEBoot subnet address range", - type=TYPES.checkbox, - shows=["IP_START_ADDRESS", "IP_END_ADDRESS"], - transient=True - ) - self.fields['IP_START_ADDRESS'] = Field( - text="PXEBoot network start address", - type=TYPES.string, - initial="192.168.202.2", - ) - self.fields['IP_END_ADDRESS'] = Field( - text="PXEBoot network end address", - type=TYPES.string, - initial="192.168.202.254", - ) - - def get_config(self): - super(PXEBootPage, self).get_config() - - if len(config.items(self.section)) == 0: - config.remove_section(self.section) - if config.has_section("REGION_2_SERVICES"): - raise ValidateFail( - "Must configure a PXEBoot network when in region mode") - - def validate_page(self): - super(PXEBootPage, self).validate_page() - # Do page specific validation here - - -class MGMTPage(ConfigPage): - - def load(self): - super(MGMTPage, self).load() - - # Preserve order plus allow mapping back to raw value - if get_opt('SYSTEM', 'SYSTEM_MODE') == 'duplex-direct': - self.lag_choices = OrderedDict([ - ('802.3ad (LACP) policy', '4'), - ]) - else: - self.lag_choices = OrderedDict([ - ('Active-backup policy', '1'), - ('802.3ad (LACP) policy', '4'), - ]) - self.section = "MGMT_NETWORK" - if get_opt('SYSTEM', 'SYSTEM_MODE') != 'simplex': - self.validator_methods = ["validate_pxeboot", "validate_mgmt"] - self.help_text = ( - "The management network is used for internal communication " - "between platform components. IP addresses on this network " - "are reachable only within the data center.") - else: - self.validator_methods = ["validate_aio_simplex_mgmt"] - self.help_text = ( - "The management network is used for internal communication " - "between platform components. IP addresses on this network " - "are reachable only within the host.") - self.title = "Management Network" - - self.set_fields() - self.do_setup() - self.bind_events() - - def set_fields(self): - if get_opt('SYSTEM', 'SYSTEM_MODE') != 'simplex': - self.fields['mgmt_port1'] = Field( - text="Management interface", - type=TYPES.string, - initial="enp0s8", - transient=True - ) - self.fields['lag_help'] = Field( - text="A management bond interface provides redundant " - "connections for the management network. When selected, " - "the field above specifies the first member of the bond.", - type=TYPES.help, - ) - self.fields['LAG_INTERFACE'] = Field( - text="Use management interface link aggregation", - type=TYPES.checkbox, - shows=["LAG_MODE", "mgmt_port2"], - transient=True - ) - self.fields['LAG_MODE'] = Field( - text="Management interface bonding policy", - type=TYPES.choice, - choices=self.lag_choices.keys(), - transient=True - ) - self.fields['mgmt_port2'] = Field( - text="Second management interface member", - type=TYPES.string, - initial="", - transient=True - ) - self.fields['INTERFACE_MTU'] = Field( - text="Management interface MTU", - type=TYPES.int, - initial="1500", - transient=True - ) - if config.has_option('PXEBOOT_NETWORK', 'PXEBOOT_CIDR') or \ - config.has_option('REGION2_PXEBOOT_NETWORK', - 'PXEBOOT_CIDR'): - self.fields['vlan_help'] = Field( - text=("A management VLAN is required because a separate " - "PXEBoot network was configured on the management " - "interface."), - type=TYPES.help - ) - self.fields['VLAN'] = Field( - text="Management VLAN Identifier", - type=TYPES.int, - initial="", - ) - - self.fields['CIDR'] = Field( - text="Management subnet", - type=TYPES.string, - initial="192.168.204.0/24", - ) - - self.fields['MULTICAST_CIDR'] = Field( - text="Management multicast subnet", - type=TYPES.string, - initial='239.1.1.0/28' - ) - - # Start/end ranges - self.fields['use_entire_subnet'] = Field( - text="Restrict management subnet address range", - type=TYPES.checkbox, - shows=["IP_START_ADDRESS", "IP_END_ADDRESS"], - transient=True - ) - self.fields['IP_START_ADDRESS'] = Field( - text="Management network start address", - type=TYPES.string, - initial="192.168.204.2", - ) - self.fields['IP_END_ADDRESS'] = Field( - text="Management network end address", - type=TYPES.string, - initial="192.168.204.254", - ) - - # Dynamic addressing - self.fields['dynamic_help'] = Field( - text=( - "IP addresses can be assigned to hosts dynamically or " - "a static IP address can be specified for each host. " - "Note: This choice applies to both the management network " - "and infrastructure network."), - type=TYPES.help, - ) - self.fields['DYNAMIC_ALLOCATION'] = Field( - text="Use dynamic IP address allocation", - type=TYPES.checkbox, - initial='Y' - ) - else: - self.fields['CIDR'] = Field( - text="Management subnet", - type=TYPES.string, - initial="192.168.204.0/28", - ) - - def validate_page(self): - super(MGMTPage, self).validate_page() - # Do page specific validation here - - def get_config(self): - super(MGMTPage, self).get_config() - - if get_opt('SYSTEM', 'SYSTEM_MODE') != 'simplex': - # Add logical interface - ports = self.fields['mgmt_port1'].get_value() - if self.fields['mgmt_port2'].get_value(): - ports += "," + self.fields['mgmt_port2'].get_value() - li = create_li( - lag=self.fields['LAG_INTERFACE'].get_value(), - mode=self.lag_choices.get(self.fields['LAG_MODE'].get_value()), - mtu=self.fields['INTERFACE_MTU'].get_value(), - ports=ports - ) - config.set(self.section, 'LOGICAL_INTERFACE', li) - clean_lis() - - -class INFRAPage(ConfigPage): - def load(self): - super(INFRAPage, self).load() - - # Preserve order plus allow mapping back to raw value - self.lag_choices = OrderedDict([ - ('Active-backup policy', '1'), - ('Balanced XOR policy', '2'), - ('802.3ad (LACP) policy', '4'), - ]) - - self.section = "INFRA_NETWORK" - self.validator_methods = ["validate_storage", - "validate_pxeboot", - "validate_mgmt", - "validate_infra"] - self.title = "Infrastructure Network" - self.help_text = ( - "The infrastructure network is used for internal communication " - "between platform components to offload the management network " - "of high bandwidth services. " - "IP addresses on this network are reachable only within the data " - "center.\n\n" - "If a separate infrastructure interface is not configured the " - "management network will be used.") - - self.set_fields() - self.do_setup() - self.bind_events() - - def set_fields(self): - self.fields['use_infra'] = Field( - text="Configure an infrastructure interface", - type=TYPES.checkbox, - transient=True - ) - self.fields['infra_port1'] = Field( - text="Infrastructure interface", - type=TYPES.string, - initial="", - transient=True - ) - self.fields['lag_help'] = Field( - text="An infrastructure bond interface provides redundant " - "connections for the infrastructure network. When selected, " - "the field above specifies the first member of the bond.", - type=TYPES.help, - ) - self.fields['LAG_INTERFACE'] = Field( - text="Use infrastructure interface link aggregation", - type=TYPES.checkbox, - shows=["LAG_MODE", "infra_port2"], - transient=True - ) - self.fields['LAG_MODE'] = Field( - text="Infrastructure interface bonding policy", - type=TYPES.choice, - choices=self.lag_choices.keys(), - transient=True - ) - self.fields['infra_port2'] = Field( - text="Second infrastructure interface member", - type=TYPES.string, - initial="", - transient=True - ) - self.fields['INTERFACE_MTU'] = Field( - text="Infrastructure interface MTU", - type=TYPES.int, - initial="1500", - transient=True - ) - - # VLAN - self.fields['use_vlan'] = Field( - text="Configure an infrastructure VLAN", - type=TYPES.checkbox, - shows=["VLAN"], - transient=True - ) - self.fields['VLAN'] = Field( - text="Infrastructure VLAN Identifier", - type=TYPES.int, - initial="", - ) - - self.fields['CIDR'] = Field( - text="Infrastructure subnet", - type=TYPES.string, - initial="192.168.205.0/24", - ) - - # Start/end ranges - self.fields['use_entire_subnet'] = Field( - text="Restrict infrastructure subnet address range", - type=TYPES.checkbox, - shows=["IP_START_ADDRESS", "IP_END_ADDRESS"], - transient=True - ) - self.fields['IP_START_ADDRESS'] = Field( - text="Infrastructure network start address", - type=TYPES.string, - initial="192.168.205.2", - ) - self.fields['IP_END_ADDRESS'] = Field( - text="Infrastructure network end address", - type=TYPES.string, - initial="192.168.205.254", - ) - - # This field show/hides all other fields - self.fields['use_infra'].shows = [field for field in self.fields.keys() - if field is not 'use_infra'] - - def validate_page(self): - super(INFRAPage, self).validate_page() - - def get_config(self): - if self.fields['use_infra'].get_value() is 'N': - if config.has_section(self.section): - config.remove_section(self.section) - clean_lis() - return - - super(INFRAPage, self).get_config() - - # Add logical interface - ports = self.fields['infra_port1'].get_value() - if self.fields['infra_port2'].get_value(): - ports += "," + self.fields['infra_port2'].get_value() - li = create_li( - lag=self.fields['LAG_INTERFACE'].get_value(), - mode=self.lag_choices.get(self.fields['LAG_MODE'].get_value()), - mtu=self.fields['INTERFACE_MTU'].get_value(), - ports=ports - ) - config.set(self.section, 'LOGICAL_INTERFACE', li) - clean_lis() - - if len(config.items(self.section)) == 0: - config.remove_section(self.section) - - -class OAMPage(ConfigPage): - def load(self): - super(OAMPage, self).load() - - self.lag_choices = OrderedDict([ - ('Active-backup policy', '1'), - ('Balanced XOR policy', '2'), - ('802.3ad (LACP) policy', '4'), - ]) - - self.section = "OAM_NETWORK" - if get_opt('SYSTEM', 'SYSTEM_MODE') == 'simplex': - self.simplex = True - self.validator_methods = ["validate_aio_network"] - else: - self.simplex = False - self.validator_methods = ["validate_pxeboot", - "validate_mgmt", - "validate_infra", - "validate_oam"] - self.title = "External OAM Network" - self.help_text = ( - "The external OAM network is used for management of the " - "cloud. It also provides access to the " - "platform APIs. IP addresses on this network are reachable " - "outside the data center.") - - self.set_fields() - self.do_setup() - self.bind_events() - - def set_fields(self): - self.fields['oam_port1'] = Field( - text="External OAM interface", - type=TYPES.string, - initial="enp0s3", - transient=True - ) - self.fields['lag_help'] = Field( - text="An external OAM bond interface provides redundant " - "connections for the OAM network. When selected, the " - "field above specifies the first member of the bond.", - type=TYPES.help, - ) - self.fields['LAG_INTERFACE'] = Field( - text="External OAM interface link aggregation", - type=TYPES.checkbox, - shows=["LAG_MODE", "oam_port2"], - transient=True - ) - self.fields['LAG_MODE'] = Field( - text="OAM interface bonding policy", - type=TYPES.choice, - choices=self.lag_choices.keys(), - transient=True - ) - self.fields['oam_port2'] = Field( - text="Second External OAM interface member", - type=TYPES.string, - initial="", - transient=True - ) - self.fields['INTERFACE_MTU'] = Field( - text="External OAM interface MTU", - type=TYPES.int, - initial="1500", - transient=True - ) - - # VLAN - self.fields['use_vlan'] = Field( - text="Configure an External OAM VLAN", - type=TYPES.checkbox, - shows=["VLAN"], - transient=True - ) - self.fields['VLAN'] = Field( - text="External OAM VLAN Identifier", - type=TYPES.int, - initial="", - ) - - self.fields['CIDR'] = Field( - text="External OAM subnet", - type=TYPES.string, - initial="10.10.10.0/24", - ) - self.fields['GATEWAY'] = Field( - text="External OAM gateway address", - type=TYPES.string, - initial="10.10.10.1", - ) - if not self.simplex: - self.fields['IP_FLOATING_ADDRESS'] = Field( - text="External OAM floating address", - type=TYPES.string, - initial="10.10.10.2", - ) - self.fields['IP_UNIT_0_ADDRESS'] = Field( - text="External OAM address for first controller node", - type=TYPES.string, - initial="10.10.10.3", - ) - self.fields['IP_UNIT_1_ADDRESS'] = Field( - text="External OAM address for second controller node", - type=TYPES.string, - initial="10.10.10.4", - ) - else: - self.fields['IP_ADDRESS'] = Field( - text="External OAM address", - type=TYPES.string, - initial="10.10.10.2", - ) - - def get_config(self): - super(OAMPage, self).get_config() - - # Add logical interface - ports = self.fields['oam_port1'].get_value() - if self.fields['oam_port2'].get_value(): - ports += "," + self.fields['oam_port2'].get_value() - li = create_li( - lag=self.fields['LAG_INTERFACE'].get_value(), - mode=self.lag_choices.get(self.fields['LAG_MODE'].get_value()), - mtu=self.fields['INTERFACE_MTU'].get_value(), - ports=ports - ) - config.set(self.section, 'LOGICAL_INTERFACE', li) - clean_lis() - - def validate_page(self): - super(OAMPage, self).validate_page() - # Do page specific validation here - - -class AUTHPage(ConfigPage): - def load(self): - super(AUTHPage, self).load() - self.section = "AUTHENTICATION" - self.validator_methods = ["validate_authentication"] - self.title = "Authentication" - self.help_text = ( - "Create the admin user password.\n" - "It must have a minimum length of 7 characters, and must " - "contain at least 1 upper case, 1 lower case, 1 digit, " - "and 1 special character.\n\n" - "Note: This password will be stored as plaintext in the generated " - "INI file.") - - self.set_fields() - self.do_setup() - self.bind_events() - - def set_fields(self): - self.fields['ADMIN_PASSWORD'] = Field( - text="Password", - type=TYPES.string, - ) - - def get_config(self): - super(AUTHPage, self).get_config() - - def validate_page(self): - super(AUTHPage, self).validate_page() - # Do page specific validation here - - -class ENDPage(WizardPage): - # Final page for file saving - def load(self): - super(ENDPage, self).load() - # Must ensure fields are destroyed/don't exist before adding to - # prevent double-loading - self.sizer.Clear(True) - - self.set_title("Configuration Complete") - self.add_content( - wx.StaticText(self, -1, 'Titanium Cloud Configuration is ' - 'complete, configuration file may now be ' - 'saved.')) - - self.write_button = wx.Button(self, -1, "Save Configuration File") - self.Bind(wx.EVT_BUTTON, self.on_save, self.write_button) - self.add_content(self.write_button) - - # Add the version to the config - if not config.has_section("VERSION"): - config.add_section("VERSION") - config.set("VERSION", "RELEASE", TiS_VERSION) - - self.preview = wx.TextCtrl(self, -1, value=get_config(), - style=wx.TE_MULTILINE | wx.TE_READONLY) - self.add_content(self.preview, 3) - - def on_save(self, event): - writer = wx.FileDialog(self, - message="Save Configuration File", - defaultDir=filedir or "", - defaultFile=filename or "TiC_config.ini", - wildcard="INI file (*.ini)|*.ini", - style=wx.FD_SAVE, - ) - - if writer.ShowModal() == wx.ID_CANCEL: - return - - # Write the configuration to disk - try: - with open(writer.GetPath(), "wb") as f: - config.write(f) - except IOError: - wx.LogError("Error writing configuration file '%s'." % - writer.GetPath()) - - -# todo tsmith include a 'reformat' to shuffle numbers down? -def clean_lis(): - # Remove unreferenced Logical Interfaces in the config - referenced = [] - for sec in config.sections(): - if config.has_option(sec, 'LOGICAL_INTERFACE'): - referenced.append(config.get(sec, 'LOGICAL_INTERFACE')) - - for sec in config.sections(): - if "LOGICAL_INTERFACE_" in sec and sec not in referenced: - config.remove_section(sec) - - -def create_li(lag='N', mode=None, mtu=1500, ports=None): - # todo more graceful matching to an existing LI - for number in range(1, len(config.sections())): - if config.has_section("LOGICAL_INTERFACE_" + str(number)): - debug("Found interface " + str(number) + " with ports " + - config.get("LOGICAL_INTERFACE_" + str(number), - 'INTERFACE_PORTS') - + ". Searching for ports: " + ports) - if config.get("LOGICAL_INTERFACE_" + str(number), - 'INTERFACE_PORTS') == ports: - debug("Matched to LI: " + str(number)) - - # This logical interface already exists, - # so use that but update any values - name = "LOGICAL_INTERFACE_" + str(number) - config.set(name, 'LAG_INTERFACE', lag) - if mode: - config.set(name, 'LAG_MODE', mode) - config.set(name, 'INTERFACE_MTU', mtu) - return name - - # Get unused LI number - number = 1 - while config.has_section("LOGICAL_INTERFACE_" + str(number)): - number += 1 - - # LI doesnt exist so create it with the given values - name = "LOGICAL_INTERFACE_" + str(number) - config.add_section(name) - config.set(name, 'LAG_INTERFACE', lag) - if mode: - config.set(name, 'LAG_MODE', mode) - config.set(name, 'INTERFACE_MTU', mtu) - config.set(name, 'INTERFACE_PORTS', ports) - return name - - -def main(): - app = wx.App(0) # Start the application - - # Create wizard and add the pages to it - conf_wizard = ConfigWizard() - - # Start the wizard - conf_wizard.run() - - # Cleanup - conf_wizard.Destroy() - app.MainLoop() - - -if __name__ == '__main__': - main() diff --git a/configutilities/configutilities/configutilities/configgui.py b/configutilities/configutilities/configutilities/configgui.py deleted file mode 100755 index 9260a15ee7..0000000000 --- a/configutilities/configutilities/configutilities/configgui.py +++ /dev/null @@ -1,114 +0,0 @@ -""" -Copyright (c) 2015-2017 Wind River Systems, Inc. - -SPDX-License-Identifier: Apache-2.0 - -""" - -import wx - -from configutilities.common.guicomponents import set_icons -from configutilities.common.validator import TiS_VERSION -from configutilities import configfiletool -from configutilities import hostfiletool - -TEXT_WIDTH = 560 -BTN_SIZE = (200, -1) - - -class WelcomeScreen(wx.Frame): - def __init__(self, *args, **kwargs): - super(WelcomeScreen, self).__init__(*args, **kwargs) - page = Content(self) - - set_icons(self) - - size = page.main_sizer.Fit(self) - self.SetMinSize(size) - self.Layout() - - -class Content(wx.Panel): - def __init__(self, *args, **kwargs): - super(Content, self).__init__(*args, **kwargs) - - self.title = wx.StaticText( - self, -1, - 'Titanium Cloud Configuration Utility') - self.title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)) - - # Set up controls for the main page - self.description = wx.StaticText( - self, -1, - ' Welcome, The following tools are available for use:') - - self.config_desc = wx.StaticText( - self, -1, - "The Titanium Cloud configuration file wizard allows users to " - "create the configuration INI file which is used during the " - "installation process") - self.config_desc.Wrap(TEXT_WIDTH / 2) - self.hosts_desc = wx.StaticText( - self, -1, - "The Titanium Cloud host file tool allows users to create an XML " - "file specifying hosts to be provisioned as part of the Titanium " - "Cloud cloud deployment.") - self.hosts_desc.Wrap(TEXT_WIDTH / 2) - - self.config_wiz_btn = wx.Button( - self, -1, "Launch Config File Wizard", size=BTN_SIZE) - self.Bind(wx.EVT_BUTTON, self.launch_config_wiz, self.config_wiz_btn) - - self.host_file_tool_btn = wx.Button( - self, -1, "Launch Host File Tool", size=BTN_SIZE) - self.Bind(wx.EVT_BUTTON, self.launch_host_wiz, self.host_file_tool_btn) - - self.box1 = wx.StaticBox(self) - self.box2 = wx.StaticBox(self) - - # Do layout of controls - self.main_sizer = wx.BoxSizer(wx.VERTICAL) - self.tool1Sizer = wx.StaticBoxSizer(self.box1, wx.HORIZONTAL) - self.tool2Sizer = wx.StaticBoxSizer(self.box2, wx.HORIZONTAL) - - self.main_sizer.AddSpacer(10) - self.main_sizer.Add(self.title, flag=wx.ALIGN_CENTER) - self.main_sizer.AddSpacer(10) - self.main_sizer.Add(self.description) - self.main_sizer.AddSpacer(5) - self.main_sizer.Add(self.tool1Sizer, proportion=1, flag=wx.EXPAND) - self.main_sizer.Add(self.tool2Sizer, proportion=1, flag=wx.EXPAND) - self.main_sizer.AddSpacer(5) - - self.tool1Sizer.Add(self.config_desc, flag=wx.ALIGN_CENTER) - self.tool1Sizer.AddSpacer(10) - self.tool1Sizer.Add(self.config_wiz_btn, flag=wx.ALIGN_CENTER) - self.tool2Sizer.Add(self.hosts_desc, flag=wx.ALIGN_CENTER) - self.tool2Sizer.AddSpacer(10) - self.tool2Sizer.Add(self.host_file_tool_btn, flag=wx.ALIGN_CENTER) - - self.SetSizer(self.main_sizer) - - self.Layout() - - def launch_config_wiz(self, event): - conf_wizard = configfiletool.ConfigWizard() - conf_wizard.run() - conf_wizard.Destroy() - - def launch_host_wiz(self, event): - hostfiletool.HostGUI() - - -def main(): - app = wx.App(0) # Start the application - - gui = WelcomeScreen(None, title="Titanium Cloud Configuration Utility v" - + TiS_VERSION) - gui.Show() - app.MainLoop() - app.Destroy() - - -if __name__ == '__main__': - main() diff --git a/configutilities/configutilities/configutilities/hostfiletool.py b/configutilities/configutilities/configutilities/hostfiletool.py deleted file mode 100755 index 3f4e4356cf..0000000000 --- a/configutilities/configutilities/configutilities/hostfiletool.py +++ /dev/null @@ -1,515 +0,0 @@ -""" -Copyright (c) 2015-2017 Wind River Systems, Inc. - -SPDX-License-Identifier: Apache-2.0 - -""" - -from collections import OrderedDict -import netaddr -import xml.etree.ElementTree as ET - -import wx - -from configutilities.common import utils -from configutilities.common import exceptions -from configutilities.common.guicomponents import Field -from configutilities.common.guicomponents import TYPES -from configutilities.common.guicomponents import prepare_fields -from configutilities.common.guicomponents import on_change -from configutilities.common.guicomponents import set_icons -from configutilities.common.guicomponents import handle_sub_show -from configutilities.common.configobjects import HOST_XML_ATTRIBUTES -from configutilities.common.validator import TiS_VERSION - -PAGE_SIZE = (200, 200) -WINDOW_SIZE = (570, 700) -CB_TRUE = True -CB_FALSE = False -PADDING = 10 - -IMPORT_ID = 100 -EXPORT_ID = 101 - -INTERNAL_ID = 105 -EXTERNAL_ID = 106 - -filedir = "" -filename = "" - -# Globals -BULK_ADDING = False - - -class HostPage(wx.Panel): - def __init__(self, parent): - wx.Panel.__init__(self, parent=parent) - - self.parent = parent - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.SetSizer(self.sizer) - self.fieldgroup = [] - self.fieldgroup.append(OrderedDict()) - self.fieldgroup.append(OrderedDict()) - self.fieldgroup.append(OrderedDict()) - - self.fields_sizer1 = wx.GridBagSizer(vgap=10, hgap=10) - self.fields_sizer2 = wx.GridBagSizer(vgap=10, hgap=10) - self.fields_sizer3 = wx.GridBagSizer(vgap=10, hgap=10) - - # Basic Fields - self.fieldgroup[0]['personality'] = Field( - text="Personality", - type=TYPES.choice, - choices=['compute', 'controller', 'storage'], - initial='compute' - ) - self.fieldgroup[0]['hostname'] = Field( - text="Hostname", - type=TYPES.string, - initial=parent.get_next_hostname() - ) - self.fieldgroup[0]['mgmt_mac'] = Field( - text="Management MAC Address", - type=TYPES.string, - initial="" - ) - self.fieldgroup[0]['mgmt_ip'] = Field( - text="Management IP Address", - type=TYPES.string, - initial="" - ) - self.fieldgroup[0]['location'] = Field( - text="Location", - type=TYPES.string, - initial="" - ) - - # Board Management - self.fieldgroup[1]['uses_bm'] = Field( - text="This host uses Board Management", - type=TYPES.checkbox, - initial="", - shows=['bm_ip', 'bm_username', - 'bm_password', 'power_on'], - transient=True - ) - self.fieldgroup[1]['bm_ip'] = Field( - text="Board Management IP Address", - type=TYPES.string, - initial="" - ) - self.fieldgroup[1]['bm_username'] = Field( - text="Board Management username", - type=TYPES.string, - initial="" - ) - self.fieldgroup[1]['bm_password'] = Field( - text="Board Management password", - type=TYPES.string, - initial="" - ) - self.fieldgroup[1]['power_on'] = Field( - text="Power on host", - type=TYPES.checkbox, - initial="N", - transient=True - ) - - # Installation Parameters - self.fieldgroup[2]['boot_device'] = Field( - text="Boot Device", - type=TYPES.string, - initial="" - ) - self.fieldgroup[2]['rootfs_device'] = Field( - text="Rootfs Device", - type=TYPES.string, - initial="" - ) - self.fieldgroup[2]['install_output'] = Field( - text="Installation Output", - type=TYPES.choice, - choices=['text', 'graphical'], - initial="text" - ) - self.fieldgroup[2]['console'] = Field( - text="Console", - type=TYPES.string, - initial="" - ) - - prepare_fields(self, self.fieldgroup[0], self.fields_sizer1, - self.on_change) - prepare_fields(self, self.fieldgroup[1], self.fields_sizer2, - self.on_change) - prepare_fields(self, self.fieldgroup[2], self.fields_sizer3, - self.on_change) - - # Bind button handlers - self.Bind(wx.EVT_CHOICE, self.on_personality, - self.fieldgroup[0]['personality'].input) - - self.Bind(wx.EVT_TEXT, self.on_hostname, - self.fieldgroup[0]['hostname'].input) - - # Control Buttons - self.button_sizer = wx.BoxSizer(orient=wx.HORIZONTAL) - - self.add = wx.Button(self, -1, "Add a New Host") - self.Bind(wx.EVT_BUTTON, self.on_add, self.add) - - self.remove = wx.Button(self, -1, "Remove this Host") - self.Bind(wx.EVT_BUTTON, self.on_remove, self.remove) - - self.button_sizer.Add(self.add) - self.button_sizer.Add(self.remove) - - # Add fields and spacers - self.sizer.Add(self.fields_sizer1) - self.sizer.AddWindow(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.ALL, - PADDING) - self.sizer.Add(self.fields_sizer2) - self.sizer.AddWindow(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.ALL, - PADDING) - self.sizer.Add(self.fields_sizer3) - self.sizer.AddStretchSpacer() - self.sizer.AddWindow(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.ALL, - PADDING) - self.sizer.Add(self.button_sizer, border=10, flag=wx.CENTER) - - def on_hostname(self, event, string=None): - """Update the List entry text to match the new hostname - """ - string = string or event.GetString() - index = self.parent.GetSelection() - self.parent.SetPageText(index, string) - self.parent.parent.Layout() - - def on_personality(self, event, string=None): - """Remove hostname field if it's a storage or controller - """ - string = string or event.GetString() - index = self.parent.GetSelection() - if string == 'compute': - self.fieldgroup[0]['hostname'].show(True) - self.parent.SetPageText(index, - self.fieldgroup[0]['hostname'].get_value()) - return - elif string == 'controller': - self.fieldgroup[0]['hostname'].show(False) - elif string == 'storage': - self.fieldgroup[0]['hostname'].show(False) - self.parent.SetPageText(index, string) - self.parent.Layout() - - def on_add(self, event): - try: - self.validate() - except Exception as ex: - wx.LogError("Error on page: " + ex.message) - return - - self.parent.new_page() - - def on_remove(self, event): - if self.parent.GetPageCount() is 1: - wx.LogError("Must leave at least one host") - return - index = self.parent.GetSelection() - self.parent.DeletePage(index) - - def to_xml(self): - """Create the XML for this host - """ - self.validate() - - attrs = "" - # Generic handling - for fgroup in self.fieldgroup: - for name, field in fgroup.items(): - if field.transient or not field.get_value(): - continue - attrs += "\t\t<" + name + ">" + \ - field.get_value() + "\n" - - # Special Fields - if self.fieldgroup[1]['power_on'].get_value() is 'Y': - attrs += "\t\t\n" - - if self.fieldgroup[1]['uses_bm'].get_value() is 'Y': - attrs += "\t\tbmc\n" - - return "\t\n" + attrs + "\t\n" - - def validate(self): - if self.fieldgroup[0]['personality'].get_value() == "compute" and not \ - utils.is_valid_hostname( - self.fieldgroup[0]['hostname'].get_value()): - raise exceptions.ValidateFail( - "Hostname %s is not valid" % - self.fieldgroup[0]['hostname'].get_value()) - - if not utils.is_valid_mac(self.fieldgroup[0]['mgmt_mac'].get_value()): - raise exceptions.ValidateFail( - "Management MAC address %s is not valid" % - self.fieldgroup[0]['mgmt_mac'].get_value()) - - ip = self.fieldgroup[0]['mgmt_ip'].get_value() - if ip: - try: - netaddr.IPAddress(ip) - except Exception: - raise exceptions.ValidateFail( - "Management IP address %s is not valid" % ip) - - if self.fieldgroup[1]['uses_bm'].get_value() == 'Y': - ip = self.fieldgroup[1]['bm_ip'].get_value() - if ip: - try: - netaddr.IPAddress(ip) - except Exception: - raise exceptions.ValidateFail( - "Board Management IP address %s is not valid" % ip) - - else: - raise exceptions.ValidateFail( - "Board Management IP is not specified. " - "External Board Management Network requires Board " - "Management IP address.") - - def on_change(self, event): - on_change(self, self.fieldgroup[1], event) - - def set_field(self, name, value): - for fgroup in self.fieldgroup: - for fname, field in fgroup.items(): - if fname == name: - field.set_value(value) - - -class HostBook(wx.Listbook): - def __init__(self, parent): - wx.Listbook.__init__(self, parent, style=wx.BK_DEFAULT) - - self.parent = parent - self.Layout() - # Add a starting host - self.new_page() - - self.Bind(wx.EVT_LISTBOOK_PAGE_CHANGED, self.on_changed) - self.Bind(wx.EVT_LISTBOOK_PAGE_CHANGING, self.on_changing) - - def on_changed(self, event): - event.Skip() - - def on_changing(self, event): - # Trigger page validation before leaving - if BULK_ADDING: - event.Skip() - return - index = self.GetSelection() - try: - if index != -1: - self.GetPage(index).validate() - except Exception as ex: - wx.LogError("Error on page: " + ex.message) - event.Veto() - return - event.Skip() - - def new_page(self, hostname=None): - new_page = HostPage(self) - self.AddPage(new_page, hostname or self.get_next_hostname()) - self.SetSelection(self.GetPageCount() - 1) - return new_page - - def get_next_hostname(self, suggest=None): - prefix = "compute-" - new_suggest = suggest or 0 - - for existing in range(self.GetPageCount()): - if prefix + str(new_suggest) in self.GetPageText(existing): - new_suggest = self.get_next_hostname(suggest=new_suggest + 1) - - if suggest: - prefix = "" - return prefix + str(new_suggest) - - def to_xml(self): - """Create the complete XML and allow user to save - """ - xml = "\n" \ - "\n" - for index in range(self.GetPageCount()): - try: - xml += self.GetPage(index).to_xml() - except Exception as ex: - wx.LogError("Error on page number %s: %s" % - (index + 1, ex.message)) - return - xml += "" - - writer = wx.FileDialog(self, - message="Save Host XML File", - defaultDir=filedir or "", - defaultFile=filename or "TiS_hosts.xml", - wildcard="XML file (*.xml)|*.xml", - style=wx.FD_SAVE, - ) - - if writer.ShowModal() == wx.ID_CANCEL: - return - - # Write the XML file to disk - try: - with open(writer.GetPath(), "wb") as f: - f.write(xml.encode('utf-8')) - except IOError: - wx.LogError("Error writing hosts xml file '%s'." % - writer.GetPath()) - - -class HostGUI(wx.Frame): - def __init__(self): - wx.Frame.__init__(self, None, wx.ID_ANY, - "Titanium Cloud Host File Creator v" + TiS_VERSION, - size=WINDOW_SIZE) - self.panel = wx.Panel(self) - - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.book = HostBook(self.panel) - self.sizer.Add(self.book, 1, wx.ALL | wx.EXPAND, 5) - self.panel.SetSizer(self.sizer) - set_icons(self) - - menu_bar = wx.MenuBar() - - # File - file_menu = wx.Menu() - import_item = wx.MenuItem(file_menu, IMPORT_ID, '&Import') - file_menu.AppendItem(import_item) - export_item = wx.MenuItem(file_menu, EXPORT_ID, '&Export') - file_menu.AppendItem(export_item) - menu_bar.Append(file_menu, '&File') - self.Bind(wx.EVT_MENU, self.on_import, id=IMPORT_ID) - self.Bind(wx.EVT_MENU, self.on_export, id=EXPORT_ID) - - self.SetMenuBar(menu_bar) - self.Layout() - self.SetMinSize(WINDOW_SIZE) - self.Show() - - def on_import(self, e): - global BULK_ADDING - try: - BULK_ADDING = True - msg = "" - - reader = wx.FileDialog(self, - "Import Existing Titanium Cloud Host File", - "", "", "XML file (*.xml)|*.xml", - wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) - - if reader.ShowModal() == wx.ID_CANCEL: - return - - # Read in the config file - try: - with open(reader.GetPath(), 'rb') as f: - contents = f.read() - root = ET.fromstring(contents) - except Exception as ex: - wx.LogError("Cannot parse host file, Error: %s." % ex) - return - - # Check version of host file - if root.get('version', "") != TiS_VERSION: - msg += "Warning: This file was created using tools for a " \ - "different version of Titanium Cloud than this tool " \ - "was designed for (" + TiS_VERSION + ")" - - for idx, xmlhost in enumerate(root.findall('host')): - hostname = None - name_elem = xmlhost.find('hostname') - if name_elem is not None: - hostname = name_elem.text - new_host = self.book.new_page() - self.book.GetSelection() - try: - for attr in HOST_XML_ATTRIBUTES: - elem = xmlhost.find(attr) - if elem is not None and elem.text: - # Enable and display bm section if used - if attr == 'bm_type' and elem.text: - new_host.set_field("uses_bm", "Y") - handle_sub_show( - new_host.fieldgroup[1], - new_host.fieldgroup[1]['uses_bm'].shows, - True) - new_host.Layout() - - # Basic field setting - new_host.set_field(attr, elem.text) - - # Additional functionality for special fields - if attr == 'personality': - # Update hostname visibility and page title - new_host.on_personality(None, elem.text) - - # Special handling for presence of power_on element - if attr == 'power_on' and elem is not None: - new_host.set_field(attr, "Y") - - new_host.validate() - except Exception as ex: - if msg: - msg += "\n" - msg += "Warning: Added host %s has a validation error, " \ - "reason: %s" % \ - (hostname or ("with index " + str(idx)), - ex.message) - # No longer delete hosts with validation errors, - # The user can fix them up before exporting - # self.book.DeletePage(new_index) - - if msg: - wx.LogWarning(msg) - finally: - BULK_ADDING = False - self.Layout() - - def on_export(self, e): - # Do a validation of current page first - index = self.book.GetSelection() - try: - if index != -1: - self.book.GetPage(index).validate() - except Exception as ex: - wx.LogError("Error on page: " + ex.message) - return - - # Check for hostname conflicts - hostnames = [] - for existing in range(self.book.GetPageCount()): - hostname = self.book.GetPage( - existing).fieldgroup[0]['hostname'].get_value() - if hostname in hostnames: - wx.LogError("Cannot export, duplicate hostname '%s'" % - hostname) - return - # Ignore multiple None hostnames - elif hostname: - hostnames.append(hostname) - - self.book.to_xml() - - -def main(): - app = wx.App(0) # Start the application - HostGUI() - app.MainLoop() - - -if __name__ == '__main__': - main() diff --git a/configutilities/configutilities/configutilities/setup.py b/configutilities/configutilities/configutilities/setup.py deleted file mode 100755 index b946b6a7a8..0000000000 --- a/configutilities/configutilities/configutilities/setup.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Copyright (c) 2016-2017 Wind River Systems, Inc. - -SPDX-License-Identifier: Apache-2.0 - -""" - -from setuptools import setup -from setuptools import find_packages - -setup( - name='wrs-configutility', - description='Titanium Cloud Configuration Utility', - version='3.1.0', - license='Apache-2.0', - platforms=['any'], - provides=['configutilities'], - packages=find_packages(), - install_requires=['netaddr>=0.7.14', 'six'], - package_data={}, - include_package_data=False, - entry_points={ - 'gui_scripts': [ - 'config_gui = configutilities.configgui:main', - ], - 'console_scripts': [ - 'config_validator = configutilities.config_validator:main' - ], - } -) diff --git a/configutilities/configutilities/favicon.ico b/configutilities/configutilities/favicon.ico deleted file mode 100755 index 3820c51ecf0391b57d6b4cf7d94eae666138f43d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32988 zcmeHP2XGa|8^2HlR1lS>G7?Z31RIJvq9~%Gj#yE^f-;DRy<&F&yN8BjxqIooHxz+B*SZ=WJth?}f&;RS+KbD3L zjib?{6KKqs1Ulr9L^}B31R6XzuG{$TvrjA?bWl8lm)KE<509q-17f=gvp47$V>E7D z5-na_KySTOPODc}(EIQ2q$i&&qw~(oq9H?oZ`Z~xD#}Nvo|;apR+Z2@?^Mvc?^bZQ z4?IvzlP0D3>F*lM-jRPn|C~A5v}H>jwY2P|_V&HBcP~*zMJv7jdO00_coM_c?82B? zG-53b<)$O?3VBd9?rjkgKl1>@EFgaalf}=34YF)kwIU7T@wh7>gw9*wb#n&sH2kq0rU%8k3KquKK-rcO-@W4r`Ek2oTk)~u=GbIA>8Y3Uxi{q{oIcVDSj!sSEc=^r&J zk)D3KjLp+lH&nSENKbE~tFO*udRvZz*H!TI$}4lovfTNJPWG^A2Aw!@BIbbLS$H-v zvh+tqS#;uwY4rW~HC#WrGJrj7XlSSBo-3oVV-q{U*Q7%aO{AAz+QD_F7d$-w~#mpCg-EzY>hWk2q-Bm=}w+Gvi zK%lURpM6%veF4a!JIp{HM3(-UGc)LyUuxNWWX4`8ZHyg|`Q5wi=V-HbZ55xh?)b*g zNhhVz`t{Y++-!dbKLWq2s@k~iQ@UX~qJisP=-}{dOXTQBpEuuJNJT|0DoR{#%gbBo z_uuO&E^fEuooO}@blc#;7#FAS0-tu_!hFiibj~I44bQ&(au@ymcLUd_5-9u)=-!bd zp;w&n-1T83=ohkf#x3A&Sb!L3gF8@4OWi?FA%U=DouU5($iy3MKHkblw7MHgjrJtc9GSIGSb zA5_u_C#2GX1$oSevE>8!{`_+-_v`KXD&SpmNj8@m2}fQ_O5i^g^Y{lmC@8Sup$&BJ zf(5yXFAzwx`a3e?KV(QeJ@n9aDk%xpQ+RgA9Yq|UsZ&$wn{R3yGLo0qOgG(Bz+*)r z0~Q@{Ks>EnSrTOPF!v!#@So8Z@z4)HIBo5&U2R;Z#*GVS4)m0Mix8JhoR~tNd{Rm9 zMb#ql6?QI$MvY2fHflSSm)m@*uW#qE;pEAwjHVb?Et)nho%#B^R8aiBwziGldv7Pf z&KSlvI_$7S9uMx^Y5Q6&E$#HnHii%?(<&CKu_s6xo>{?>eevF=f8@vndg6&v7T4HgD)Gi#zx(bYCeN_(7+aI`;=>Os9kvTH z3%S60Npy5F;eBJHt=A+x#DB1fB6fs+H@WP=?nBSW0-Xz8E96AzQ+Gb}eEg3;Ud(CL zMoT52oj*U9uR%zf6vHB2xBS>=0HkH6Q!m$Is84mhn-x# zdMER3-QqiouQ4J)4-us&$R^5Cg&=4(=N^!=kIM z%5~^W%mL7eihH%d|G)LtLau9r=ds0Q3Tt4AiOv}L&p+$ge99uMn~M3Tjy>+XPe1%! z*lolyfdxJu%)G#J`g#dySt8 zFNUuHV|~4@&entQ4Ogx#_0L6j`bUh2OCLSDkgv&No!zUB8Wqp=>6|$^e2n2|1QzIT zj2G5yLyZ^Sp$+^#jFDT(&u^jS%Zr)42xn~{>+T|EhV79BIKtMt%cB_o<;#oGAA78p zu$L05Voe`@)z+=`4*yN|1)KBLS2c9ZG4SQRW!08pp$FHks|>PvfQfalS+g<}|4AKh zw|k4nzOX&24S_#=}Hm2w26Zc6GcZ90&Q4nvyN5vXH zD(>Us8~J(`_V>bHe}X?4%VaZy+d{-av9XOj9zy&#Z(gp8{}h^j#6;(wn?)agT*+~Y zixV*6TOM~@;69^Mv959LwRy}&XL9}{CJtBrF%IzQ zPd`1K?+IZ27<&VtVeDAdcMe6jd?(^@>@%NrRwl;@cmW<_aIxO5;wI>4db&^KKZ|jZ zyuww|AH(R+_K%sIAKksG@Vj#F)?Zh?4{RF_JV}4w7=Nek2fsA^j3+w(zmMoYE&qW! zQqO-q|F!<>EB>F>e_H=JWkBnHt^c9_Ep`UD${!CvCi+SR&1N~1fgf1>%VJ=}fqkih zX5S|Kp8))KfSIgz@_zytzXElr{;heUW#FGD1M2!$sPPH6T__mNcUb>M?giFer%%t| zIZ|HynKmtr=fz!oakf8q*9pt(JMZTfoqTdyNA4Kb<#Arftv${X;XDQk^03Z7U*?PS z1P6=lIhSyl_=9{+tm6l-hg*E_OWi-l-klqsU3rGw3gn8Y1$&6t7f|8gH}Zzmg1tMj zZ`ob?Ew*l->BvO_eB`AfPsrwh*r!7Nr&_#u6+S-LpOXdqQ8Fh4dv|vKK6VzXR5s)J zw8%d}S-ZB9@5!jV3ilrQ4k;=2UMBXTWF8;#7O^h@9MDegd4lF8OA1(Cq{#QfUY$70 z6F$uXKao=ccqrKSMNY)Rg?T(L5psq(#{3(en;`edvA>SI#KnvAd9E_{4UyNO@+utq zv5y7b$+CHKE#Ke8o(uB!P>_#<95>`_%7T3<^o3latSphk1zw0fwD5TVo~gO8$T^iX zy!he{-W~Rnky|M9m2jOt9eE03-w6ASD9E7z@8tKL({Hi7#Db1JSIC{nxe&S)d2Ns{ zoQFc5pxm3?w5f*YJIe9H9u@Qu3iiFj?H~K-$a|J$!-i^q&X3?9aw?H$p%&m0IL^a{ z#dqW|WAAzBP~^?1W1!j!`yRZKc_)CoXiL9UamkTu*R zHw$wOXB&~L1GvcXQ@_JK`hpyy4ZZ^%Ds8eo^8Rs_3G^fH3H#&n9dd+&YYNW~L5>LC zAsR2qwmAxt>%;F zQ`cnx>jYz1J)!e;f;_{BuVy+T!WA%m47Sx^7&t!*zdn)`FaaBQyT=SYlN-R4Jozuf zN1may4Q_HKb1Vbjbu-vShz)e=6C;1_J|`t^292Kd64khU-se5=Ff>F_#+s^Jz)ysan3yQy!i^huIr2Ht=YtQz*9VUze3R)P5i5#$B;*Ed zajss4k8=^SApg{UCwPu?LCA>~zC4FnJ#e7KY7)nze}9Yn#>hKF*|1@kABL1UA3K97 z9sb{x`rCbu0=_+Wo$YO305HY525)@iw_aB-n&cX_ z*LU){^LyYdtH4QZ=XEdFb?`p0sPOR)zp*}utNbn6c=N#PeQ4e}>F|Q_-+IoJgf5x` zngf~xngf~xngf~xngf~xngf~xngf~xngf~xngf~xngf~xngf~xngf~xngf~xngf~x Ungf~xngf~xngf~x|0)jrADGE8tN;K2 diff --git a/configutilities/configutilities/pylint.rc b/configutilities/configutilities/pylint.rc deleted file mode 100755 index 5c51c4c3ba..0000000000 --- a/configutilities/configutilities/pylint.rc +++ /dev/null @@ -1,233 +0,0 @@ -[MASTER] -# Specify a configuration file. -rcfile=pylint.rc - -# Python code to execute, usually for sys.path manipulation such as pygtk.require(). -#init-hook= - -# Add files or directories to the blacklist. They should be base names, not paths. -ignore=tests - -# Pickle collected data for later comparisons. -persistent=yes - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time. -#enable= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). -# https://pylint.readthedocs.io/en/latest/user_guide/output.html#source-code-analysis-section -# We are disabling (C)onvention -# We are disabling (R)efactor -# The following warnings should be fixed: -# fixme (todo, xxx, fixme) -# W0102: dangerous-default-value -# W0106: expression-not-assigned -# W0107: unnecessary-pass -# W0201: attribute-defined-outside-init -# W0231: super-init-not-called -# W0235: useless-super-delegation -# W0311: bad-indentation -# W0603: global-statement -# W0611: unused-import -# W0612: unused-variable -# W0613: unused-argument -# W0622: redefined-builtin -# W0703: broad-except -# W1401: anomalous-backslash-in-string -# E0401: import-error -# E1101: no-member -disable=C, R, fixme, W0102, W0106, W0107, W0201, W0231, W0235, W0311, - W0603, W0611, W0612, W0613, W0622, W0703, W1401, E0401, E1101 - -[REPORTS] -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html -output-format=text - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells whether to display a full report or only the messages -reports=no - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - - -[SIMILARITIES] -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - - -[FORMAT] -# Maximum number of characters on a single line. -max-line-length=85 - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 tab). -indent-string=' ' - - -[TYPECHECK] -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of classes names for which member attributes should not be checked -# (useful for classes with attributes dynamically set). -ignored-classes=SQLObject - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E0201 when accessed. Python regular -# expressions are accepted. -generated-members=REQUEST,acl_users,aq_parent - - -[BASIC] -# List of builtins function names that should not be used, separated by a comma -bad-functions=map,filter,apply,input - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression which should only match functions or classes name which do -# not require a docstring -no-docstring-rgx=__.*__ - - -[MISCELLANEOUS] -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -[VARIABLES] -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching the beginning of the name of dummy variables -# (i.e. not used). -dummy-variables-rgx=_|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - - -[IMPORTS] -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,string,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - - -[DESIGN] -# Maximum number of arguments for function / method -max-args=5 - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branchs=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -[CLASSES] -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - - -[EXCEPTIONS] -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception diff --git a/configutilities/configutilities/setup.py b/configutilities/configutilities/setup.py deleted file mode 100755 index 9ac7b4cd7d..0000000000 --- a/configutilities/configutilities/setup.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Copyright (c) 2016 Wind River Systems, Inc. - -SPDX-License-Identifier: Apache-2.0 - -""" - -from setuptools import setup -from setuptools import find_packages - -setup( - name='configutilities', - description='Configuration File Validator', - version='3.1.0', - license='Apache-2.0', - platforms=['any'], - provides=['configutilities'], - packages=find_packages(), - install_requires=['netaddr>=0.7.14'], - package_data={}, - include_package_data=False, - entry_points={ - 'console_scripts': [ - 'config_validator = configutilities.config_validator:main', - ], - } -) diff --git a/configutilities/configutilities/test-requirements.txt b/configutilities/configutilities/test-requirements.txt deleted file mode 100644 index e069914668..0000000000 --- a/configutilities/configutilities/test-requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -# 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 diff --git a/configutilities/configutilities/tox.ini b/configutilities/configutilities/tox.ini deleted file mode 100644 index f9ac97717c..0000000000 --- a/configutilities/configutilities/tox.ini +++ /dev/null @@ -1,46 +0,0 @@ -# Tox (http://tox.testrun.org/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - -[tox] -envlist = flake8,pylint -# Tox does not work if the path to the workdir is too long, so move it to /tmp -toxworkdir = /tmp/{env:USER}_ccutiltox -stxdir = {toxinidir}/../../.. - - -[testenv] -whitelist_externals = find -install_command = pip install --no-cache-dir {opts} {packages} - -[testenv:venv] -commands = {posargs} - -[testenv:flake8] -basepython = python2.7 -deps = -r{toxinidir}/test-requirements.txt -commands = flake8 {posargs} - -# hacking pulls in flake8 2.5.5 which does not support parsing multi-line ignore list -# H series are hacking -# H102: Apache 2.0 license header not found -# H104: File contains nothing but comments -# H306: imports not in alphabetical order -# H401: docstring should not start with a space -# H403: multi line docstrings should end on a new line -# H404: multi line docstring should start without a leading new line -# H405: multi line docstring summary not separated with an empty line -[flake8] -ignore = H102,H104,H306,H401,H403,H404,H405 -exclude = dist,build - -[testenv:pylint] -basepython = python3 -sitepackages = False - -deps = -r{toxinidir}/test-requirements.txt - -e{[tox]stxdir}/stx-update/tsconfig/tsconfig - pylint -commands = - pylint {posargs} configutilities --rcfile=./pylint.rc diff --git a/controllerconfig/centos/build_srpm.data b/controllerconfig/centos/build_srpm.data index 8a80236ea8..04bab29441 100755 --- a/controllerconfig/centos/build_srpm.data +++ b/controllerconfig/centos/build_srpm.data @@ -1,2 +1,2 @@ SRC_DIR="controllerconfig" -TIS_PATCH_VER=150 +TIS_PATCH_VER=151 diff --git a/controllerconfig/controllerconfig/controllerconfig/__init__.py b/controllerconfig/controllerconfig/controllerconfig/__init__.py index 1d58fc700e..138851db64 100644 --- a/controllerconfig/controllerconfig/controllerconfig/__init__.py +++ b/controllerconfig/controllerconfig/controllerconfig/__init__.py @@ -1,5 +1,34 @@ # -# Copyright (c) 2015 Wind River Systems, Inc. +# Copyright (c) 2015-2019 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # + +from controllerconfig.common.validator import validate # noqa: F401 +from controllerconfig.common.configobjects import Network # noqa: F401 +from controllerconfig.common.configobjects import DEFAULT_CONFIG # noqa: F401 +from controllerconfig.common.configobjects import REGION_CONFIG # noqa: F401 +from controllerconfig.common.configobjects import DEFAULT_NAMES # noqa: F401 +from controllerconfig.common.configobjects import HP_NAMES # noqa: F401 +from controllerconfig.common.configobjects import SUBCLOUD_CONFIG # noqa: F401 +from controllerconfig.common.configobjects import MGMT_TYPE # noqa: F401 +from controllerconfig.common.configobjects import INFRA_TYPE # noqa: F401 +from controllerconfig.common.configobjects import OAM_TYPE # noqa: F401 +from controllerconfig.common.configobjects import NETWORK_PREFIX_NAMES # noqa: F401 +from controllerconfig.common.configobjects import HOST_XML_ATTRIBUTES # noqa: F401 +from controllerconfig.common.configobjects import DEFAULT_DOMAIN_NAME # noqa: F401 +from controllerconfig.common.exceptions import ConfigError # noqa: F401 +from controllerconfig.common.exceptions import ConfigFail # noqa: F401 +from controllerconfig.common.exceptions import ValidateFail # noqa: F401 +from controllerconfig.utils import is_valid_vlan # noqa: F401 +from controllerconfig.utils import is_mtu_valid # noqa: F401 +from controllerconfig.utils import validate_network_str # noqa: F401 +from controllerconfig.utils import validate_address_str # noqa: F401 +from controllerconfig.utils import validate_address # noqa: F401 +from controllerconfig.utils import is_valid_url # noqa: F401 +from controllerconfig.utils import is_valid_domain_or_ip # noqa: F401 +from controllerconfig.utils import ip_version_to_string # noqa: F401 +from controllerconfig.utils import lag_mode_to_str # noqa: F401 +from controllerconfig.utils import validate_openstack_password # noqa: F401 +from controllerconfig.utils import validate_nameserver_address_str # noqa: F401 +from controllerconfig.utils import extract_openstack_password_rules_from_file # noqa: F401 diff --git a/configutilities/configutilities/configutilities/common/configobjects.py b/controllerconfig/controllerconfig/controllerconfig/common/configobjects.py similarity index 96% rename from configutilities/configutilities/configutilities/common/configobjects.py rename to controllerconfig/controllerconfig/controllerconfig/common/configobjects.py index 003d73db2a..1866a7c996 100644 --- a/configutilities/configutilities/configutilities/common/configobjects.py +++ b/controllerconfig/controllerconfig/controllerconfig/common/configobjects.py @@ -1,17 +1,17 @@ """ -Copyright (c) 2015-2016 Wind River Systems, Inc. +Copyright (c) 2015-2019 Wind River Systems, Inc. SPDX-License-Identifier: Apache-2.0 """ from netaddr import IPRange -from configutilities.common.exceptions import ConfigFail -from configutilities.common.exceptions import ValidateFail -from configutilities.common.utils import is_mtu_valid -from configutilities.common.utils import is_valid_vlan -from configutilities.common.utils import validate_network_str -from configutilities.common.utils import validate_address_str +from controllerconfig.common.exceptions import ConfigFail +from controllerconfig.common.exceptions import ValidateFail +from controllerconfig.utils import is_mtu_valid +from controllerconfig.utils import is_valid_vlan +from controllerconfig.utils import validate_network_str +from controllerconfig.utils import validate_address_str DEFAULT_CONFIG = 0 REGION_CONFIG = 1 @@ -26,8 +26,6 @@ NETWORK_PREFIX_NAMES = [ ('CLM', 'BLS', 'CAN', 'CLUSTER') ] -# Additions to this list must be reflected in the hostfile -# generator tool (config->configutilities->hostfiletool.py) HOST_XML_ATTRIBUTES = ['hostname', 'personality', 'subfunctions', 'mgmt_mac', 'mgmt_ip', 'bm_ip', 'bm_type', 'bm_username', diff --git a/configutilities/configutilities/configutilities/common/crypt.py b/controllerconfig/controllerconfig/controllerconfig/common/crypt.py similarity index 92% rename from configutilities/configutilities/configutilities/common/crypt.py rename to controllerconfig/controllerconfig/controllerconfig/common/crypt.py index c90bafc946..ce53d73f80 100644 --- a/configutilities/configutilities/configutilities/common/crypt.py +++ b/controllerconfig/controllerconfig/controllerconfig/common/crypt.py @@ -12,6 +12,11 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +# +# Copyright (c) 2019 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# """ Routines for URL-safe encrypting/decrypting @@ -34,20 +39,19 @@ from six.moves import range def urlsafe_encrypt(key, plaintext, blocksize=16): - """ - Encrypts plaintext. Resulting ciphertext will contain URL-safe characters. + """Encrypts plaintext. + + Resulting ciphertext will contain URL-safe characters. If plaintext is Unicode, encode it to UTF-8 before encryption. :param key: AES secret key :param plaintext: Input text to be encrypted :param blocksize: Non-zero integer multiple of AES blocksize in bytes (16) - :returns: Resulting ciphertext """ + def pad(text): - """ - Pads text to be encrypted - """ + """Pads text to be encrypted""" pad_length = (blocksize - len(text) % blocksize) # NOTE(rosmaita): I know this looks stupid, but we can't just # use os.urandom() to get the bytes because we use char(0) as @@ -74,8 +78,8 @@ def urlsafe_encrypt(key, plaintext, blocksize=16): def urlsafe_decrypt(key, ciphertext): - """ - Decrypts URL-safe base64 encoded ciphertext. + """Decrypts URL-safe base64 encoded ciphertext. + On Python 3, the result is decoded from UTF-8. :param key: AES secret key diff --git a/controllerconfig/controllerconfig/controllerconfig/common/dcmanager.py b/controllerconfig/controllerconfig/controllerconfig/common/dcmanager.py index 02ef188742..c88c69cc1e 100755 --- a/controllerconfig/controllerconfig/controllerconfig/common/dcmanager.py +++ b/controllerconfig/controllerconfig/controllerconfig/common/dcmanager.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2017 Wind River Systems, Inc. +# Copyright (c) 2017-2019 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -11,7 +11,7 @@ DC Manager Interactions from controllerconfig.common import log from Crypto.Hash import MD5 -from configutilities.common import crypt +from controllerconfig.common import crypt import json diff --git a/controllerconfig/controllerconfig/controllerconfig/common/exceptions.py b/controllerconfig/controllerconfig/controllerconfig/common/exceptions.py index afbcd3bb33..66a4b7e1c3 100644 --- a/controllerconfig/controllerconfig/controllerconfig/common/exceptions.py +++ b/controllerconfig/controllerconfig/controllerconfig/common/exceptions.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2014 Wind River Systems, Inc. +# Copyright (c) 2014-2019 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -8,7 +8,26 @@ Configuration Errors """ -from configutilities import ConfigError + +class ConfigError(Exception): + """Base class for configuration exceptions.""" + + def __init__(self, message=None): + self.message = message + super(ConfigError, self).__init__(message) + + def __str__(self): + return self.message or "" + + +class ConfigFail(ConfigError): + """General configuration error.""" + pass + + +class ValidateFail(ConfigError): + """Validation of data failed.""" + pass class BackupFail(ConfigError): diff --git a/configutilities/configutilities/configutilities/common/validator.py b/controllerconfig/controllerconfig/controllerconfig/common/validator.py similarity index 97% rename from configutilities/configutilities/configutilities/common/validator.py rename to controllerconfig/controllerconfig/controllerconfig/common/validator.py index 69e1e33656..a27447263b 100644 --- a/configutilities/configutilities/configutilities/common/validator.py +++ b/controllerconfig/controllerconfig/controllerconfig/common/validator.py @@ -1,34 +1,34 @@ """ -Copyright (c) 2015-2017 Wind River Systems, Inc. +Copyright (c) 2015-2019 Wind River Systems, Inc. SPDX-License-Identifier: Apache-2.0 """ -from configutilities.common.configobjects import DEFAULT_NAMES -from configutilities.common.configobjects import NETWORK_PREFIX_NAMES -from configutilities.common.configobjects import OAM_TYPE -from configutilities.common.configobjects import MGMT_TYPE -from configutilities.common.configobjects import Network -from configutilities.common.configobjects import REGION_CONFIG -from configutilities.common.configobjects import INFRA_TYPE -from configutilities.common.configobjects import DEFAULT_DOMAIN_NAME -from configutilities.common.configobjects import HP_NAMES -from configutilities.common.configobjects import SUBCLOUD_CONFIG -from configutilities.common.configobjects import CLUSTER_TYPE +from controllerconfig.common.configobjects import DEFAULT_NAMES +from controllerconfig.common.configobjects import NETWORK_PREFIX_NAMES +from controllerconfig.common.configobjects import OAM_TYPE +from controllerconfig.common.configobjects import MGMT_TYPE +from controllerconfig.common.configobjects import Network +from controllerconfig.common.configobjects import REGION_CONFIG +from controllerconfig.common.configobjects import INFRA_TYPE +from controllerconfig.common.configobjects import DEFAULT_DOMAIN_NAME +from controllerconfig.common.configobjects import HP_NAMES +from controllerconfig.common.configobjects import SUBCLOUD_CONFIG +from controllerconfig.common.configobjects import CLUSTER_TYPE from netaddr import IPRange -from configutilities.common.utils import lag_mode_to_str -from configutilities.common.utils import validate_network_str -from configutilities.common.utils import check_network_overlap -from configutilities.common.utils import is_mtu_valid -from configutilities.common.utils import get_service -from configutilities.common.utils import get_optional -from configutilities.common.utils import validate_address_str -from configutilities.common.utils import validate_nameserver_address_str -from configutilities.common.utils import is_valid_url -from configutilities.common.utils import is_valid_domain_or_ip -from configutilities.common.utils import is_valid_bool_str -from configutilities.common.exceptions import ConfigFail -from configutilities.common.exceptions import ValidateFail +from controllerconfig.utils import lag_mode_to_str +from controllerconfig.utils import validate_network_str +from controllerconfig.utils import check_network_overlap +from controllerconfig.utils import is_mtu_valid +from controllerconfig.utils import get_service +from controllerconfig.utils import get_optional +from controllerconfig.utils import validate_address_str +from controllerconfig.utils import validate_nameserver_address_str +from controllerconfig.utils import is_valid_url +from controllerconfig.utils import is_valid_domain_or_ip +from controllerconfig.utils import is_valid_bool_str +from controllerconfig.common.exceptions import ConfigFail +from controllerconfig.common.exceptions import ValidateFail # Constants diff --git a/controllerconfig/controllerconfig/controllerconfig/config_management.py b/controllerconfig/controllerconfig/controllerconfig/config_management.py index db42355336..9cbd6972c1 100644 --- a/controllerconfig/controllerconfig/controllerconfig/config_management.py +++ b/controllerconfig/controllerconfig/controllerconfig/config_management.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2017 Wind River Systems, Inc. +Copyright (c) 2017-2019 Wind River Systems, Inc. SPDX-License-Identifier: Apache-2.0 @@ -13,8 +13,8 @@ import subprocess import sys import time -import configutilities.common.exceptions as cexeptions -import configutilities.common.utils as cutils +import controllerconfig.common.exceptions as exeptions +import controllerconfig.utils as utils from six.moves import input @@ -109,9 +109,9 @@ def configure_management(): continue break except (netaddr.AddrFormatError, ValueError): - print ("Invalid CIDR - " - "please enter a valid management IP address in " - "CIDR notation.") + print("Invalid CIDR - " + "please enter a valid management IP address in " + "CIDR notation.") while True: user_input = input("Enter management gateway IP address [" + @@ -127,18 +127,18 @@ def configure_management(): management_gateway_address = ip_input break except (netaddr.AddrFormatError, ValueError): - print ("Invalid address - " - "please enter a valid management gateway IP address") + print("Invalid address - " + "please enter a valid management gateway IP address") min_addresses = 8 while True: user_input = input("Enter System Controller subnet in " "CIDR notation: ") try: - system_controller_subnet = cutils.validate_network_str( + system_controller_subnet = utils.validate_network_str( user_input, min_addresses) break - except cexeptions.ValidateFail as e: + except exeptions.ValidateFail as e: print("{}".format(e)) print("Disabling non-management interfaces... ", end=' ') diff --git a/controllerconfig/controllerconfig/controllerconfig/configassistant.py b/controllerconfig/controllerconfig/controllerconfig/configassistant.py index 0b0a9ea918..5185abfc27 100644 --- a/controllerconfig/controllerconfig/controllerconfig/configassistant.py +++ b/controllerconfig/controllerconfig/controllerconfig/configassistant.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2014-2018 Wind River Systems, Inc. +Copyright (c) 2014-2019 Wind River Systems, Inc. SPDX-License-Identifier: Apache-2.0 @@ -20,19 +20,19 @@ import textwrap import time import pyudev -from configutilities import ConfigFail -from configutilities import ValidateFail -from configutilities import is_valid_vlan -from configutilities import is_mtu_valid -from configutilities import validate_network_str -from configutilities import validate_address_str -from configutilities import validate_address -from configutilities import ip_version_to_string -from configutilities import validate_nameserver_address_str -from configutilities import is_valid_url -from configutilities import is_valid_domain_or_ip -from configutilities import validate_openstack_password -from configutilities import DEFAULT_DOMAIN_NAME +from controllerconfig import ConfigFail +from controllerconfig import ValidateFail +from controllerconfig import is_valid_vlan +from controllerconfig import is_mtu_valid +from controllerconfig import validate_network_str +from controllerconfig import validate_address_str +from controllerconfig import validate_address +from controllerconfig import ip_version_to_string +from controllerconfig import validate_nameserver_address_str +from controllerconfig import is_valid_url +from controllerconfig import is_valid_domain_or_ip +from controllerconfig import validate_openstack_password +from controllerconfig import DEFAULT_DOMAIN_NAME from netaddr import IPNetwork from netaddr import IPAddress from netaddr import IPRange diff --git a/controllerconfig/controllerconfig/controllerconfig/regionconfig.py b/controllerconfig/controllerconfig/controllerconfig/regionconfig.py index a3cfa6cb20..930ee43d68 100755 --- a/controllerconfig/controllerconfig/controllerconfig/regionconfig.py +++ b/controllerconfig/controllerconfig/controllerconfig/regionconfig.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2015-2018 Wind River Systems, Inc. +Copyright (c) 2015-2019 Wind River Systems, Inc. SPDX-License-Identifier: Apache-2.0 @@ -19,16 +19,15 @@ from controllerconfig.common import constants from controllerconfig.common import log from controllerconfig.common import rest_api_utils as rutils from controllerconfig.common.exceptions import KeystoneFail -from configutilities.common import utils as cutils -from configutilities.common.configobjects import REGION_CONFIG -from configutilities.common.configobjects import SUBCLOUD_CONFIG -from configutilities import ConfigFail +from controllerconfig.common.configobjects import REGION_CONFIG +from controllerconfig.common.configobjects import SUBCLOUD_CONFIG +from controllerconfig import ConfigFail from controllerconfig.configassistant import ConfigAssistant from netaddr import IPAddress from controllerconfig.systemconfig import parse_system_config from controllerconfig.systemconfig import configure_management_interface from controllerconfig.systemconfig import create_cgcs_config_file -from configutilities import DEFAULT_DOMAIN_NAME +from controllerconfig import DEFAULT_DOMAIN_NAME # Temporary file for building cgcs_config TEMP_CGCS_CONFIG_FILE = "/tmp/cgcs_config" @@ -290,18 +289,18 @@ def validate_region_one_keystone_config(region_config, token, api_url, users, # Verify that region two endpoints & services match our requirements, # optionally creating missing entries - public_address = cutils.get_optional(region_config, 'CAN_NETWORK', - 'CAN_IP_START_ADDRESS') + public_address = utils.get_optional(region_config, 'CAN_NETWORK', + 'CAN_IP_START_ADDRESS') if not public_address: - public_address = cutils.get_optional(region_config, 'CAN_NETWORK', - 'CAN_IP_FLOATING_ADDRESS') + public_address = utils.get_optional(region_config, 'CAN_NETWORK', + 'CAN_IP_FLOATING_ADDRESS') if not public_address: - public_address = cutils.get_optional(region_config, 'OAM_NETWORK', - 'IP_START_ADDRESS') + public_address = utils.get_optional(region_config, 'OAM_NETWORK', + 'IP_START_ADDRESS') if not public_address: # AIO-SX configuration - public_address = cutils.get_optional(region_config, 'OAM_NETWORK', - 'IP_ADDRESS') + public_address = utils.get_optional(region_config, 'OAM_NETWORK', + 'IP_ADDRESS') if not public_address: public_address = region_config.get('OAM_NETWORK', 'IP_FLOATING_ADDRESS') @@ -313,17 +312,17 @@ def validate_region_one_keystone_config(region_config, token, api_url, users, internal_address = region_config.get('MGMT_NETWORK', 'IP_START_ADDRESS') - internal_infra_address = cutils.get_optional( + internal_infra_address = utils.get_optional( region_config, 'BLS_NETWORK', 'BLS_IP_START_ADDRESS') if not internal_infra_address: - internal_infra_address = cutils.get_optional( + internal_infra_address = utils.get_optional( region_config, 'INFRA_NETWORK', 'IP_START_ADDRESS') for endpoint in expected_region_2_endpoints: - service_name = cutils.get_service(region_config, 'REGION_2_SERVICES', - endpoint[SERVICE_NAME]) - service_type = cutils.get_service(region_config, 'REGION_2_SERVICES', - endpoint[SERVICE_TYPE]) + service_name = utils.get_service(region_config, 'REGION_2_SERVICES', + endpoint[SERVICE_NAME]) + service_type = utils.get_service(region_config, 'REGION_2_SERVICES', + endpoint[SERVICE_TYPE]) service_id = services.get_service_id(service_name, service_type) expected_public_url = endpoint[PUBLIC_URL].format(public_address) diff --git a/controllerconfig/controllerconfig/controllerconfig/systemconfig.py b/controllerconfig/controllerconfig/controllerconfig/systemconfig.py index 17905f7e78..2ca27bbc11 100644 --- a/controllerconfig/controllerconfig/controllerconfig/systemconfig.py +++ b/controllerconfig/controllerconfig/controllerconfig/systemconfig.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2015-2017 Wind River Systems, Inc. +Copyright (c) 2015-2019 Wind River Systems, Inc. SPDX-License-Identifier: Apache-2.0 @@ -18,16 +18,16 @@ from controllerconfig.common.exceptions import BackupFail from controllerconfig.common.exceptions import RestoreFail from controllerconfig.common.exceptions import UserQuit from controllerconfig.common.exceptions import CloneFail -from configutilities import lag_mode_to_str -from configutilities import Network -from configutilities import validate -from configutilities import ConfigFail -from configutilities import DEFAULT_CONFIG -from configutilities import REGION_CONFIG -from configutilities import SUBCLOUD_CONFIG -from configutilities import MGMT_TYPE -from configutilities import HP_NAMES -from configutilities import DEFAULT_NAMES +from controllerconfig import lag_mode_to_str +from controllerconfig import Network +from controllerconfig import validate +from controllerconfig import ConfigFail +from controllerconfig import DEFAULT_CONFIG +from controllerconfig import REGION_CONFIG +from controllerconfig import SUBCLOUD_CONFIG +from controllerconfig import MGMT_TYPE +from controllerconfig import HP_NAMES +from controllerconfig import DEFAULT_NAMES from controllerconfig.configassistant import ConfigAssistant from controllerconfig import backup_restore from controllerconfig import utils diff --git a/controllerconfig/controllerconfig/controllerconfig/tests/test_region_config.py b/controllerconfig/controllerconfig/controllerconfig/tests/test_region_config.py index 5b263c1138..5e0531fae4 100644 --- a/controllerconfig/controllerconfig/controllerconfig/tests/test_region_config.py +++ b/controllerconfig/controllerconfig/controllerconfig/tests/test_region_config.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2014-2017 Wind River Systems, Inc. +Copyright (c) 2014-2019 Wind River Systems, Inc. SPDX-License-Identifier: Apache-2.0 @@ -17,9 +17,9 @@ import pytest import shutil import sys -import configutilities.common.exceptions as exceptions -from configutilities import REGION_CONFIG -from configutilities import validate +import controllerconfig.common.exceptions as exceptions +from controllerconfig import REGION_CONFIG +from controllerconfig import validate import controllerconfig.common.keystone as keystone from controllerconfig.tests import test_answerfile diff --git a/controllerconfig/controllerconfig/controllerconfig/tests/test_system_config.py b/controllerconfig/controllerconfig/controllerconfig/tests/test_system_config.py index 2bda2825c9..0798fcdd46 100644 --- a/controllerconfig/controllerconfig/controllerconfig/tests/test_system_config.py +++ b/controllerconfig/controllerconfig/controllerconfig/tests/test_system_config.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2014, 2017 Wind River Systems, Inc. +Copyright (c) 2014-2019 Wind River Systems, Inc. SPDX-License-Identifier: Apache-2.0 @@ -11,9 +11,9 @@ import os import pytest import sys -import configutilities.common.exceptions as exceptions -from configutilities import validate -from configutilities import DEFAULT_CONFIG +import controllerconfig.common.exceptions as exceptions +from controllerconfig import validate +from controllerconfig import DEFAULT_CONFIG sys.modules['fm_core'] = mock.Mock() diff --git a/controllerconfig/controllerconfig/controllerconfig/upgrades/utils.py b/controllerconfig/controllerconfig/controllerconfig/upgrades/utils.py index bca695478d..a478a5ad47 100644 --- a/controllerconfig/controllerconfig/controllerconfig/upgrades/utils.py +++ b/controllerconfig/controllerconfig/controllerconfig/upgrades/utils.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2016 Wind River Systems, Inc. +# Copyright (c) 2016-2019 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -21,7 +21,7 @@ import yaml from tsconfig.tsconfig import SW_VERSION from tsconfig.tsconfig import PLATFORM_PATH -from configutilities import DEFAULT_DOMAIN_NAME +from controllerconfig import DEFAULT_DOMAIN_NAME from controllerconfig import utils as cutils from controllerconfig.common import log from controllerconfig.common import constants diff --git a/controllerconfig/controllerconfig/controllerconfig/utils.py b/controllerconfig/controllerconfig/controllerconfig/utils.py index 7bfb522a99..c29437b3cb 100644 --- a/controllerconfig/controllerconfig/controllerconfig/utils.py +++ b/controllerconfig/controllerconfig/controllerconfig/utils.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2014-2018 Wind River Systems, Inc. +# Copyright (c) 2014-2019 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -19,13 +19,17 @@ import time import sys import yaml +from six.moves import configparser +import re +import six + import netaddr from tsconfig import tsconfig -from configutilities.common.utils import is_valid_mac from sysinv.common import constants as sysinv_constants from controllerconfig.common import constants from controllerconfig.common import log +from controllerconfig.common.exceptions import ValidateFail LOOPBACK_IFNAME = 'lo' @@ -40,6 +44,21 @@ LOG = log.get_logger(__name__) DEVNULL = open(os.devnull, 'w') +EXPECTED_SERVICE_NAME_AND_TYPE = ( + {"KEYSTONE_SERVICE_NAME": "keystone", + "KEYSTONE_SERVICE_TYPE": "identity", + "SYSINV_SERVICE_NAME": "sysinv", + "SYSINV_SERVICE_TYPE": "platform", + "PATCHING_SERVICE_NAME": "patching", + "PATCHING_SERVICE_TYPE": "patching", + "NFV_SERVICE_NAME": "vim", + "NFV_SERVICE_TYPE": "nfv", + "FM_SERVICE_NAME": "fm", + "FM_SERVICE_TYPE": "faultmanagement", + "BARBICAN_SERVICE_NAME": "barbican", + "BARBICAN_SERVICE_TYPE": "key-manager", + }) + def filesystem_get_free_space(path): """ Get Free space of directory """ @@ -283,21 +302,6 @@ def validate_and_normalize_mac(address): return address.lower() -def is_valid_ipv4(address): - """Verify that address represents a valid IPv4 address.""" - try: - return netaddr.valid_ipv4(address) - except Exception: - return False - - -def is_valid_ipv6(address): - try: - return netaddr.valid_ipv6(address) - except Exception: - return False - - def is_valid_ip(address): if not is_valid_ipv4(address): return is_valid_ipv6(address) @@ -895,3 +899,318 @@ def is_ssh_parent(): return False except subprocess.CalledProcessError: return False + + +def is_valid_vlan(vlan): + """Determine whether vlan is valid.""" + try: + if 0 < int(vlan) < 4095: + return True + else: + return False + except (ValueError, TypeError): + return False + + +def is_mtu_valid(mtu): + """Determine whether a mtu is valid.""" + try: + if int(mtu) < 576: + return False + elif int(mtu) > 9216: + return False + else: + return True + except (ValueError, TypeError): + return False + + +def is_valid_hostname(hostname): + """Determine whether a hostname is valid as per RFC 1123.""" + + # Maximum length of 255 + if not hostname or len(hostname) > 255: + return False + # Allow a single dot on the right hand side + if hostname[-1] == ".": + hostname = hostname[:-1] + # Create a regex to ensure: + # - hostname does not begin or end with a dash + # - each segment is 1 to 63 characters long + # - valid characters are A-Z (any case) and 0-9 + valid_re = re.compile("(?!-)[A-Z\d-]{1,63}(?