StarlingX open source release updates
Signed-off-by: Dean Troyer <dtroyer@gmail.com>
This commit is contained in:
parent
48eda4de1e
commit
9d3ca49387
7
CONTRIBUTORS.wrs
Normal file
7
CONTRIBUTORS.wrs
Normal file
@ -0,0 +1,7 @@
|
||||
The following contributors from Wind River have developed the seed code in this
|
||||
repository. We look forward to community collaboration and contributions for
|
||||
additional features, enhancements and refactoring.
|
||||
|
||||
Contributors:
|
||||
=============
|
||||
Wind River Titanium Cloud Team
|
202
LICENSE
Normal file
202
LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
5
README.rst
Normal file
5
README.rst
Normal file
@ -0,0 +1,5 @@
|
||||
============
|
||||
stx-upstream
|
||||
============
|
||||
|
||||
StarlingX Upstream Packages
|
6
ceph-manager/.gitignore
vendored
Normal file
6
ceph-manager/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
!.distro
|
||||
.distro/centos7/rpmbuild/RPMS
|
||||
.distro/centos7/rpmbuild/SRPMS
|
||||
.distro/centos7/rpmbuild/BUILD
|
||||
.distro/centos7/rpmbuild/BUILDROOT
|
||||
.distro/centos7/rpmbuild/SOURCES/ceph-manager*tar.gz
|
202
ceph-manager/LICENSE
Normal file
202
ceph-manager/LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
13
ceph-manager/PKG-INFO
Normal file
13
ceph-manager/PKG-INFO
Normal file
@ -0,0 +1,13 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: ceph-manager
|
||||
Version: 1.0
|
||||
Summary: Handle Ceph API calls and provide status updates via alarms
|
||||
Home-page:
|
||||
Author: Windriver
|
||||
Author-email: info@windriver.com
|
||||
License: Apache-2.0
|
||||
|
||||
Description: Handle Ceph API calls and provide status updates via alarms
|
||||
|
||||
|
||||
Platform: UNKNOWN
|
3
ceph-manager/centos/build_srpm.data
Normal file
3
ceph-manager/centos/build_srpm.data
Normal file
@ -0,0 +1,3 @@
|
||||
SRC_DIR="ceph-manager"
|
||||
COPY_LIST_TO_TAR="files scripts"
|
||||
TIS_PATCH_VER=4
|
70
ceph-manager/centos/ceph-manager.spec
Normal file
70
ceph-manager/centos/ceph-manager.spec
Normal file
@ -0,0 +1,70 @@
|
||||
Summary: Handle Ceph API calls and provide status updates via alarms
|
||||
Name: ceph-manager
|
||||
Version: 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
|
||||
|
||||
BuildRequires: python-setuptools
|
||||
BuildRequires: systemd-units
|
||||
BuildRequires: systemd-devel
|
||||
Requires: sysinv
|
||||
|
||||
%description
|
||||
Handle Ceph API calls and provide status updates via alarms.
|
||||
Handle sysinv RPC calls for long running Ceph API operations:
|
||||
- cache tiering enable
|
||||
- cache tiering disable
|
||||
|
||||
%define local_bindir /usr/bin/
|
||||
%define local_etc_initd /etc/init.d/
|
||||
%define local_etc_logrotated /etc/logrotate.d/
|
||||
%define pythonroot /usr/lib64/python2.7/site-packages
|
||||
|
||||
%define debug_package %{nil}
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
%{__python} setup.py build
|
||||
|
||||
%install
|
||||
%{__python} setup.py install --root=$RPM_BUILD_ROOT \
|
||||
--install-lib=%{pythonroot} \
|
||||
--prefix=/usr \
|
||||
--install-data=/usr/share \
|
||||
--single-version-externally-managed
|
||||
|
||||
install -d -m 755 %{buildroot}%{local_etc_initd}
|
||||
install -p -D -m 700 scripts/init.d/ceph-manager %{buildroot}%{local_etc_initd}/ceph-manager
|
||||
|
||||
install -d -m 755 %{buildroot}%{local_bindir}
|
||||
install -p -D -m 700 scripts/bin/ceph-manager %{buildroot}%{local_bindir}/ceph-manager
|
||||
|
||||
install -d -m 755 %{buildroot}%{local_etc_logrotated}
|
||||
install -p -D -m 644 files/ceph-manager.logrotate %{buildroot}%{local_etc_logrotated}/ceph-manager.logrotate
|
||||
|
||||
install -d -m 755 %{buildroot}%{_unitdir}
|
||||
install -m 644 -p -D files/%{name}.service %{buildroot}%{_unitdir}/%{name}.service
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
# Note: The package name is ceph-manager but the import name is ceph_manager so
|
||||
# can't use '%{name}'.
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc LICENSE
|
||||
%{local_bindir}/*
|
||||
%{local_etc_initd}/*
|
||||
%{_unitdir}/%{name}.service
|
||||
%dir %{local_etc_logrotated}
|
||||
%{local_etc_logrotated}/*
|
||||
%dir %{pythonroot}/ceph_manager
|
||||
%{pythonroot}/ceph_manager/*
|
||||
%dir %{pythonroot}/ceph_manager-%{version}.0-py2.7.egg-info
|
||||
%{pythonroot}/ceph_manager-%{version}.0-py2.7.egg-info/*
|
202
ceph-manager/ceph-manager/LICENSE
Normal file
202
ceph-manager/ceph-manager/LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
5
ceph-manager/ceph-manager/ceph_manager/__init__.py
Normal file
5
ceph-manager/ceph-manager/ceph_manager/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
705
ceph-manager/ceph-manager/ceph_manager/cache_tiering.py
Normal file
705
ceph-manager/ceph-manager/ceph_manager/cache_tiering.py
Normal file
@ -0,0 +1,705 @@
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import copy
|
||||
import contextlib
|
||||
import functools
|
||||
import math
|
||||
import subprocess
|
||||
import time
|
||||
import traceback
|
||||
# noinspection PyUnresolvedReferences
|
||||
import eventlet
|
||||
# noinspection PyUnresolvedReferences
|
||||
from eventlet.semaphore import Semaphore
|
||||
# noinspection PyUnresolvedReferences
|
||||
from oslo_log import log as logging
|
||||
# noinspection PyUnresolvedReferences
|
||||
from sysinv.conductor.cache_tiering_service_config import ServiceConfig
|
||||
|
||||
from i18n import _LI, _LW, _LE
|
||||
|
||||
import constants
|
||||
import exception
|
||||
import ceph
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CEPH_POOLS = copy.deepcopy(constants.CEPH_POOLS)
|
||||
|
||||
MAX_WAIT = constants.CACHE_FLUSH_MAX_WAIT_OBJ_COUNT_DECREASE_SEC
|
||||
MIN_WAIT = constants.CACHE_FLUSH_MIN_WAIT_OBJ_COUNT_DECREASE_SEC
|
||||
|
||||
|
||||
class LockOwnership(object):
|
||||
def __init__(self, sem):
|
||||
self.sem = sem
|
||||
|
||||
@contextlib.contextmanager
|
||||
def __call__(self):
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
if self.sem:
|
||||
self.sem.release()
|
||||
|
||||
def transfer(self):
|
||||
new_lo = LockOwnership(self.sem)
|
||||
self.sem = None
|
||||
return new_lo
|
||||
|
||||
|
||||
class Lock(object):
|
||||
|
||||
def __init__(self):
|
||||
self.sem = Semaphore(value=1)
|
||||
|
||||
def try_lock(self):
|
||||
result = self.sem.acquire(blocking=False)
|
||||
if result:
|
||||
return LockOwnership(self.sem)
|
||||
|
||||
|
||||
class CacheTiering(object):
|
||||
|
||||
def __init__(self, service):
|
||||
self.service = service
|
||||
self.lock = Lock()
|
||||
# will be unlocked by set_initial_config()
|
||||
self._init_config_lock = self.lock.try_lock()
|
||||
self.config = None
|
||||
self.config_desired = None
|
||||
self.config_applied = None
|
||||
self.target_max_bytes = {}
|
||||
|
||||
def set_initial_config(self, config):
|
||||
with self._init_config_lock():
|
||||
LOG.info("Setting Ceph cache tiering initial configuration")
|
||||
self.config = ServiceConfig.from_dict(
|
||||
config.get(constants.CACHE_TIERING, {})) or \
|
||||
ServiceConfig()
|
||||
self.config_desired = ServiceConfig.from_dict(
|
||||
config.get(constants.CACHE_TIERING_DESIRED, {})) or \
|
||||
ServiceConfig()
|
||||
self.config_applied = ServiceConfig.from_dict(
|
||||
config.get(constants.CACHE_TIERING_APPLIED, {})) or \
|
||||
ServiceConfig()
|
||||
if self.config_desired:
|
||||
LOG.debug("set_initial_config config_desired %s " %
|
||||
self.config_desired.to_dict())
|
||||
if self.config_applied:
|
||||
LOG.debug("set_initial_config config_applied %s " %
|
||||
self.config_applied.to_dict())
|
||||
|
||||
# Check that previous caching tier operation completed
|
||||
# successfully or perform recovery
|
||||
if (self.config_desired and
|
||||
self.config_applied and
|
||||
(self.config_desired.cache_enabled !=
|
||||
self.config_applied.cache_enabled)):
|
||||
if self.config_desired.cache_enabled:
|
||||
self.enable_cache(self.config_desired.to_dict(),
|
||||
self.config_applied.to_dict(),
|
||||
self._init_config_lock.transfer())
|
||||
else:
|
||||
self.disable_cache(self.config_desired.to_dict(),
|
||||
self.config_applied.to_dict(),
|
||||
self._init_config_lock.transfer())
|
||||
|
||||
def is_locked(self):
|
||||
lock_ownership = self.lock.try_lock()
|
||||
if not lock_ownership:
|
||||
return True
|
||||
with lock_ownership():
|
||||
return False
|
||||
|
||||
def update_pools_info(self):
|
||||
global CEPH_POOLS
|
||||
cfg = self.service.sysinv_conductor.call(
|
||||
{}, 'get_ceph_pools_config')
|
||||
CEPH_POOLS = copy.deepcopy(cfg)
|
||||
LOG.info(_LI("update_pools_info: pools: {}").format(CEPH_POOLS))
|
||||
|
||||
def enable_cache(self, new_config, applied_config, lock_ownership=None):
|
||||
new_config = ServiceConfig.from_dict(new_config)
|
||||
applied_config = ServiceConfig.from_dict(applied_config)
|
||||
if not lock_ownership:
|
||||
lock_ownership = self.lock.try_lock()
|
||||
if not lock_ownership:
|
||||
raise exception.CephCacheEnableFailure()
|
||||
with lock_ownership():
|
||||
eventlet.spawn(self.do_enable_cache,
|
||||
new_config, applied_config,
|
||||
lock_ownership.transfer())
|
||||
|
||||
def do_enable_cache(self, new_config, applied_config, lock_ownership):
|
||||
LOG.info(_LI("cache_tiering_enable_cache: "
|
||||
"new_config={}, applied_config={}").format(
|
||||
new_config.to_dict(), applied_config.to_dict()))
|
||||
_unwind_actions = []
|
||||
with lock_ownership():
|
||||
success = False
|
||||
_exception = None
|
||||
try:
|
||||
self.config_desired.cache_enabled = True
|
||||
self.update_pools_info()
|
||||
for pool in CEPH_POOLS:
|
||||
if (pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_JEWEL or
|
||||
pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_HAMMER):
|
||||
object_pool_name = \
|
||||
self.service.monitor._get_object_pool_name()
|
||||
pool['pool_name'] = object_pool_name
|
||||
|
||||
self.cache_pool_create(pool)
|
||||
_unwind_actions.append(
|
||||
functools.partial(self.cache_pool_delete, pool))
|
||||
for pool in CEPH_POOLS:
|
||||
if (pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_JEWEL or
|
||||
pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_HAMMER):
|
||||
object_pool_name = \
|
||||
self.service.monitor._get_object_pool_name()
|
||||
pool['pool_name'] = object_pool_name
|
||||
|
||||
self.cache_tier_add(pool)
|
||||
_unwind_actions.append(
|
||||
functools.partial(self.cache_tier_remove, pool))
|
||||
for pool in CEPH_POOLS:
|
||||
if (pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_JEWEL or
|
||||
pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_HAMMER):
|
||||
object_pool_name = \
|
||||
self.service.monitor._get_object_pool_name()
|
||||
pool['pool_name'] = object_pool_name
|
||||
|
||||
self.cache_mode_set(pool, 'writeback')
|
||||
self.cache_pool_set_config(pool, new_config)
|
||||
self.cache_overlay_create(pool)
|
||||
success = True
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to enable cache: reason=%s') %
|
||||
traceback.format_exc())
|
||||
for action in reversed(_unwind_actions):
|
||||
try:
|
||||
action()
|
||||
except Exception:
|
||||
LOG.warn(_LW('Failed cache enable '
|
||||
'unwind action: reason=%s') %
|
||||
traceback.format_exc())
|
||||
success = False
|
||||
_exception = str(e)
|
||||
finally:
|
||||
self.service.monitor.monitor_check_cache_tier(success)
|
||||
if success:
|
||||
self.config_applied.cache_enabled = True
|
||||
self.service.sysinv_conductor.call(
|
||||
{}, 'cache_tiering_enable_cache_complete',
|
||||
success=success, exception=_exception,
|
||||
new_config=new_config.to_dict(),
|
||||
applied_config=applied_config.to_dict())
|
||||
# Run first update of periodic target_max_bytes
|
||||
self.update_cache_target_max_bytes()
|
||||
|
||||
@contextlib.contextmanager
|
||||
def ignore_ceph_failure(self):
|
||||
try:
|
||||
yield
|
||||
except exception.CephManagerException:
|
||||
pass
|
||||
|
||||
def disable_cache(self, new_config, applied_config, lock_ownership=None):
|
||||
new_config = ServiceConfig.from_dict(new_config)
|
||||
applied_config = ServiceConfig.from_dict(applied_config)
|
||||
if not lock_ownership:
|
||||
lock_ownership = self.lock.try_lock()
|
||||
if not lock_ownership:
|
||||
raise exception.CephCacheDisableFailure()
|
||||
with lock_ownership():
|
||||
eventlet.spawn(self.do_disable_cache,
|
||||
new_config, applied_config,
|
||||
lock_ownership.transfer())
|
||||
|
||||
def do_disable_cache(self, new_config, applied_config, lock_ownership):
|
||||
LOG.info(_LI("cache_tiering_disable_cache: "
|
||||
"new_config={}, applied_config={}").format(
|
||||
new_config, applied_config))
|
||||
with lock_ownership():
|
||||
success = False
|
||||
_exception = None
|
||||
try:
|
||||
self.config_desired.cache_enabled = False
|
||||
for pool in CEPH_POOLS:
|
||||
if (pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_JEWEL or
|
||||
pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_HAMMER):
|
||||
object_pool_name = \
|
||||
self.service.monitor._get_object_pool_name()
|
||||
pool['pool_name'] = object_pool_name
|
||||
|
||||
with self.ignore_ceph_failure():
|
||||
self.cache_mode_set(
|
||||
pool, 'forward')
|
||||
|
||||
for pool in CEPH_POOLS:
|
||||
if (pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_JEWEL or
|
||||
pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_HAMMER):
|
||||
object_pool_name = \
|
||||
self.service.monitor._get_object_pool_name()
|
||||
pool['pool_name'] = object_pool_name
|
||||
|
||||
retries_left = 3
|
||||
while True:
|
||||
try:
|
||||
self.cache_flush(pool)
|
||||
break
|
||||
except exception.CephCacheFlushFailure:
|
||||
retries_left -= 1
|
||||
if not retries_left:
|
||||
# give up
|
||||
break
|
||||
else:
|
||||
time.sleep(1)
|
||||
for pool in CEPH_POOLS:
|
||||
if (pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_JEWEL or
|
||||
pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_HAMMER):
|
||||
object_pool_name = \
|
||||
self.service.monitor._get_object_pool_name()
|
||||
pool['pool_name'] = object_pool_name
|
||||
|
||||
with self.ignore_ceph_failure():
|
||||
self.cache_overlay_delete(pool)
|
||||
self.cache_tier_remove(pool)
|
||||
for pool in CEPH_POOLS:
|
||||
if (pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_JEWEL or
|
||||
pool['pool_name'] ==
|
||||
constants.CEPH_POOL_OBJECT_GATEWAY_NAME_HAMMER):
|
||||
object_pool_name = \
|
||||
self.service.monitor._get_object_pool_name()
|
||||
pool['pool_name'] = object_pool_name
|
||||
|
||||
with self.ignore_ceph_failure():
|
||||
self.cache_pool_delete(pool)
|
||||
success = True
|
||||
except Exception as e:
|
||||
LOG.warn(_LE('Failed to disable cache: reason=%s') %
|
||||
traceback.format_exc())
|
||||
_exception = str(e)
|
||||
finally:
|
||||
self.service.monitor.monitor_check_cache_tier(False)
|
||||
if success:
|
||||
self.config_desired.cache_enabled = False
|
||||
self.config_applied.cache_enabled = False
|
||||
self.service.sysinv_conductor.call(
|
||||
{}, 'cache_tiering_disable_cache_complete',
|
||||
success=success, exception=_exception,
|
||||
new_config=new_config.to_dict(),
|
||||
applied_config=applied_config.to_dict())
|
||||
|
||||
def get_pool_pg_num(self, pool_name):
|
||||
return self.service.sysinv_conductor.call(
|
||||
{}, 'get_pool_pg_num',
|
||||
pool_name=pool_name)
|
||||
|
||||
def cache_pool_create(self, pool):
|
||||
backing_pool = pool['pool_name']
|
||||
cache_pool = backing_pool + '-cache'
|
||||
pg_num = self.get_pool_pg_num(cache_pool)
|
||||
if not ceph.osd_pool_exists(self.service.ceph_api, cache_pool):
|
||||
ceph.osd_pool_create(
|
||||
self.service.ceph_api, cache_pool,
|
||||
pg_num, pg_num)
|
||||
|
||||
def cache_pool_delete(self, pool):
|
||||
cache_pool = pool['pool_name'] + '-cache'
|
||||
ceph.osd_pool_delete(
|
||||
self.service.ceph_api, cache_pool)
|
||||
|
||||
def cache_tier_add(self, pool):
|
||||
backing_pool = pool['pool_name']
|
||||
cache_pool = backing_pool + '-cache'
|
||||
response, body = self.service.ceph_api.osd_tier_add(
|
||||
backing_pool, cache_pool,
|
||||
force_nonempty="--force-nonempty",
|
||||
body='json')
|
||||
if response.ok:
|
||||
LOG.info(_LI("Added OSD tier: "
|
||||
"backing_pool={}, cache_pool={}").format(
|
||||
backing_pool, cache_pool))
|
||||
else:
|
||||
e = exception.CephPoolAddTierFailure(
|
||||
backing_pool=backing_pool,
|
||||
cache_pool=cache_pool,
|
||||
response_status_code=response.status_code,
|
||||
response_reason=response.reason,
|
||||
status=body.get('status'),
|
||||
output=body.get('output'))
|
||||
LOG.warn(e)
|
||||
raise e
|
||||
|
||||
def cache_tier_remove(self, pool):
|
||||
backing_pool = pool['pool_name']
|
||||
cache_pool = backing_pool + '-cache'
|
||||
response, body = self.service.ceph_api.osd_tier_remove(
|
||||
backing_pool, cache_pool, body='json')
|
||||
if response.ok:
|
||||
LOG.info(_LI("Removed OSD tier: "
|
||||
"backing_pool={}, cache_pool={}").format(
|
||||
backing_pool, cache_pool))
|
||||
else:
|
||||
e = exception.CephPoolRemoveTierFailure(
|
||||
backing_pool=backing_pool,
|
||||
cache_pool=cache_pool,
|
||||
response_status_code=response.status_code,
|
||||
response_reason=response.reason,
|
||||
status=body.get('status'),
|
||||
output=body.get('output'))
|
||||
LOG.warn(e)
|
||||
raise e
|
||||
|
||||
def cache_mode_set(self, pool, mode):
|
||||
backing_pool = pool['pool_name']
|
||||
cache_pool = backing_pool + '-cache'
|
||||
response, body = self.service.ceph_api.osd_tier_cachemode(
|
||||
cache_pool, mode, body='json')
|
||||
if response.ok:
|
||||
LOG.info(_LI("Set OSD tier cache mode: "
|
||||
"cache_pool={}, mode={}").format(cache_pool, mode))
|
||||
else:
|
||||
e = exception.CephCacheSetModeFailure(
|
||||
cache_pool=cache_pool,
|
||||
mode=mode,
|
||||
response_status_code=response.status_code,
|
||||
response_reason=response.reason,
|
||||
status=body.get('status'),
|
||||
output=body.get('output'))
|
||||
LOG.warn(e)
|
||||
raise e
|
||||
|
||||
def cache_pool_set_config(self, pool, config):
|
||||
for name, value in config.params.iteritems():
|
||||
self.cache_pool_set_param(pool, name, value)
|
||||
|
||||
def cache_pool_set_param(self, pool, name, value):
|
||||
backing_pool = pool['pool_name']
|
||||
cache_pool = backing_pool + '-cache'
|
||||
ceph.osd_set_pool_param(
|
||||
self.service.ceph_api, cache_pool, name, value)
|
||||
|
||||
def cache_overlay_create(self, pool):
|
||||
backing_pool = pool['pool_name']
|
||||
cache_pool = backing_pool + '-cache'
|
||||
response, body = self.service.ceph_api.osd_tier_set_overlay(
|
||||
backing_pool, cache_pool, body='json')
|
||||
if response.ok:
|
||||
LOG.info(_LI("Set OSD tier overlay: "
|
||||
"backing_pool={}, cache_pool={}").format(
|
||||
backing_pool, cache_pool))
|
||||
else:
|
||||
e = exception.CephCacheCreateOverlayFailure(
|
||||
backing_pool=backing_pool,
|
||||
cache_pool=cache_pool,
|
||||
response_status_code=response.status_code,
|
||||
response_reason=response.reason,
|
||||
status=body.get('status'),
|
||||
output=body.get('output'))
|
||||
LOG.warn(e)
|
||||
raise e
|
||||
|
||||
def cache_overlay_delete(self, pool):
|
||||
backing_pool = pool['pool_name']
|
||||
cache_pool = pool['pool_name']
|
||||
response, body = self.service.ceph_api.osd_tier_remove_overlay(
|
||||
backing_pool, body='json')
|
||||
if response.ok:
|
||||
LOG.info(_LI("Removed OSD tier overlay: "
|
||||
"backing_pool={}").format(backing_pool))
|
||||
else:
|
||||
e = exception.CephCacheDeleteOverlayFailure(
|
||||
backing_pool=backing_pool,
|
||||
cache_pool=cache_pool,
|
||||
response_status_code=response.status_code,
|
||||
response_reason=response.reason,
|
||||
status=body.get('status'),
|
||||
output=body.get('output'))
|
||||
LOG.warn(e)
|
||||
raise e
|
||||
|
||||
@staticmethod
|
||||
def rados_cache_flush_evict_all(pool):
|
||||
backing_pool = pool['pool_name']
|
||||
cache_pool = backing_pool + '-cache'
|
||||
try:
|
||||
subprocess.check_call(
|
||||
['/usr/bin/rados', '-p', cache_pool, 'cache-flush-evict-all'])
|
||||
LOG.info(_LI("Flushed OSD cache pool:"
|
||||
"cache_pool={}").format(cache_pool))
|
||||
except subprocess.CalledProcessError as e:
|
||||
_e = exception.CephCacheFlushFailure(
|
||||
cache_pool=cache_pool,
|
||||
return_code=str(e.returncode),
|
||||
cmd=" ".join(e.cmd),
|
||||
output=e.output)
|
||||
LOG.warn(_e)
|
||||
raise _e
|
||||
|
||||
def cache_flush(self, pool):
|
||||
backing_pool = pool['pool_name']
|
||||
cache_pool = backing_pool + '-cache'
|
||||
try:
|
||||
# set target_max_objects to a small value to force evacuation of
|
||||
# objects from cache before we use rados cache-flush-evict-all
|
||||
# WARNING: assuming cache_pool will be deleted after flush so
|
||||
# we don't have to save/restore the value of target_max_objects
|
||||
#
|
||||
self.cache_pool_set_param(pool, 'target_max_objects', 1)
|
||||
prev_object_count = None
|
||||
wait_interval = MIN_WAIT
|
||||
while True:
|
||||
response, body = self.service.ceph_api.df(body='json')
|
||||
if not response.ok:
|
||||
LOG.warn(_LW(
|
||||
"Failed to retrieve cluster free space stats: "
|
||||
"status_code=%d, reason=%s") % (
|
||||
response.status_code, response.reason))
|
||||
break
|
||||
stats = None
|
||||
for s in body['output']['pools']:
|
||||
if s['name'] == cache_pool:
|
||||
stats = s['stats']
|
||||
break
|
||||
if not stats:
|
||||
LOG.warn(_LW("Missing pool free space stats: "
|
||||
"cache_pool=%s") % cache_pool)
|
||||
break
|
||||
object_count = stats['objects']
|
||||
if object_count < constants.CACHE_FLUSH_OBJECTS_THRESHOLD:
|
||||
break
|
||||
if prev_object_count is not None:
|
||||
delta_objects = object_count - prev_object_count
|
||||
if delta_objects > 0:
|
||||
LOG.warn(_LW("Unexpected increase in number "
|
||||
"of objects in cache pool: "
|
||||
"cache_pool=%s, prev_object_count=%d, "
|
||||
"object_count=%d") % (
|
||||
cache_pool, prev_object_count,
|
||||
object_count))
|
||||
break
|
||||
if delta_objects == 0:
|
||||
wait_interval *= 2
|
||||
if wait_interval > MAX_WAIT:
|
||||
LOG.warn(_LW(
|
||||
"Cache pool number of objects did not "
|
||||
"decrease: cache_pool=%s, object_count=%d, "
|
||||
"wait_interval=%d") % (
|
||||
cache_pool, object_count, wait_interval))
|
||||
break
|
||||
else:
|
||||
wait_interval = MIN_WAIT
|
||||
time.sleep(wait_interval)
|
||||
prev_object_count = object_count
|
||||
except exception.CephPoolSetParamFailure as e:
|
||||
LOG.warn(e)
|
||||
finally:
|
||||
self.rados_cache_flush_evict_all(pool)
|
||||
|
||||
def update_cache_target_max_bytes(self):
|
||||
"Dynamically compute target_max_bytes of caching pools"
|
||||
|
||||
# Only compute if cache tiering is enabled
|
||||
if self.config_applied and self.config_desired:
|
||||
if (not self.config_desired.cache_enabled or
|
||||
not self.config_applied.cache_enabled):
|
||||
LOG.debug("Cache tiering disabled, no need to update "
|
||||
"target_max_bytes.")
|
||||
return
|
||||
LOG.debug("Updating target_max_bytes")
|
||||
|
||||
# Get available space
|
||||
response, body = self.service.ceph_api.osd_df(body='json',
|
||||
output_method='tree')
|
||||
if not response.ok:
|
||||
LOG.warn(_LW(
|
||||
"Failed to retrieve cluster free space stats: "
|
||||
"status_code=%d, reason=%s") % (
|
||||
response.status_code, response.reason))
|
||||
return
|
||||
|
||||
storage_tier_size = 0
|
||||
cache_tier_size = 0
|
||||
|
||||
replication = constants.CEPH_REPLICATION_FACTOR
|
||||
for node in body['output']['nodes']:
|
||||
if node['name'] == 'storage-tier':
|
||||
storage_tier_size = node['kb']*1024/replication
|
||||
elif node['name'] == 'cache-tier':
|
||||
cache_tier_size = node['kb']*1024/replication
|
||||
|
||||
if storage_tier_size == 0 or cache_tier_size == 0:
|
||||
LOG.info("Failed to get cluster size "
|
||||
"(storage_tier_size=%s, cache_tier_size=%s),"
|
||||
"retrying on next cycle" %
|
||||
(storage_tier_size, cache_tier_size))
|
||||
return
|
||||
|
||||
# Get available pools
|
||||
response, body = self.service.ceph_api.osd_lspools(body='json')
|
||||
if not response.ok:
|
||||
LOG.warn(_LW(
|
||||
"Failed to retrieve available pools: "
|
||||
"status_code=%d, reason=%s") % (
|
||||
response.status_code, response.reason))
|
||||
return
|
||||
pools = [p['poolname'] for p in body['output']]
|
||||
|
||||
# Separate backing from caching for easy iteration
|
||||
backing_pools = []
|
||||
caching_pools = []
|
||||
for p in pools:
|
||||
if p.endswith('-cache'):
|
||||
caching_pools.append(p)
|
||||
else:
|
||||
backing_pools.append(p)
|
||||
LOG.debug("Pools: caching: %s, backing: %s" % (caching_pools,
|
||||
backing_pools))
|
||||
|
||||
if not len(caching_pools):
|
||||
# We do not have caching pools created yet
|
||||
return
|
||||
|
||||
# Get quota from backing pools that are cached
|
||||
stats = {}
|
||||
for p in caching_pools:
|
||||
backing_name = p.replace('-cache', '')
|
||||
stats[backing_name] = {}
|
||||
try:
|
||||
quota = ceph.osd_pool_get_quota(self.service.ceph_api,
|
||||
backing_name)
|
||||
except exception.CephPoolGetQuotaFailure as e:
|
||||
LOG.warn(_LW(
|
||||
"Failed to retrieve quota: "
|
||||
"exception: %s") % str(e))
|
||||
return
|
||||
stats[backing_name]['quota'] = quota['max_bytes']
|
||||
stats[backing_name]['quota_pt'] = (quota['max_bytes']*100.0 /
|
||||
storage_tier_size)
|
||||
LOG.debug("Quota for pool: %s "
|
||||
"is: %s B representing %s pt" %
|
||||
(backing_name,
|
||||
quota['max_bytes'],
|
||||
stats[backing_name]['quota_pt']))
|
||||
|
||||
# target_max_bytes logic:
|
||||
# - For computing target_max_bytes cache_tier_size must be equal than
|
||||
# the sum of target_max_bytes of each caching pool
|
||||
# - target_max_bytes for each caching pool is computed as the
|
||||
# percentage of quota in corresponding backing pool
|
||||
# - the caching tiers has to work at full capacity, so if the sum of
|
||||
# all quotas in the backing tier is different than 100% we need to
|
||||
# normalize
|
||||
# - if the quota is zero for any pool we add CACHE_TIERING_MIN_QUOTA
|
||||
# by default *after* normalization so that we have real minimum
|
||||
|
||||
# We compute the real percentage that need to be normalized after
|
||||
# ensuring that we have CACHE_TIERING_MIN_QUOTA for each pool with
|
||||
# a quota of 0
|
||||
real_100pt = 90.0 # we start from max and decrease it for each 0 pool
|
||||
# Note: We must avoid reaching 100% at all costs! and
|
||||
# cache_target_full_ratio, the Ceph parameter that is supposed to
|
||||
# protect the cluster against this does not work in Ceph v0.94.6!
|
||||
# Therefore a value of 90% is better suited for this
|
||||
for p in caching_pools:
|
||||
backing_name = p.replace('-cache', '')
|
||||
if stats[backing_name]['quota_pt'] == 0:
|
||||
real_100pt -= constants.CACHE_TIERING_MIN_QUOTA
|
||||
LOG.debug("Quota before normalization for %s is: %s pt" %
|
||||
(p, stats[backing_name]['quota_pt']))
|
||||
|
||||
# Compute total percentage of quotas for all backing pools.
|
||||
# Should be 100% if correctly configured
|
||||
total_quota_pt = 0
|
||||
for p in caching_pools:
|
||||
backing_name = p.replace('-cache', '')
|
||||
total_quota_pt += stats[backing_name]['quota_pt']
|
||||
LOG.debug("Total quota pt is: %s" % total_quota_pt)
|
||||
|
||||
# Normalize quota pt to 100% (or real_100pt)
|
||||
if total_quota_pt != 0: # to avoid divide by zero
|
||||
for p in caching_pools:
|
||||
backing_name = p.replace('-cache', '')
|
||||
stats[backing_name]['quota_pt'] = \
|
||||
(stats[backing_name]['quota_pt'] *
|
||||
(real_100pt / total_quota_pt))
|
||||
|
||||
# Do not allow quota to be 0 for any pool
|
||||
total = 0
|
||||
for p in caching_pools:
|
||||
backing_name = p.replace('-cache', '')
|
||||
if stats[backing_name]['quota_pt'] == 0:
|
||||
stats[backing_name]['quota_pt'] = \
|
||||
constants.CACHE_TIERING_MIN_QUOTA
|
||||
total += stats[backing_name]['quota_pt']
|
||||
LOG.debug("Quota after normalization for %s is: %s:" %
|
||||
(p, stats[backing_name]['quota_pt']))
|
||||
|
||||
if total > 100:
|
||||
# Supplementary protection, we really have to avoid going above
|
||||
# 100%. Note that real_100pt is less than 100% but we still got
|
||||
# more than 100!
|
||||
LOG.warn("Total sum of quotas should not go above 100% "
|
||||
"but is: %s, recalculating in next cycle" % total)
|
||||
return
|
||||
LOG.debug("Total sum of quotas is %s pt" % total)
|
||||
|
||||
# Get current target_max_bytes. We cache it to reduce requests
|
||||
# to ceph-rest-api. We are the ones changing it, so not an issue.
|
||||
for p in caching_pools:
|
||||
if p not in self.target_max_bytes:
|
||||
try:
|
||||
value = ceph.osd_get_pool_param(self.service.ceph_api, p,
|
||||
constants.TARGET_MAX_BYTES)
|
||||
except exception.CephPoolGetParamFailure as e:
|
||||
LOG.warn(e)
|
||||
return
|
||||
self.target_max_bytes[p] = value
|
||||
LOG.debug("Existing target_max_bytes got from "
|
||||
"Ceph: %s" % self.target_max_bytes)
|
||||
|
||||
# Set TARGET_MAX_BYTES
|
||||
LOG.debug("storage_tier_size: %s "
|
||||
"cache_tier_size: %s" % (storage_tier_size,
|
||||
cache_tier_size))
|
||||
for p in caching_pools:
|
||||
backing_name = p.replace('-cache', '')
|
||||
s = stats[backing_name]
|
||||
target_max_bytes = math.floor(s['quota_pt'] * cache_tier_size /
|
||||
100.0)
|
||||
target_max_bytes = int(target_max_bytes)
|
||||
LOG.debug("New Target max bytes of pool: %s is: %s B" % (
|
||||
p, target_max_bytes))
|
||||
|
||||
# Set the new target_max_bytes only if it changed
|
||||
if self.target_max_bytes.get(p) == target_max_bytes:
|
||||
LOG.debug("Target max bytes of pool: %s "
|
||||
"is already updated" % p)
|
||||
continue
|
||||
try:
|
||||
ceph.osd_set_pool_param(self.service.ceph_api, p,
|
||||
constants.TARGET_MAX_BYTES,
|
||||
target_max_bytes)
|
||||
self.target_max_bytes[p] = target_max_bytes
|
||||
except exception.CephPoolSetParamFailure as e:
|
||||
LOG.warn(e)
|
||||
continue
|
||||
return
|
164
ceph-manager/ceph-manager/ceph_manager/ceph.py
Normal file
164
ceph-manager/ceph-manager/ceph_manager/ceph.py
Normal file
@ -0,0 +1,164 @@
|
||||
#
|
||||
# Copyright (c) 2016-2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import exception
|
||||
from i18n import _LI
|
||||
# noinspection PyUnresolvedReferences
|
||||
from oslo_log import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def osd_pool_set_quota(ceph_api, pool_name, max_bytes=0, max_objects=0):
|
||||
"""Set the quota for an OSD pool_name
|
||||
Setting max_bytes or max_objects to 0 will disable that quota param
|
||||
:param pool_name: OSD pool_name
|
||||
:param max_bytes: maximum bytes for OSD pool_name
|
||||
:param max_objects: maximum objects for OSD pool_name
|
||||
"""
|
||||
|
||||
# Update quota if needed
|
||||
prev_quota = osd_pool_get_quota(ceph_api, pool_name)
|
||||
if prev_quota["max_bytes"] != max_bytes:
|
||||
resp, b = ceph_api.osd_set_pool_quota(pool_name, 'max_bytes',
|
||||
max_bytes, body='json')
|
||||
if resp.ok:
|
||||
LOG.info(_LI("Set OSD pool_name quota: "
|
||||
"pool_name={}, max_bytes={}").format(
|
||||
pool_name, max_bytes))
|
||||
else:
|
||||
e = exception.CephPoolSetQuotaFailure(
|
||||
pool=pool_name, name='max_bytes',
|
||||
value=max_bytes, reason=resp.reason)
|
||||
LOG.error(e)
|
||||
raise e
|
||||
if prev_quota["max_objects"] != max_objects:
|
||||
resp, b = ceph_api.osd_set_pool_quota(pool_name, 'max_objects',
|
||||
max_objects,
|
||||
body='json')
|
||||
if resp.ok:
|
||||
LOG.info(_LI("Set OSD pool_name quota: "
|
||||
"pool_name={}, max_objects={}").format(
|
||||
pool_name, max_objects))
|
||||
else:
|
||||
e = exception.CephPoolSetQuotaFailure(
|
||||
pool=pool_name, name='max_objects',
|
||||
value=max_objects, reason=resp.reason)
|
||||
LOG.error(e)
|
||||
raise e
|
||||
|
||||
|
||||
def osd_pool_get_quota(ceph_api, pool_name):
|
||||
resp, quota = ceph_api.osd_get_pool_quota(pool_name, body='json')
|
||||
if not resp.ok:
|
||||
e = exception.CephPoolGetQuotaFailure(
|
||||
pool=pool_name, reason=resp.reason)
|
||||
LOG.error(e)
|
||||
raise e
|
||||
else:
|
||||
return {"max_objects": quota["output"]["quota_max_objects"],
|
||||
"max_bytes": quota["output"]["quota_max_bytes"]}
|
||||
|
||||
|
||||
def osd_pool_exists(ceph_api, pool_name):
|
||||
response, body = ceph_api.osd_pool_get(
|
||||
pool_name, "pg_num", body='json')
|
||||
if response.ok:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def osd_pool_create(ceph_api, pool_name, pg_num, pgp_num):
|
||||
if pool_name.endswith("-cache"):
|
||||
# ruleset 1: is the ruleset for the cache tier
|
||||
# Name: cache_tier_ruleset
|
||||
ruleset = 1
|
||||
else:
|
||||
# ruleset 0: is the default ruleset if no crushmap is loaded or
|
||||
# the ruleset for the backing tier if loaded:
|
||||
# Name: storage_tier_ruleset
|
||||
ruleset = 0
|
||||
response, body = ceph_api.osd_pool_create(
|
||||
pool_name, pg_num, pgp_num, pool_type="replicated",
|
||||
ruleset=ruleset, body='json')
|
||||
if response.ok:
|
||||
LOG.info(_LI("Created OSD pool: "
|
||||
"pool_name={}, pg_num={}, pgp_num={}, "
|
||||
"pool_type=replicated, ruleset={}").format(
|
||||
pool_name, pg_num, pgp_num, ruleset))
|
||||
else:
|
||||
e = exception.CephPoolCreateFailure(
|
||||
name=pool_name, reason=response.reason)
|
||||
LOG.error(e)
|
||||
raise e
|
||||
|
||||
# Explicitly assign the ruleset to the pool on creation since it is
|
||||
# ignored in the create call
|
||||
response, body |