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 <kristine.bujold@windriver.com>
This commit is contained in:
parent
95875029ca
commit
a1e2d1e183
26
.zuul.yaml
26
.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
|
||||
|
@ -10,9 +10,6 @@ workerconfig
|
||||
workerconfig-standalone
|
||||
workerconfig-subfunction
|
||||
|
||||
# configutilities
|
||||
configutilities
|
||||
|
||||
# controllerconfig
|
||||
controllerconfig
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
cgts-client-wheels
|
||||
configutilities-wheels
|
||||
controllerconfig-wheels
|
||||
sysinv-wheels
|
||||
|
@ -1,7 +1,6 @@
|
||||
kubernetes/applications/stx-openstack/stx-openstack-helm
|
||||
worker-utils
|
||||
workerconfig
|
||||
configutilities
|
||||
controllerconfig
|
||||
storageconfig
|
||||
sysinv/cgts-client
|
||||
|
@ -1,4 +1,3 @@
|
||||
cgts-client-wheels
|
||||
configutilities-wheels
|
||||
controllerconfig-wheels
|
||||
sysinv-wheels
|
||||
|
6
configutilities/.gitignore
vendored
6
configutilities/.gitignore
vendored
@ -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
|
@ -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
|
@ -1,3 +0,0 @@
|
||||
SRC_DIR="configutilities"
|
||||
COPY_LIST="$SRC_DIR/LICENSE"
|
||||
TIS_PATCH_VER=2
|
@ -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 <info@windriver.com>
|
||||
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/*
|
@ -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.
|
@ -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.
|
@ -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 <filename>
|
||||
|
||||
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.
|
||||
|
@ -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
|
@ -1,5 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2015 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
@ -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
|
@ -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, '')
|
@ -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}(?<!-)$", re.IGNORECASE)
|
||||
return all(valid_re.match(x) for x in hostname.split("."))
|
||||
|
||||
|
||||
def is_valid_mac(mac):
|
||||
"""Verify the format of a MAC addres."""
|
||||
if not mac:
|
||||
return False
|
||||
m = "[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$"
|
||||
return isinstance(mac, six.string_types) and re.match(m, mac.lower())
|
||||
|
||||
|
||||
def validate_network_str(network_str, minimum_size,
|
||||
existing_networks=None, multicast=False):
|
||||
"""Determine whether a network is valid."""
|
||||
try:
|
||||
network = IPNetwork(network_str)
|
||||
if network.ip != network.network:
|
||||
raise ValidateFail("Invalid network address")
|
||||
elif network.size < minimum_size:
|
||||
raise ValidateFail("Subnet too small - must have at least %d "
|
||||
"addresses" % minimum_size)
|
||||
elif network.version == 6 and network.prefixlen < 64:
|
||||
raise ValidateFail("IPv6 minimum prefix length is 64")
|
||||
elif existing_networks:
|
||||
if any(network.ip in subnet for subnet in existing_networks):
|
||||
raise ValidateFail("Subnet overlaps with another "
|
||||
"configured subnet")
|
||||
elif multicast and not network.is_multicast():
|
||||
raise ValidateFail("Invalid subnet - must be multicast")
|
||||
return network
|
||||
except AddrFormatError:
|
||||
raise ValidateFail(
|
||||
"Invalid subnet - not a valid IP subnet")
|
||||
|
||||
|
||||
def is_valid_filename(filename):
|
||||
return '\0' not in filename
|
||||
|
||||
|
||||
def is_valid_by_path(filename):
|
||||
return "/dev/disk/by-path" in filename and "-part" not in filename
|
||||
|
||||
|
||||
def is_valid_url(url_str):
|
||||
# Django URL validation patterns
|
||||
r = re.compile(
|
||||
r'^(?:http|ftp)s?://' # http:// or https://
|
||||
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)' # domain...
|
||||
r'+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'
|
||||
r'localhost|' # localhost...
|
||||
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
|
||||
r'(?::\d+)?' # optional port
|
||||
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
|
||||
|
||||
url = r.match(url_str)
|
||||
if url:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_valid_domain(url_str):
|
||||
r = re.compile(
|
||||
r'^(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)' # domain...
|
||||
r'+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'
|
||||
r'[A-Za-z0-9-_]*)' # localhost, hostname
|
||||
r'(?::\d+)?' # optional port
|
||||
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
|
||||
|
||||
url = r.match(url_str)
|
||||
if url:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_valid_ipv4(address):
|
||||
"""Verify that address represents a valid IPv4 address."""
|
||||
try:
|
||||
return valid_ipv4(address)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def is_valid_ipv6(address):
|
||||
try:
|
||||
return valid_ipv6(address)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def is_valid_domain_or_ip(url_str):
|
||||
if url_str:
|
||||
if is_valid_domain(url_str):
|
||||
return True
|
||||
ip_with_port = url_str.split(':')
|
||||
if len(ip_with_port) <= 2:
|
||||
# check ipv4 or ipv4 with port
|
||||
return is_valid_ipv4(ip_with_port[0])
|
||||
else:
|
||||
# check ipv6 with port
|
||||
if '[' in url_str:
|
||||
try:
|
||||
bkt_idx = url_str.index(']')
|
||||
if bkt_idx + 1 == len(url_str):
|
||||
# brackets without port
|
||||
return False
|
||||
else:
|
||||
return is_valid_ipv6(url_str[1:bkt_idx])
|
||||
except Exception:
|
||||
return False
|
||||
else:
|
||||
# check ipv6 without port
|
||||
return is_valid_ipv6(url_str)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_valid_bool_str(val):
|
||||
"""Check if the provided string is a valid bool string or not."""
|
||||
boolstrs = ('true', 'false')
|
||||
return str(val).lower() in boolstrs
|
||||
|
||||
|
||||
def validate_address_str(ip_address_str, network):
|
||||
"""Determine whether an address is valid."""
|
||||
try:
|
||||
ip_address = IPAddress(ip_address_str)
|
||||
if ip_address.version != network.version:
|
||||
msg = ("Invalid IP version - must match network version " +
|
||||
ip_version_to_string(network.version))
|
||||
raise ValidateFail(msg)
|
||||
elif ip_address == network:
|
||||
raise ValidateFail("Cannot use network address")
|
||||
elif ip_address == network.broadcast:
|
||||
raise ValidateFail("Cannot use broadcast address")
|
||||
elif ip_address not in network:
|
||||
raise ValidateFail(
|
||||
"Address must be in subnet %s" % str(network))
|
||||
return ip_address
|
||||
except AddrFormatError:
|
||||
raise ValidateFail(
|
||||
"Invalid address - not a valid IP address")
|
||||
|
||||
|
||||
def ip_version_to_string(ip_version):
|
||||
"""Determine whether a nameserver address is valid."""
|
||||
if ip_version == 4:
|
||||
return "IPv4"
|
||||
elif ip_version == 6:
|
||||
return "IPv6"
|
||||
else:
|
||||
return "IP"
|
||||
|
||||
|
||||
def validate_nameserver_address_str(ip_address_str, subnet_version=None):
|
||||
"""Determine whether a nameserver address is valid."""
|
||||
try:
|
||||
ip_address = IPAddress(ip_address_str)
|
||||
if subnet_version is not None and ip_address.version != subnet_version:
|
||||
msg = ("Invalid IP version - must match OAM subnet version " +
|
||||
ip_version_to_string(subnet_version))
|
||||
raise ValidateFail(msg)
|
||||
return ip_address
|
||||
except AddrFormatError:
|
||||
msg = "Invalid address - "
|
||||
"not a valid %s address" % ip_version_to_string(subnet_version)
|
||||
raise ValidateFail(msg)
|
||||
|
||||
|
||||
def validate_address(ip_address, network):
|
||||
"""Determine whether an address is valid."""
|
||||
if ip_address.version != network.version:
|
||||
msg = ("Invalid IP version - must match network version " +
|
||||
ip_version_to_string(network.version))
|
||||
raise ValidateFail(msg)
|
||||
elif ip_address == network:
|
||||
raise ValidateFail("Cannot use network address")
|
||||
elif ip_address == network.broadcast:
|
||||
raise ValidateFail("Cannot use broadcast address")
|
||||
elif ip_address not in network:
|
||||
raise ValidateFail("Address must be in subnet %s" % str(network))
|
||||
|
||||
|
||||
def check_network_overlap(new_network, configured_networks):
|
||||
""" Validate that new_network does not overlap any configured_networks.
|
||||
"""
|
||||
if any(new_network.ip in subnet for subnet in
|
||||
configured_networks):
|
||||
raise ValidateFail(
|
||||
"Subnet %s overlaps with another configured subnet" % new_network)
|
||||
|
||||
|
||||
def lag_mode_to_str(lag_mode):
|
||||
if lag_mode == 0:
|
||||
return "balance-rr"
|
||||
if lag_mode == 1:
|
||||
return "active-backup"
|
||||
elif lag_mode == 2:
|
||||
return "balance-xor"
|
||||
elif lag_mode == 3:
|
||||
return "broadcast"
|
||||
elif lag_mode == 4:
|
||||
return "802.3ad"
|
||||
elif lag_mode == 5:
|
||||
return "balance-tlb"
|
||||
elif lag_mode == 6:
|
||||
return "balance-alb"
|
||||
else:
|
||||
raise Exception(
|
||||
"Invalid LAG_MODE value of %d. Valid values: 0-6" % lag_mode)
|
||||
|
||||
|
||||
def validate_openstack_password(password, rules_file,
|
||||
section="security_compliance"):
|
||||
try:
|
||||
config = configparser.RawConfigParser()
|
||||
parsed_config = config.read(rules_file)
|
||||
if not parsed_config:
|
||||
msg = ("Cannot parse rules file: %s" % rules_file)
|
||||
raise Exception(msg)
|
||||
if not config.has_section(section):
|
||||
msg = ("Required section '%s' not found in rules file" % section)
|
||||
raise Exception(msg)
|
||||
|
||||
password_regex = get_optional(config, section, 'password_regex')
|
||||
password_regex_description = get_optional(config, section,
|
||||
'password_regex_description')
|
||||
|
||||
if not password_regex:
|
||||
msg = ("Required option 'password_regex' not found in "
|
||||
"rule file: %s" % rules_file)
|
||||
raise Exception(msg)
|
||||
# Even if regex_description is not found, we will proceed
|
||||
# and give a generic failure warning instead
|
||||
if not password_regex_description:
|
||||
password_regex_description = ("Password does not meet "
|
||||
"complexity criteria")
|
||||
|
||||
if not isinstance(password, six.string_types):
|
||||
msg = ("Password must be a string type")
|
||||
raise Exception(msg)
|
||||
try:
|
||||
# config parser would read in the string as a literal
|
||||
# representation which would fail regex matching
|
||||
password_regex = password_regex.strip('"')
|
||||
if not re.match(password_regex, password):
|
||||
return False, password_regex_description
|
||||
except re.error:
|
||||
msg = ("Unable to validate password due to invalid "
|
||||
"complexity criteria ('password_regex')")
|
||||
raise Exception(msg)
|
||||
except Exception:
|
||||
raise Exception("Password validation failed")
|
||||
return True, ""
|
||||
|
||||
|
||||
def extract_openstack_password_rules_from_file(
|
||||
rules_file, section="security_compliance"):
|
||||
try:
|
||||
config = configparser.RawConfigParser()
|
||||
parsed_config = config.read(rules_file)
|
||||
if not parsed_config:
|
||||
msg = ("Cannot parse rules file: %s" % rules_file)
|
||||
raise Exception(msg)
|
||||
if not config.has_section(section):
|
||||
msg = ("Required section '%s' not found in rules file" % section)
|
||||
raise Exception(msg)
|
||||
|
||||
rules = config.items(section)
|
||||
if not rules:
|
||||
msg = ("section '%s' contains no configuration options" % section)
|
||||
raise Exception(msg)
|
||||
return dict(rules)
|
||||
except Exception:
|
||||
raise Exception("Failed to extract password rules from file")
|
||||
|
||||
|
||||
def get_optional(conf, section, key):
|
||||
if conf.has_option(section, key):
|
||||
return conf.get(section, key)
|
||||
return None
|
||||
|
||||
|
||||
def get_service(conf, section, key):
|
||||
if key in EXPECTED_SERVICE_NAME_AND_TYPE:
|
||||
if conf.has_option(section, key):
|
||||
value = conf.get(section, key)
|
||||
if value != EXPECTED_SERVICE_NAME_AND_TYPE[key]:
|
||||
raise ValidateFail("Unsupported %s: %s " % (key, value))
|
||||
else:
|
||||
value = EXPECTED_SERVICE_NAME_AND_TYPE[key]
|
||||
return value
|
||||
else:
|
||||
return conf.get(section, key)
|
@ -1,37 +0,0 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# This file was generated by img2py.py
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015-2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
#
|
||||
# Stylized red Wind River 'W' icon
|
||||
#
|
||||
|
||||
from wx.lib.embeddedimage import PyEmbeddedImage
|
||||
|
||||
favicon = PyEmbeddedImage(
|
||||
"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAA99J"
|
||||
"REFUWIXtls1PE2sUxn/z0Q7U0g/AXmNAUBGNxsSYGnWjQQ0YNAISY1y4kLh16T/g1qV/gwtJ"
|
||||
"JFFATbBCmuBXrhiMitGk0hpBJaQtM4Vpp+3cxXAHSltub1zggpPM4p155pznfd5zznuEv8Fk"
|
||||
"A03cyOCbBDYJ/BEE5EpqUPiP72YFmHI42bV/f0ng6uDG3BzZubmSTuW6OhzbtmEaBuloFDOd"
|
||||
"Lo3buhVHIGDhpqcxMxnLfzoaXYlnmiAICJKEoCjWWpKI37tH7MYNyOUKvQoCDbdvU3ftGnlN"
|
||||
"Y7qvj4VQqGiXgizTeOcOtVeukHr1isjly+QSCYvYdF9fEVvR5aLu6lX8ly4B4OnoQGlqIh2J"
|
||||
"FOCcTU34urqQa2uhthZ/by/qs2cW8VWmtLTgPXcOyetlcWLCDg4gL4RCJSXLfPtGzcmTyIEA"
|
||||
"SnMz7hMn0CMRe3cm4GlvR9m1y/7H096Os7mZzNevK6ICnrNncTY2kksmSQ4PF+SCKCwv1j76"
|
||||
"p0+kXr9eRol4z59HdDptx5LLhf/iRRBXCknZuRPPmTMFOSR7PPi6ugBYfPuWpcnJgiMqW4Z5"
|
||||
"XScxOGjL6T5+HGXPHszlXbkOH2bL0aOQz2PMzlo4UcTX04Pkctm7dx05wpZgEIDko0dkVbUg"
|
||||
"TlkCAqCOjpKJxQBwbN+O59Qp+5uvuxvJ5yMTizF765Z9ru5jx6g+dMiSWRDwdXcjut1kf/1i"
|
||||
"YWSkKM66jSgTiaCGw/ba29mJWFWFo6EBb2cnAOrYGPN376K9eAGA5Pfbkjt37MDb0QGA9vIl"
|
||||
"+tRUUYWsSyCfy5EcHMQ0DABcwSBV+/ZR09aG0tpKXteJDwyQVVXi/f2Y2axN1BEIUHP6NMru"
|
||||
"3WCaJIeGyJfoEesSEABtfBz982cA5Pp6/D09+Ht7ESSJpclJUs+fIwALIyPoU1MAVO3di+/C"
|
||||
"BUsJUSQTi6GOjZXslvJ6BACMmRnUp0+pPnAAgPrr1xHdbgASDx9izM9b3XJmhsSDB1QfPIjg"
|
||||
"cPDXzZs4AgEA1HCYzJoeUpECYGVyYmiIfCoFWMkoeTwYP36QHB4uxA0MYPz8aanQ2ork82Ea"
|
||||
"hiX/2i5aKQEBWHzzhqV37wrea+Ew+sePtqwCsPT+vdUJV1n6yxe08fGyl1VF13E2Hif5+LG9"
|
||||
"Ng2D+P375JeT81/LGwbx/n7yum6/WwiFML5/L+u74nkg+eSJfSMuffiAFg4XXzpY5704MWER"
|
||||
"0jS79ZYzodKxXFAUatrakP1+MtGoVfdm6V9dwSBVLS3kUinU0VHymvb7BKB4TvhdHFRQhqut"
|
||||
"kqnn/+DgD5gJNwlsEthwAv8AApOBr7T8BuQAAAAASUVORK5CYII=")
|
@ -1,103 +0,0 @@
|
||||
"""
|
||||
Copyright (c) 2015-2016 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import os
|
||||
from six.moves import configparser
|
||||
from configutilities.common.validator import validate
|
||||
from configutilities.common.configobjects import DEFAULT_CONFIG
|
||||
from configutilities.common.configobjects import REGION_CONFIG
|
||||
from configutilities.common.exceptions import ConfigFail
|
||||
from configutilities.common.exceptions import ValidateFail
|
||||
|
||||
|
||||
def parse_config(config_file):
|
||||
"""Parse system config file"""
|
||||
config = configparser.RawConfigParser()
|
||||
try:
|
||||
config.read(config_file)
|
||||
except Exception as e:
|
||||
raise ConfigFail("Error parsing system config file: %s" % e.message)
|
||||
return config
|
||||
|
||||
|
||||
def show_help():
|
||||
print("Usage: %s\n"
|
||||
"Perform validation of a given configuration file\n\n"
|
||||
"--system-config <name> Validate a system configuration file\n"
|
||||
"--region-config <name> 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")
|
File diff suppressed because it is too large
Load Diff
@ -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()
|
@ -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() + "</" + name + ">\n"
|
||||
|
||||
# Special Fields
|
||||
if self.fieldgroup[1]['power_on'].get_value() is 'Y':
|
||||
attrs += "\t\t<power_on/>\n"
|
||||
|
||||
if self.fieldgroup[1]['uses_bm'].get_value() is 'Y':
|
||||
attrs += "\t\t<bm_type>bmc</bm_type>\n"
|
||||
|
||||
return "\t<host>\n" + attrs + "\t</host>\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 = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" \
|
||||
"<hosts version=\"" + TiS_VERSION + "\">\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 += "</hosts>"
|
||||
|
||||
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()
|
@ -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'
|
||||
],
|
||||
}
|
||||
)
|
Binary file not shown.
Before Width: | Height: | Size: 32 KiB |
@ -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
|
@ -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',
|
||||
],
|
||||
}
|
||||
)
|
@ -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
|
@ -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
|
@ -1,2 +1,2 @@
|
||||
SRC_DIR="controllerconfig"
|
||||
TIS_PATCH_VER=150
|
||||
TIS_PATCH_VER=151
|
||||
|
@ -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
|
||||
|
@ -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',
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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
|
@ -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=' ')
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
|
@ -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}(?<!-)$", re.IGNORECASE) # noqa pylint: disable=anomalous-backslash-in-string
|
||||
return all(valid_re.match(x) for x in hostname.split("."))
|
||||
|
||||
|
||||
def is_valid_mac(mac):
|
||||
"""Verify the format of a MAC addres."""
|
||||
if not mac:
|
||||
return False
|
||||
m = "[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$"
|
||||
return isinstance(mac, six.string_types) and re.match(m, mac.lower())
|
||||
|
||||
|
||||
def validate_network_str(network_str, minimum_size,
|
||||
existing_networks=None, multicast=False):
|
||||
"""Determine whether a network is valid."""
|
||||
try:
|
||||
network = netaddr.IPNetwork(network_str)
|
||||
if network.ip != network.network:
|
||||
raise ValidateFail("Invalid network address")
|
||||
elif network.size < minimum_size:
|
||||
raise ValidateFail("Subnet too small - must have at least %d "
|
||||
"addresses" % minimum_size)
|
||||
elif network.version == 6 and network.prefixlen < 64:
|
||||
raise ValidateFail("IPv6 minimum prefix length is 64")
|
||||
elif existing_networks:
|
||||
if any(network.ip in subnet for subnet in existing_networks):
|
||||
raise ValidateFail("Subnet overlaps with another "
|
||||
"configured subnet")
|
||||
elif multicast and not network.is_multicast():
|
||||
raise ValidateFail("Invalid subnet - must be multicast")
|
||||
return network
|
||||
except netaddr.AddrFormatError:
|
||||
raise ValidateFail(
|
||||
"Invalid subnet - not a valid IP subnet")
|
||||
|
||||
|
||||
def is_valid_filename(filename):
|
||||
return '\0' not in filename
|
||||
|
||||
|
||||
def is_valid_by_path(filename):
|
||||
return "/dev/disk/by-path" in filename and "-part" not in filename
|
||||
|
||||
|
||||
def is_valid_url(url_str):
|
||||
# Django URL validation patterns
|
||||
r = re.compile(
|
||||
r'^(?:http|ftp)s?://' # http:// or https://
|
||||
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)' # domain...
|
||||
r'+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'
|
||||
r'localhost|' # localhost...
|
||||
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
|
||||
r'(?::\d+)?' # optional port
|
||||
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
|
||||
|
||||
url = r.match(url_str)
|
||||
if url:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_valid_domain(url_str):
|
||||
r = re.compile(
|
||||
r'^(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)' # domain...
|
||||
r'+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'
|
||||
r'[A-Za-z0-9-_]*)' # localhost, hostname
|
||||
r'(?::\d+)?' # optional port
|
||||
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
|
||||
|
||||
url = r.match(url_str)
|
||||
if url:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
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_domain_or_ip(url_str):
|
||||
if url_str:
|
||||
if is_valid_domain(url_str):
|
||||
return True
|
||||
ip_with_port = url_str.split(':')
|
||||
if len(ip_with_port) <= 2:
|
||||
# check ipv4 or ipv4 with port
|
||||
return is_valid_ipv4(ip_with_port[0])
|
||||
else:
|
||||
# check ipv6 with port
|
||||
if '[' in url_str:
|
||||
try:
|
||||
bkt_idx = url_str.index(']')
|
||||
if bkt_idx + 1 == len(url_str):
|
||||
# brackets without port
|
||||
return False
|
||||
else:
|
||||
return is_valid_ipv6(url_str[1:bkt_idx])
|
||||
except Exception:
|
||||
return False
|
||||
else:
|
||||
# check ipv6 without port
|
||||
return is_valid_ipv6(url_str)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_valid_bool_str(val):
|
||||
"""Check if the provided string is a valid bool string or not."""
|
||||
boolstrs = ('true', 'false')
|
||||
return str(val).lower() in boolstrs
|
||||
|
||||
|
||||
def validate_address_str(ip_address_str, network):
|
||||
"""Determine whether an address is valid."""
|
||||
try:
|
||||
ip_address = netaddr.IPAddress(ip_address_str)
|
||||
if ip_address.version != network.version:
|
||||
msg = ("Invalid IP version - must match network version " +
|
||||
ip_version_to_string(network.version))
|
||||
raise ValidateFail(msg)
|
||||
elif ip_address == network:
|
||||
raise ValidateFail("Cannot use network address")
|
||||
elif ip_address == network.broadcast:
|
||||
raise ValidateFail("Cannot use broadcast address")
|
||||
elif ip_address not in network:
|
||||
raise ValidateFail(
|
||||
"Address must be in subnet %s" % str(network))
|
||||
return ip_address
|
||||
except netaddr.AddrFormatError:
|
||||
raise ValidateFail(
|
||||
"Invalid address - not a valid IP address")
|
||||
|
||||
|
||||
def ip_version_to_string(ip_version):
|
||||
"""Determine whether a nameserver address is valid."""
|
||||
if ip_version == 4:
|
||||
return "IPv4"
|
||||
elif ip_version == 6:
|
||||
return "IPv6"
|
||||
else:
|
||||
return "IP"
|
||||
|
||||
|
||||
def validate_nameserver_address_str(ip_address_str, subnet_version=None):
|
||||
"""Determine whether a nameserver address is valid."""
|
||||
try:
|
||||
ip_address = netaddr.IPAddress(ip_address_str)
|
||||
if subnet_version is not None and ip_address.version != subnet_version:
|
||||
msg = ("Invalid IP version - must match OAM subnet version " +
|
||||
ip_version_to_string(subnet_version))
|
||||
raise ValidateFail(msg)
|
||||
return ip_address
|
||||
except netaddr.AddrFormatError:
|
||||
msg = "Invalid address - not a valid %s address" % \
|
||||
ip_version_to_string(subnet_version)
|
||||
raise ValidateFail(msg)
|
||||
|
||||
|
||||
def validate_address(ip_address, network):
|
||||
"""Determine whether an address is valid."""
|
||||
if ip_address.version != network.version:
|
||||
msg = ("Invalid IP version - must match network version " +
|
||||
ip_version_to_string(network.version))
|
||||
raise ValidateFail(msg)
|
||||
elif ip_address == network:
|
||||
raise ValidateFail("Cannot use network address")
|
||||
elif ip_address == network.broadcast:
|
||||
raise ValidateFail("Cannot use broadcast address")
|
||||
elif ip_address not in network:
|
||||
raise ValidateFail("Address must be in subnet %s" % str(network))
|
||||
|
||||
|
||||
def check_network_overlap(new_network, configured_networks):
|
||||
""" Validate that new_network does not overlap any configured_networks.
|
||||
"""
|
||||
if any(new_network.ip in subnet for subnet in
|
||||
configured_networks):
|
||||
raise ValidateFail(
|
||||
"Subnet %s overlaps with another configured subnet" % new_network)
|
||||
|
||||
|
||||
def validate_openstack_password(password, rules_file,
|
||||
section="security_compliance"):
|
||||
try:
|
||||
config = configparser.RawConfigParser()
|
||||
parsed_config = config.read(rules_file)
|
||||
if not parsed_config:
|
||||
msg = ("Cannot parse rules file: %s" % rules_file)
|
||||
raise Exception(msg)
|
||||
if not config.has_section(section):
|
||||
msg = ("Required section '%s' not found in rules file" % section)
|
||||
raise Exception(msg)
|
||||
|
||||
password_regex = get_optional(config, section, 'password_regex')
|
||||
password_regex_description = get_optional(config, section,
|
||||
'password_regex_description')
|
||||
|
||||
if not password_regex:
|
||||
msg = ("Required option 'password_regex' not found in "
|
||||
"rule file: %s" % rules_file)
|
||||
raise Exception(msg)
|
||||
# Even if regex_description is not found, we will proceed
|
||||
# and give a generic failure warning instead
|
||||
if not password_regex_description:
|
||||
password_regex_description = ("Password does not meet "
|
||||
"complexity criteria")
|
||||
|
||||
if not isinstance(password, six.string_types):
|
||||
msg = "Password must be a string type"
|
||||
raise Exception(msg)
|
||||
try:
|
||||
# config parser would read in the string as a literal
|
||||
# representation which would fail regex matching
|
||||
password_regex = password_regex.strip('"')
|
||||
if not re.match(password_regex, password):
|
||||
return False, password_regex_description
|
||||
except re.error:
|
||||
msg = ("Unable to validate password due to invalid "
|
||||
"complexity criteria ('password_regex')")
|
||||
raise Exception(msg)
|
||||
except Exception:
|
||||
raise Exception("Password validation failed")
|
||||
return True, ""
|
||||
|
||||
|
||||
def extract_openstack_password_rules_from_file(
|
||||
rules_file, section="security_compliance"):
|
||||
try:
|
||||
config = configparser.RawConfigParser()
|
||||
parsed_config = config.read(rules_file)
|
||||
if not parsed_config:
|
||||
msg = ("Cannot parse rules file: %s" % rules_file)
|
||||
raise Exception(msg)
|
||||
if not config.has_section(section):
|
||||
msg = ("Required section '%s' not found in rules file" % section)
|
||||
raise Exception(msg)
|
||||
|
||||
rules = config.items(section)
|
||||
if not rules:
|
||||
msg = ("section '%s' contains no configuration options" % section)
|
||||
raise Exception(msg)
|
||||
return dict(rules)
|
||||
except Exception:
|
||||
raise Exception("Failed to extract password rules from file")
|
||||
|
||||
|
||||
def get_optional(conf, section, key):
|
||||
if conf.has_option(section, key):
|
||||
return conf.get(section, key)
|
||||
return None
|
||||
|
||||
|
||||
def get_service(conf, section, key):
|
||||
if key in EXPECTED_SERVICE_NAME_AND_TYPE:
|
||||
if conf.has_option(section, key):
|
||||
value = conf.get(section, key)
|
||||
if value != EXPECTED_SERVICE_NAME_AND_TYPE[key]:
|
||||
raise ValidateFail("Unsupported %s: %s " % (key, value))
|
||||
else:
|
||||
value = EXPECTED_SERVICE_NAME_AND_TYPE[key]
|
||||
return value
|
||||
else:
|
||||
return conf.get(section, key)
|
||||
|
@ -14,7 +14,6 @@ whitelist_externals = find
|
||||
install_command = pip install --no-cache-dir -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/pike} {opts} {packages}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
-e{[tox]stxdir}/stx-config/configutilities/configutilities
|
||||
-e{[tox]stxdir}/stx-fault/fm-api
|
||||
-e{[tox]stxdir}/stx-update/tsconfig/tsconfig
|
||||
-e{[tox]stxdir}/stx-config/sysinv/sysinv/sysinv
|
||||
|
@ -4,6 +4,8 @@
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation
|
||||
#
|
||||
# Copyright (c) 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# lib/stx-config
|
||||
# Functions to control the configuration and operation of stx-config
|
||||
|
||||
@ -36,7 +38,6 @@ STX_SYSCONFDIR=${STX_SYSCONFDIR:-/etc}
|
||||
# Set up GITDIR so setup_lib and setup_dev_lib work properly
|
||||
GITDIR["cgts-client"]=$STX_CONFIG_DIR/sysinv/cgts-client/cgts-client
|
||||
|
||||
STX_CONF_UTILS_DIR=$STX_CONFIG_DIR/configutilities/configutilities
|
||||
STX_CTRL_CONF_DIR=$STX_CONFIG_DIR/controllerconfig/controllerconfig
|
||||
|
||||
SYSINV_DIR=$STX_CONFIG_DIR/sysinv/sysinv/sysinv
|
||||
@ -88,7 +89,6 @@ function cleanup_cgtsclient {
|
||||
function cleanup_config {
|
||||
if is_service_enabled sysinv; then
|
||||
cleanup_sysinv
|
||||
cleanup_configutilities
|
||||
cleanup_controllerconfig
|
||||
fi
|
||||
|
||||
@ -97,10 +97,6 @@ function cleanup_config {
|
||||
fi
|
||||
}
|
||||
|
||||
function cleanup_configutilities {
|
||||
pip_uninstall configutilities
|
||||
}
|
||||
|
||||
function cleanup_controllerconfig {
|
||||
pip_uninstall controllerconfig
|
||||
|
||||
@ -230,7 +226,6 @@ function install_config {
|
||||
install_cgtsclient
|
||||
fi
|
||||
if is_service_enabled sysinv; then
|
||||
install_configutilities
|
||||
install_controllerconfig
|
||||
install_sysinv
|
||||
fi
|
||||
@ -239,11 +234,6 @@ function install_config {
|
||||
fi
|
||||
}
|
||||
|
||||
function install_configutilities {
|
||||
# We can't use setup_develop as there is no setup.cfg file present for configutilities
|
||||
setup_package $STX_CONF_UTILS_DIR -e
|
||||
}
|
||||
|
||||
function install_controllerconfig {
|
||||
# This is a hack to work around the lack of proper global-requirements
|
||||
# setup in these packages
|
||||
|
@ -1,2 +1,2 @@
|
||||
SRC_DIR="sysinv"
|
||||
TIS_PATCH_VER=309
|
||||
TIS_PATCH_VER=310
|
||||
|
@ -16,8 +16,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Copyright (c) 2013-2018 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import ast
|
||||
import cgi
|
||||
@ -42,7 +43,7 @@ import wsme
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from wsme import types as wtypes
|
||||
from configutilities import HOST_XML_ATTRIBUTES
|
||||
from controllerconfig import HOST_XML_ATTRIBUTES
|
||||
from fm_api import constants as fm_constants
|
||||
from fm_api import fm_api
|
||||
from pecan import expose
|
||||
|
@ -38,7 +38,6 @@ setenv = VIRTUAL_ENV={envdir}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
-e{[tox]stxdir}/stx-update/tsconfig/tsconfig
|
||||
-e{[tox]stxdir}/stx-config/configutilities/configutilities
|
||||
-e{[tox]stxdir}/stx-fault/fm-api
|
||||
-e{[tox]stxdir}/stx-fault/python-fmclient/fmclient
|
||||
-e{[tox]stxdir}/stx-config/controllerconfig/controllerconfig
|
||||
|
Loading…
Reference in New Issue
Block a user