StarlingX open source release updates

Signed-off-by: Dean Troyer <dtroyer@gmail.com>
This commit is contained in:
Dean Troyer 2018-05-30 16:17:30 -07:00
parent 05c408a5cd
commit 85cd488bef
714 changed files with 172490 additions and 0 deletions

10
CONTRIBUTORS.wrs Normal file
View File

@ -0,0 +1,10 @@
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:
=============
Bart Wensley <Barton.Wensley@windriver.com>
Tao Liu <Tao.Liu@windriver.com>
Eric Macdonald <Eric.MacDonald@windriver.com>
Jack Ding <Jack.Ding@windriver.com>

202
LICENSE Normal file
View 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
View File

@ -0,0 +1,5 @@
=======
stx-nfv
=======
StarlingX NFVI Orchestration

12
guest-agent/PKG-INFO Normal file
View File

@ -0,0 +1,12 @@
Metadata-Version: 1.1
Name: guest-scale-agent
Version: 2.0
Summary: Titanium Cloud agent and helper app to scale VMs up/down
Home-page:
Author: Windriver
Author-email: info@windriver.com
License: Apache-2.0
Description: Titanium Cloud agent and helper app to scale VMs up/down
Platform: UNKNOWN

View File

@ -0,0 +1,2 @@
SRC_DIR="guest-scale-agent-2.0"
TIS_PATCH_VER=6

View File

@ -0,0 +1,137 @@
Summary: Titanium Cloud agent and helper app to scale VMs up/down
Name: guest-scale-agent
Version: 2.0
%define patchlevel %{tis_patch_ver}
Release: %{tis_patch_ver}%{?_tis_dist}
License: Apache-2.0
Group: base
Packager: Wind River <info@windriver.com>
URL: unknown
%define cgcs_sdk_deploy_dir /opt/deploy/cgcs_sdk
Source0: %{name}-%{version}.tar.gz
BuildRequires: json-c-devel
BuildRequires: host-guest-comm-dev
BuildRequires: guest-host-comm-dev
BuildRequires: systemd-devel
Requires: bash
%description
Titanium Cloud agent and helper app to scale VMs up/down
%package -n guest-scale-agent-dbg
Summary: Titanium Cloud agent and helper app to scale VMs up/down - Debugging files
Group: devel
%description -n guest-scale-agent-dbg
Titanium Cloud agent and helper app to scale VMs up/down This package contains ELF
symbols and related sources for debugging purposes.
%package -n guest-scale-agent-dev
Summary: Titanium Cloud agent and helper app to scale VMs up/down - Development files
Group: devel
Requires: guest-scale-agent = %{version}-%{release}
%description -n guest-scale-agent-dev
Titanium Cloud agent and helper app to scale VMs up/down This package contains
symbolic links, header files, and related items necessary for software
development.
%package -n guest-scale-helper
Summary: Titanium Cloud agent and helper app to scale VMs up/down
Group: base
Requires: rtld(GNU_HASH)
%description -n guest-scale-helper
Titanium Cloud agent and helper app to scale VMs up/down
%package -n %{name}-cgts-sdk
Summary: SDK files for Titanium Cloud agent and helper app to scale VMs up/down
Group: devel
%description -n %{name}-cgts-sdk
SDK files for Titanium Cloud agent and helper app to scale VMs up/down
%prep
%setup
%build
VER=%{version}
MAJOR=`echo $VER | awk -F . '{print $1}'`
MINOR=`echo $VER | awk -F . '{print $2}'`
PATCH=%{patchlevel}
make all VER=${VER} MAJOR=${MAJOR} MINOR=${MINOR} PATCH=${PATCH}
%global _buildsubdir %{_builddir}/%{name}-%{version}
%install
install -d 750 -d %{buildroot}/usr/sbin
install -d 750 -d %{buildroot}%{_sysconfdir}/init.d
install -m 750 -d %{buildroot}/usr
install -m 750 -d %{buildroot}/usr/src
install -m 750 -d %{buildroot}/usr/src/debug
install -m 750 -d %{buildroot}/usr/src/debug/%{name}-%{version}
install -d 750 -d %{buildroot}/usr/sbin/.debug
install -m 750 %{_buildsubdir}/scripts/app_scale_helper %{buildroot}/usr/sbin/app_scale_helper
install -m 750 %{_buildsubdir}/scripts/offline_cpus %{buildroot}/usr/sbin/offline_cpus
install -m 750 %{_buildsubdir}/bin/guest_scale_helper %{buildroot}/usr/sbin/guest_scale_helper
install -m 750 %{_buildsubdir}/bin/guest_scale_agent %{buildroot}/usr/sbin/guest_scale_agent
install -m 750 %{_buildsubdir}/scripts/init_offline_cpus %{buildroot}/etc/init.d/offline_cpus
install -m 750 %{_buildsubdir}/bin/guest_scale_agent %{buildroot}/usr/sbin/.debug/guest_scale_agent
install -d %{buildroot}%{_unitdir}
install -m 750 %{_buildsubdir}/scripts/offline-cpus.service %{buildroot}%{_unitdir}/offline-cpus.service
install -m 750 %{_buildsubdir}/scripts/guest-scale-agent.service %{buildroot}%{_unitdir}/guest-scale-agent.service
# Deploy to the SDK deployment directory
install -d %{buildroot}%{cgcs_sdk_deploy_dir}
install -m 644 sdk/wrs-guest-scale-%{version}.%{patchlevel}.tgz %{buildroot}%{cgcs_sdk_deploy_dir}/wrs-guest-scale-%{version}.%{patchlevel}.tgz
%post
%systemd_post offline-cpus.service
%systemd_post guest-scale-agent.service
/usr/bin/systemctl enable offline-cpus.service >/dev/null 2>&1
/usr/bin/systemctl enable guest-scale-agent.service >/dev/null 2>&1
%preun
%systemd_preun offline-cpus.service
%systemd_preun guest-scale-agent.service
%postun
%systemd_postun guest-scale-agent.service
%systemd_postun offline-cpus.service
%files
%defattr(-,root,root,-)
/usr/sbin/guest_scale_agent
/usr/sbin/offline_cpus
/usr/sbin/app_scale_helper
/etc/init.d/offline_cpus
%{_unitdir}/offline-cpus.service
%{_unitdir}/guest-scale-agent.service
%files -n guest-scale-agent-dbg
%defattr(-,root,root,-)
/usr/src/debug/*
/usr/sbin/.debug/guest_scale_agent
%files -n guest-scale-agent-dev
%defattr(-,root,root,-)
/usr/sbin/.debug/guest_scale_agent
%files -n guest-scale-helper
%defattr(-,root,root,-)
/usr/sbin/guest_scale_helper
%files -n %{name}-cgts-sdk
%{cgcs_sdk_deploy_dir}/wrs-guest-scale-%{version}.%{patchlevel}.tgz

View 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.

View File

@ -0,0 +1,110 @@
#
# BSD LICENSE
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Note: if you change either Makefile or Makefile.sdk you need to manually
# do a "make clean" and then "make".
EXECS = guest_scale_helper guest_scale_agent
CFLAGS= -g -Wall
ODIR=obj
BINDIR=bin
BINEXECS=$(addprefix $(BINDIR)/, $(EXECS))
GUEST_SCALE_HELPER_SRCS = guest_scale_helper.c parser.c
GUEST_SCALE_HELPER_OBJ := $(patsubst %,$(ODIR)/%,$(GUEST_SCALE_HELPER_SRCS:.c=.o))
GUEST_SCALE_AGENT_SRCS= guest_scale_agent.c parser.c
GUEST_SCALE_AGENT_OBJ := $(patsubst %,$(ODIR)/%,$(GUEST_SCALE_AGENT_SRCS:.c=.o))
OBJS = $(GUEST_SCALE_OBJ) $(GUEST_SCALE_AGENT_OBJ)
DEPS = $(OBJS:.o=.d) sdk/sdk.d
-include $(DEPS)
EXPORT_SDK := wrs-guest-scale-$(MAJOR).$(MINOR).$(PATCH)
# SYSROOT = $(shell for i in $(LD) ; do echo $$i; done | grep sysroot= | awk -F = '{ print $$2 }'`)
SYSROOT = $(shell echo "$(LD)" | sed -n -e 's/^.*sysroot=//p' | awk '{ print $$1 }')
LIBSERVERGROUP_VER = $(shell find $(SYSROOT) | grep libservergroup.so. | sed -n -e 's/^.*libservergroup\.so\.//p')
print-%:
@echo $* = $($*)
printvars:
@$(foreach V,$(sort $(.VARIABLES)), $(if $(filter-out environment% default automatic, $(origin $V)),$(warning $V=$($V) ($(value $V)))))
.PHONY: printvars
all: host_all
host_all: $(BINEXECS) sdk/$(EXPORT_SDK).tgz
# The dependency tracking for the SDK tarball is rather crude. If any
# file changes they're all copied over again. This is quick, so it's
# not worth getting fancy.
sdk/$(EXPORT_SDK).tgz: printvars
@echo "Making SDK"
@mkdir -p sdk/$(EXPORT_SDK)
@mkdir -p sdk/$(EXPORT_SDK)/bin
@mkdir -p sdk/$(EXPORT_SDK)/obj
@mkdir -p sdk/$(EXPORT_SDK)/scripts
@cp scripts/* sdk/$(EXPORT_SDK)/scripts
@echo "MAJOR=$(MAJOR)" > sdk/$(EXPORT_SDK)/Makefile
@echo "MINOR=$(MINOR)" >> sdk/$(EXPORT_SDK)/Makefile
@echo "PATCH=$(PATCH)" >> sdk/$(EXPORT_SDK)/Makefile
@cat Makefile.sdk >> sdk/$(EXPORT_SDK)/Makefile
@cat docs/README.txt | sed 's/1\.0\.0/$(MAJOR).$(MINOR).$(PATCH)/' | sed 's/9.9.9/${LIBSERVERGROUP_VER}/' > sdk/$(EXPORT_SDK)/README.txt
@cp docs/TiS-Guest-Resource-Scaling.pdf sdk/$(EXPORT_SDK)/TiS-Guest-Resource-Scaling.pdf
@cp LICENSE sdk/$(EXPORT_SDK)/LICENSE
@cp $(GUEST_SCALE_AGENT_SRCS) sdk/$(EXPORT_SDK)
@cp misc.h sdk/$(EXPORT_SDK)
@cd sdk && tar czf $(EXPORT_SDK).tgz $(EXPORT_SDK)
@echo -n "sdk/$(EXPORT_SDK).tgz: Makefile.sdk docs/README.txt docs/TiS-Guest-Resource-Scaling.pdf " > sdk/sdk.d
@echo -n "scripts/init_offline_cpus scripts/offline_cpus scripts/offline-cpus.service" >> sdk/sdk.d
@echo -n "scripts/app_scale_helper " >> sdk/sdk.d
@echo -n "$(GUEST_SCALE_AGENT_SRCS) " >> sdk/sdk.d
@echo "misc.h " >> sdk/sdk.d
@echo '*' > sdk/.gitignore
$(ODIR)/%.o: %.c
$(CC) -c $(CFLAGS) $(CFLAGS2) -MMD -o $@ $<
$(BINDIR)/guest_scale_agent: $(GUEST_SCALE_AGENT_OBJ)
$(CC) -o $@ $^ $(LDFLAGS) -lguesthostmsg -ljson-c
$(BINDIR)/guest_scale_helper: $(GUEST_SCALE_HELPER_OBJ)
$(CC) -o $@ $^ $(LDFLAGS) -lhostguestmsg -ljson-c
# Add the host clean as a dependency to the SDK stuff
clean: host_clean
host_clean:
rm -rf sdk

View File

@ -0,0 +1,74 @@
#
# BSD LICENSE
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
.PHONY: all clean
EXECS= guest_scale_agent
CFLAGS= -g -Wall
ODIR=obj
BINDIR=bin
GUEST_SCALE_AGENT_SRCS= guest_scale_agent.c parser.c
GUEST_SCALE_AGENT_OBJ := $(patsubst %,$(ODIR)/%,$(GUEST_SCALE_AGENT_SRCS:.c=.o))
BINEXECS=$(addprefix $(BINDIR)/, $(EXECS))
OBJS = $(GUEST_SCALE_AGENT_OBJ)
_DEPS = *.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
DEPS = $(OBJS:.o=.d)
-include $(DEPS)
WRS_SERVER_GROUP_DIR ?= $(shell find ../wrs-server-group*[0-9] -maxdepth 0 -type d | sort | tail -n 1)
WRS_SERVER_GROUP_INC2 = $(WRS_SERVER_GROUP_DIR)/include
WRS_SERVER_GROUP_INC ?= $(shell if [ -d $(WRS_SERVER_GROUP_INC2) ]; then echo "$(WRS_SERVER_GROUP_INC2)"; else echo "/usr/include"; fi)
WRS_SERVER_GROUP_LIB2 = $(WRS_SERVER_GROUP_DIR)/lib
WRS_SERVER_GROUP_LIB3 = $(shell if [ -d /usr/lib64 ]; then echo "/usr/lib64"; else echo "/usr/lib"; fi)
WRS_SERVER_GROUP_LIB ?= $(shell if [ -d $(WRS_SERVER_GROUP_LIB2) ]; then echo "$(WRS_SERVER_GROUP_LIB2)"; else echo "$(WRS_SERVER_GROUP_LIB3)"; fi)
CFLAGS += -I$(WRS_SERVER_GROUP_INC)
LDFLAGS += -L$(WRS_SERVER_GROUP_LIB)
$(ODIR)/%.o: %.c
$(CC) -c $(CFLAGS) $(CFLAGS2) -MMD -o $@ $<
all: $(BINEXECS)
$(BINDIR)/guest_scale_agent: $(GUEST_SCALE_AGENT_OBJ)
$(CC) -o $@ $^ $(LDFLAGS) -lguesthostmsg -ljson-c
clean:
rm -rf $(ODIR)/* *~ core $(BINDIR)/*

View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -0,0 +1,243 @@
BSD LICENSE
Copyright(c) 2013-2016, Wind River Systems, Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Wind River Systems nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------
DESCRIPTION
===========
Guest Server Scaling is a service to allow a guest to scale the capacity of a
single guest server up and down on demand.
Current supported scaling operation is CPU scaling.
The resources can be scaled up/down from the nova CLI or GUI. Scaling can also
be set up via heat to be automatically triggered based on Ceilometer statistics.
(This will not be covered in this document, see the full documentation and the
heat SDK for how to configure heat templates for scaling a single guest server.)
This package contains an agent and a number of scripts to be included in the
guest image. These will handle the guest side of the coordinated efforts
involved in scaling up/down guest resources.
DEPENDENCIES
============
NOTE that this wrs-guest-scale SDK module has both a compile-time and run-time
dependency on the wrs-server-group SDK module.
This wrs-guest-scale SDK module requires that the wrs-server-group SDK tarball
has been previously extracted and built, and that the resulting libraries
and headers have been placed in a location that can be found by the normal build
tools, or the WRS_SERVER_GROUP_DIR environment variable has been set.
The output of BOTH the wrs-guest-scale SDK module and the wrs-server-group SDK
module are required to be installed in a guest image for guest resource scaling.
REQUIREMENTS
============
Compilation:
Linux OS, x86_64 architecture
gcc compiler
development libraries and headers for glibc
development libraries and headers for libguesthostmsg
(built by the wrs-server-group SDK package)
development libraries and headers for json-c
VM Runtime:
Linux OS, x86_64 architecture; CONFIG_HOTPLUG_CPU=y|m
runtime libraries for glibc
runtime libraries for libguesthostmsg
"guest_agent" binary daemon
(provided by the wrs-server-group SDK package)
runtime libraries for json-c
The code has been tested with glibc 2.15, gcc 4.6 and json-c 0.12.99 but it
should run on other versions without difficulty.
DELIVERABLE
===========
The Guest Server Scaling service is delivered as source with the required
Makefiles in a compressed tarball called "wrs-guest-scale-#.#.#.tgz", such that
it can be compiled for the applicable guest linux distribution.
COMPILE
=======
Pre-requisite:
Ensure that the wrs-server-group SDK tarball has been previously extracted and
built, and that the resulting libraries and headers have been placed in a
location that can be found by the normal build tools, or the WRS_SERVER_GROUP_DIR
environment variable has been set.
Extract the tarball contents:
tar xvf wrs-guest-scale-#.#.#.tgz
To compile:
# Note: assumes wrs-server-group-#.#.#.tgz has already been extracted and compiled.
cd wrs-guest-scale-#.#.#
# If wrs-guest-scale-#.#.#.tgz and wrs-server-group-#.#.#.tgz where extracted in a common directory
make
# Otherwise supply the path to where wrs-server-group can be found. e.g.
make WRS_SERVER_GROUP_DIR=/usr/src/wrs-server-group-#.#.#
This will produce:
1) An executable "bin/guest_scale_agent". This handles the basic vCPU scaling
in the guest, and calls out to a helper script if present to support
application-specific customization. It should be configured to respawn
(via /etc/inittab or some other process monitor) if it dies for any reason.
This executable must be installed into the guest (e.g. in "/usr/sbin") and configured
to run at startup as early as possible.
NOTE
The "guest_agent" executable from the wrs-server-group SDK package MUST ALSO
be installed into the guest (e.g. in "/usr/bin"), configured to run at startup
as early as possible and configured to respawn via /etc/inittab or some other
process monitor (in case it dies for any reason).
2) A script "script/app_scale_helper". This is an optional script that is
intended to allow for app-specific customization. If present, it must be
installed in "/usr/sbin". If present, it will be called by "guest_scale_agent"
when scaling in either direction.
3) A script "script/offline_cpus". This must be run later in the init sequence,
after guest_scale_agent has started up but before the application has started
any CPU-affined applications. A helper script "script/init_offline_cpus" has
been provided, and should be installed to "/etc/init.d/offline_cpus. The
"offline_cpus" script will offline vCPUs in the guest to match the status on
the hypervisor. This covers the case where we are booting up with some CPUs
offlined by the hypervisor.
4) For systemd users, the files "scripts/guest-scale-agent.service" and
"scripts/offline-cpus.service" should be copied to /lib/systemd/system/.
Note:
The inclusion of the files into the build system and the guest image and the
configuration of the guest startup scripts is left up to the user to allow for
different build systems and init subsystems in the guest.
INSTALL
=======
Installing in a running VM:
As the root user
1) Copy "bin/guest_scale_agent" to /usr/sbin in the VM.
2) Copy "scripts/app_scale_helper" and "scripts/offline_cpus" to /usr/sbin in the VM.
3) Copy "scripts/init_offline_cpus" to "/etc/init.d/offline_cpus". (Note the name change.)
4) Copy "scripts/guest-scale-agent.service" and "scripts/offline-cpus.service" to
/lib/systemd/system/.
5) Run "systemctl enable guest-scale-agent.service", "systemctl enable offline-cpus.service",
"systemctl start guest-scale-agent.service", "systemctl start offline-cpus.service"
The VM should now be ready to scale up and down.
USAGE
=====
The service is designed to be simple to use. A basic description is given
below, but more details are provided in the source and scripts.
1) Create a new flavor (or edit an existing flavor) such that the number of
vCPUs in the flavor matches the desired maximum number of vCPUs. To specify the
minimum number of vCPUs, create an "extra spec" metadata entry for the flavor
with a key of "wrs:min_vcpus" and a value that is an integer number between one
and the max number of vCPUs. This can be done from the CLI or the GUI. (In the
GUI select the "Admin" tab, go to the "Flavor" navigation link, click on a
flavor name, select the "Extra Specs" tab, click on "Create", select
"Minimum Number of CPUs" from the pulldown, and enter the desired value.)
2) Build BOTH the wrs-server-group SDK package and this wrs-guest-scale package,
and install the output of BOTH packages in an image. Lastly, ensure that the
CONFIG_HOTPLUG_CPU kernel config option is set in the image kernel.
3) Boot the image. It will come up with the full set of vCPUs.
4) To reduce the number of online vCPUs in the guest server, run
"nova scale <server> cpu down" from the controller (or anywhere else you can run
nova commands). This will pass a message up into the guest, where it will be
handled by "guest_scale_agent". That in turn will call out to
"/usr/sbin/app_scale_helper" (if it exists) which is expected to pick a vCPU to
offline. This script can be modified/replaced as needed for application-
specific purposes. By default, it will select the highest-numbered online vCPU.
If the script isn't present or errors out, then "guest_scale_agent" will itself
select the highest-numbered online vCPU as the one to be offlined. It will then
tell the guest kernel to offline the selected vCPU, and will pass the selected
vCPU back down to the hypervisor, which will adjust vCPU affinity so that the
underlying physical CPU can be freed up for use by other VMs. At this point
displaying the information for the guest server will show it using less than the
maximum number of cpus.
5) To increase the number of online vCPUs, run "nova scale <server> cpu up".
Assuming the resources are available the hypervisor will allocate a physical CPU
and will associate it with the guest server. "guest_scale_agent" will set the
lowest-numbered offline vCPU to "online", and will pass the vCPU number to
"/usr/sbin/app_scale_helper" (if it exists) for the application to do any
special handling that may be required.
The behaviour of a scaled-down server during various nova operations is as
follows:
live migration: server remains scaled-down
pause/unpause: server remains scaled-down
stop/start: server remains scaled-down
evacuation: server remains scaled-down
rebuild: server remains scaled-down
automatic restart on crash: server remains scaled-down
cold migration: server reverts to max vcpus
resize: server reverts to max vcpus for the new flavor
If a snapshot is taken of a scaled-down server, a new server booting the
snapshot will start with the number of vCPUs specified by the flavor.
CAVEATS
=======
It is possible for the scale-up operation to fail if the compute node has
already allocated all of its resources to other guests. If this happens,
the system will not do any automatic migration to try to free up resources.
Manual action will be required to free up resources.
Any CPUs that are handling userspace DPDK/AVP packet processing should not be
offlined. It may appear to work, but may lead to packet loss. This can be
enforced by setting the wrs:min_vcpus value appropriately high.
If hyperthreading is used, the flavor must set hw:cpu_thread_policy to
isolate and set cpu_policy to dedicated.

View File

@ -0,0 +1,515 @@
/**
* Copyright (c) <2013-2016>, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <poll.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <cgcs/guest_host_msg.h>
#include <json-c/json.h>
#include "misc.h"
gh_info_t *info;
/* Scaling Request/Response message is encoded in JSON format.
The message sent out to UNIX socket is a null-terminated JSON format string
without embedded newlines.
Format:
{key:value,key:value,..., key:value}
Key/value pairs for Scaling Request:
"version": <integer> - version of the interface
"timeout_ms": <integer> - timeout for app_scale_helper scripts
"resource": cpu - indicate the resouce to scale.
Only cpu is currently supported.
"direction“: "up or down
"online_cpu": <integer> - vcpu number to online when scale up
"online_cpus": <array of integers> - array of current online cpus
when request was sent.
example: [0,1,2,3,4,5]
Key/value pairs for Scaling Response:
"version": <integer>
"resource": cpu
"direction“: "up or down
"online_cpu": <integer> - vcpu number to online when scale up
"offline_cpu": <integer> - actual offlined vcpu number
"online_cpus": <array of integers> - array of current online cpus
when response was sent.
"result": "success" or "fail"
"err_msg": <string> - error message if result is fail
*/
#define CPU_SCRIPT "/usr/sbin/app_scale_helper"
// generic function to call out to helper script
// need to add support for timeout in here in case script hangs
int call_helper_script(char *cmd, int timeout_ms)
{
FILE *fp;
int rc;
fp = popen(cmd, "w");
if (fp) {
rc = pclose(fp);
if (rc == -1) {
ERR_LOG("pclose failed: %m");
return -1;
} else {
if (WIFEXITED(rc)) {
rc = WEXITSTATUS(rc);
if (rc == 127) {
ERR_LOG("problem with shell or helper script, possibly script missing");
return -1;
} else
return rc;
} else {
return -1;
}
}
} else {
ERR_LOG("popen failed due to fork/pipe/memory");
return -1;
}
}
int online_cpu(unsigned cpu)
{
int fd;
int rc;
char buf[100];
char val;
snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%u/online", cpu);
fd = open(buf, O_RDWR);
if (fd < 0) {
ERR_LOG("can't open cpu online path: %m");
return -1;
}
rc = read(fd, &val, 1);
if (rc != 1){
ERR_LOG("can't read cpu online value: %m");
return -1;
}
if (val == '1') {
ERR_LOG("cpu %d is already online", cpu);
return 0;
}
val = '1';
rc = write(fd, &val, 1);
if (rc != 1){
ERR_LOG("can't set cpu %d online", cpu);
return -1;
}
return 0;
}
int offline_cpu(unsigned cpu)
{
int fd;
int rc;
char buf[100];
char val;
snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%u/online", cpu);
fd = open(buf, O_RDWR);
if (fd < 0) {
ERR_LOG("can't open cpu online path: %m");
return -1;
}
rc = read(fd, &val, 1);
if (rc != 1){
ERR_LOG("can't read cpu online value: %m");
return -1;
}
if (val == '0') {
ERR_LOG("cpu %d is already offline\n", cpu);
return 0;
}
val = '0';
rc = write(fd, &val, 1);
if (rc != 1){
ERR_LOG("can't set cpu %d offline", cpu);
return -1;
}
return 0;
}
// read /sys/devices/system/cpu/online and get the last cpu listed
int get_highest_online_cpu(void)
{
int fd, rc;
char buf[256];
char *start;
unsigned int cpu;
fd = open("/sys/devices/system/cpu/online", O_RDONLY);
if (fd < 0) {
ERR_LOG("can't fopen /sys/devices/system/cpu/online: %m");
return -1;
}
rc = read(fd, buf, sizeof(buf));
if (rc < 2) {
ERR_LOG("error parsing /sys/devices/system/cpu/online, too few chars");
return -1;
}
// go to the end of the string
start = buf+rc-1;
if(*start != '\n') {
ERR_LOG("error parsing /sys/devices/system/cpu/online, not null-terminated");
return -1;
}
// now go backwards until we get to a separator or the beginning of the string
while ((*start != ',') && (*start != '-') && (start != buf))
start--;
start++;
rc = sscanf(start, "%u", &cpu);
if (rc != 1) {
ERR_LOG("error parsing /sys/devices/system/cpu/online, bad number");
return -1;
}
return cpu;
}
char *get_online_cpu_range(void)
{
FILE *file;
int rc;
char *str = NULL;
file = fopen("/sys/devices/system/cpu/online", "r");
if (!file) {
ERR_LOG("can't fopen /sys/devices/system/cpu/online: %m");
return 0;
}
rc = fscanf(file, "%ms", &str);
if (rc != 1)
ERR_LOG("can't read /sys/devices/system/cpu/online: %m");
fclose(file);
return str;
}
void cpu_scale_down(json_object *jobj_request,
json_object *jobj_response)
{
char cmd[1000];
int cpu=-1;
int rc;
//build our command to send to the helper script
rc = snprintf(cmd, sizeof(cmd), "%s --cpu_del\n", CPU_SCRIPT);
if ((rc > sizeof(cmd)) || rc < 0) {
ERR_LOG("error generating command: %m");
goto pick_cpu;
}
struct json_object *jobj_timeout_ms;
int timeout_ms;
if (!json_object_object_get_ex(jobj_request, TIMEOUT_MS, &jobj_timeout_ms))
{
ERR_LOG("failed to parse timeout_ms");
goto failed;
}
errno = 0;
timeout_ms = json_object_get_int(jobj_timeout_ms);
if(errno){
ERR_LOG("Error converting timeout_ms: %s", strerror(errno));
goto failed;
}
// call app helper script to select cpu to offline
rc = call_helper_script(cmd, timeout_ms);
if (rc < 0) {
ERR_LOG("call to app helper script failed\n");
goto pick_cpu;
} else if (rc == 0) {
ERR_LOG("call to app helper script return invalid cpu number 0\n");
goto pick_cpu;
} else {
INFO_LOG("app helper script chose cpu %d to offline\n", rc);
cpu = rc;
}
pick_cpu:
// if the app helper script doesn't exist or didn't return
// a cpu to offline, pick one ourselves
if (cpu == -1) {
cpu = get_highest_online_cpu();
if (cpu <= 0) {
ERR_LOG("unable to find cpu to offline\n");
goto failed;
}
}
// try to offline selected cpu
rc = offline_cpu(cpu);
if (rc < 0) {
ERR_LOG("failed to set cpu %d offline\n", cpu);
goto failed;
}
INFO_LOG("set cpu %d offline", cpu);
// we have successfully offlined the cpu
json_object_object_add(jobj_response, RESULT, json_object_new_string("success"));
json_object_object_add(jobj_response, OFFLINE_CPU, json_object_new_int(cpu));
struct online_cpus *current_online_cpus = range_to_array(get_online_cpu_range());
// no need to release jobj_array as its ownership is transferred to jobj_response
struct json_object *jobj_array = new_json_obj_from_array(current_online_cpus);
json_object_object_add(jobj_response, ONLINE_CPUS, jobj_array);
return;
failed:
json_object_object_add(jobj_response, RESULT, json_object_new_string("fail"));
json_object_object_add(jobj_response, ERR_MSG, json_object_new_string(errorbuf));
return;
}
void cpu_scale_up(json_object *jobj_request,
json_object *jobj_response)
{
char cmd[1000];
struct json_object *jobj_timeout_ms;
if (!json_object_object_get_ex(jobj_request, TIMEOUT_MS, &jobj_timeout_ms)) {
ERR_LOG("failed to parse timeout_ms");
goto failed;
}
int timeout_ms = json_object_get_int(jobj_timeout_ms);
struct json_object *jobj_cpu;
if (!json_object_object_get_ex(jobj_request, ONLINE_CPU, &jobj_cpu)) {
ERR_LOG("failed to parse online_cpu");
goto failed;
}
int cpu = json_object_get_int(jobj_cpu);
//online_cpus is optional
struct json_object *jobj_online_cpus;
const char *online_cpus;
if (!json_object_object_get_ex(jobj_request, ONLINE_CPUS, &jobj_online_cpus)) {
ERR_LOG("failed to parse online_cpus");
goto failed;
}
json_object_object_get_ex(jobj_request, ONLINE_CPUS, &jobj_online_cpus);
if (!json_object_is_type(jobj_online_cpus, json_type_array)) {
ERR_LOG("failed to parse online_cpus");
goto failed;
}
online_cpus = json_object_to_json_string_ext(jobj_online_cpus, JSON_C_TO_STRING_PLAIN);
int rc = online_cpu(cpu);
if (rc < 0) {
printf("failed to set cpu %d online\n", cpu);
goto failed;
}
INFO_LOG("set cpu %d online", cpu);
// Now try to call out to the helper script
// If it fails, not the end of the world.
rc = snprintf(cmd, sizeof(cmd), "%s --cpu_add %d %s\n",
CPU_SCRIPT, cpu, online_cpus);
if ((rc > 0) && (rc < sizeof(cmd))) {
rc = call_helper_script(cmd, timeout_ms);
if (rc != 0)
ERR_LOG("call to app helper script failed, return code: %d\n", rc);
} else
ERR_LOG("error generating command: %m");
json_object_object_add(jobj_response, RESULT, json_object_new_string("success"));
json_object_object_add(jobj_response, ONLINE_CPU, json_object_new_int(cpu));
struct online_cpus *current_online_cpus = range_to_array(get_online_cpu_range());
// no need to release jobj_array as its ownership is transferred to jobj_response
struct json_object *jobj_array = new_json_obj_from_array(current_online_cpus);
json_object_object_add(jobj_response, ONLINE_CPUS, jobj_array);
return;
failed:
json_object_object_add(jobj_response, RESULT, json_object_new_string("fail"));
json_object_object_add(jobj_response, ERR_MSG, json_object_new_string(errorbuf));
return;
}
/* Callback message handler. This will be called by the generic guest/host
* messaging library when a valid message arrives from the host.
*/
void msg_handler(const char *source_addr, json_object *jobj_request)
{
int rc;
// parse version
struct json_object *jobj_version;
if (!json_object_object_get_ex(jobj_request, VERSION, &jobj_version)) {
ERR_LOG("failed to parse version");
return;
}
int version = json_object_get_int(jobj_version);
if (version != CUR_VERSION) {
ERR_LOG("invalid version %d, expecting %d", version, CUR_VERSION);
return;
}
// parse msg_type
struct json_object *jobj_msg_type;
if (!json_object_object_get_ex(jobj_request, MSG_TYPE, &jobj_msg_type)) {
ERR_LOG("failed to parse msg_type");
return;
}
const char *msg_type = json_object_get_string(jobj_msg_type);
if (!strcmp(msg_type, MSG_TYPE_NACK)) {
struct json_object *jobj_log_msg;
if (!json_object_object_get_ex(jobj_request, LOG_MSG, &jobj_log_msg)) {
ERR_LOG("Nack: failed to parse log_msg");
}
const char *log_msg = json_object_get_string(jobj_log_msg);
ERR_LOG("Nack received, error message from host: %s", log_msg);
return;
} else if (!strcmp(msg_type, MSG_TYPE_SCALE_REQUEST)) {
;
} else {
ERR_LOG("unknown message type: %s", msg_type);
return;
}
struct json_object *jobj_response = json_object_new_object();
if (jobj_response == NULL) {
ERR_LOG("failed to allocate json object for response");
return;
}
struct json_object *jobj_resource;
if (!json_object_object_get_ex(jobj_request, RESOURCE, &jobj_resource)) {
ERR_LOG("failed to parse resource");
goto done;
}
const char *resource = json_object_get_string(jobj_resource);
struct json_object *jobj_direction;
if (!json_object_object_get_ex(jobj_request, DIRECTION, &jobj_direction)) {
ERR_LOG("failed to parse direction'");
goto done;
}
const char *direction = json_object_get_string(jobj_direction);
rc = -1;
if (!strcmp(resource,"cpu")) {
if (!strcmp(direction,"up")) {
cpu_scale_up(jobj_request, jobj_response);
} else if (!strcmp(direction,"down")) {
cpu_scale_down(jobj_request, jobj_response);
}
}
json_object_object_add(jobj_response, VERSION, json_object_new_int(CUR_VERSION));
json_object_object_add(jobj_response, RESOURCE, jobj_resource);
json_object_object_add(jobj_response, DIRECTION, jobj_direction);
const char *response = json_object_to_json_string_ext(jobj_response, JSON_C_TO_STRING_PLAIN);
// Send response back to the sender.
rc = gh_send_msg(info, source_addr, response);
if (rc < 0) {
ERR_LOG("gh_send_msg failed: %s\n", gh_get_error(info));
return;
}
done:
json_object_put(jobj_response);
}
void wait_for_messages(int fd)
{
int rc;
fd_set rfds, rfds_tmp;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
while(1) {
rfds_tmp = rfds;
rc = select(fd+1, &rfds_tmp, NULL, NULL, NULL);
if (rc > 0) {
if (gh_process_msg(info) < 0) {
ERR_LOG("problem processing messages: %s\n",
gh_get_error(info));
}
} else if (rc < 0) {
ERR_LOG("select(): %m");
}
}
}
int main()
{
int fd = gh_init(msg_handler, SCALE_AGENT_ADDR, &info);
if (fd == -1) {
if (!info)
ERR_LOG("Unable to allocate memory for info: %m");
else
ERR_LOG("Unable to initialize guest/host messaging: %s\n",
gh_get_error(info));
return -1;
}
INFO_LOG("Running offline_cpus script");
system("offline_cpus");
wait_for_messages(fd);
return 0;
}

View File

@ -0,0 +1,534 @@
/**
* Copyright (c) <2013-2016>, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This is intended to run as a helper function, called by nova, to pass data up
* into the guest and receive data back from the guest and return it to nova.
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <cgcs/host_guest_msg.h>
#include <json-c/json.h>
#include "misc.h"
hg_info_t *info;
#define SPARE_ALLOC 128
#define INSTANCE_NAME_SIZE 32
#define NACK_LOG_SIZE 500
#define UNIX_ADDR_LEN 16
#define DEFAULT_TIMEOUT_MS 1000
#define TIMEOUT_OVERHEAD_MS 500
#define MIN_SCRIPT_TIMEOUT_MS 500
int timeout_ms = DEFAULT_TIMEOUT_MS;
int *request_online_cpus;
int len_request_online_cpus;
int request_cpu;
void usage() {
printf("guest_scale_helper --instance_name <name>\n");
printf(" --cpu_del | --cpu_add <index> <cur_mask>\n");
printf(" [--timeout <millisec, at least 1000>]\n");
printf("\n");
exit(-1);
}
void handle_cpu_scale_up(json_object *jobj_response, const char *source_instance)
{
int rc = -1;
char log_msg[NACK_LOG_SIZE];
struct json_object *jobj_result;
if (!json_object_object_get_ex(jobj_response, RESULT, &jobj_result)) {
snprintf(log_msg, NACK_LOG_SIZE, "failed to parse result");
goto failed;
}
const char *result = json_object_get_string(jobj_result);
if (!strcmp(result, "fail")) {
struct json_object *jobj_err_msg;
const char *err_msg;
if (!json_object_object_get_ex(jobj_response, ERR_MSG, &jobj_err_msg))
err_msg="";
else
err_msg = json_object_get_string(jobj_err_msg);
ERR_LOG("Error: guest helper scaling cpu up failed: %s\n", err_msg);
goto out;
}
struct json_object *jobj_online_cpu;
if (!json_object_object_get_ex(jobj_response, ONLINE_CPU, &jobj_online_cpu)) {
snprintf(log_msg, NACK_LOG_SIZE, "failed to parse online_cpu");
goto failed;
}
int online_cpu = json_object_get_int(jobj_online_cpu);
struct json_object *jobj_online_cpus;
json_object_object_get_ex(jobj_response, ONLINE_CPUS, &jobj_online_cpus);
if (!json_object_is_type(jobj_online_cpus, json_type_array)) {
snprintf(log_msg, NACK_LOG_SIZE, "failed to parse online_cpus");
goto failed;
}
int i, len_response;
len_response = json_object_array_length(jobj_online_cpus);
int *response_online_cpus = malloc(len_response*sizeof(int));
for (i=0; i< len_response; i++){
response_online_cpus[i] = json_object_get_int(json_object_array_get_idx(jobj_online_cpus, i));
}
// compare request and response, assuming cpus are in the same order
if ( (len_response - len_request_online_cpus ) <=1 ) {
int req =0;
int rsp = 0;
int found_req = 0;
while (req < len_request_online_cpus){
if (response_online_cpus[rsp] == request_online_cpus[req]) {
req++; rsp++;
} else if (response_online_cpus[rsp] == request_cpu) {
rsp++;
found_req = 1;
// protect against infinite loop
if (rsp == len_response)
break;
} else {
ERR_LOG("Error: cpu %d online by guest but not online in nova\n", response_online_cpus[rsp]);
break;
}
}
if ((!found_req) && (req == len_request_online_cpus)) {
if ((len_response == len_request_online_cpus) ||
(response_online_cpus[len_response] != request_cpu)) {
ERR_LOG("Error: cpu %d online by nova but not online in guest\n", response_online_cpus[req]);
}
}
}
else {
ERR_LOG("Error: guest's online cpu range doesn't match nova\n");
char buf[1024];
print_array(buf, response_online_cpus, len_response);
ERR_LOG("guest online cpu range: %s\n", buf);
}
// Yay, everything looks good.
free(response_online_cpus);
free(request_online_cpus);
exit(online_cpu);
rc = online_cpu;
failed:
send_nack(log_msg, source_instance);
out:
free(request_online_cpus);
exit(rc);
}
void handle_cpu_scale_down(json_object *jobj_response, const char *source_instance)
{
int rc = -1;
struct json_object *jobj_result;
char log_msg[NACK_LOG_SIZE];
if (!json_object_object_get_ex(jobj_response, RESULT, &jobj_result)) {
snprintf(log_msg, NACK_LOG_SIZE, "failed to parse result");
goto failed;
}
const char *result = json_object_get_string(jobj_result);
if (!strcmp(result, "fail")) {
struct json_object *jobj_err_msg;
const char *err_msg;
if (!json_object_object_get_ex(jobj_response, ERR_MSG, &jobj_err_msg))
err_msg="";
else
err_msg = json_object_get_string(jobj_err_msg);
ERR_LOG("problem, guest helper scaling cpu down failed: %s\n", err_msg);
goto out;
}
struct json_object *jobj_offline_cpu;
if (!json_object_object_get_ex(jobj_response, OFFLINE_CPU, &jobj_offline_cpu)) {
snprintf(log_msg, NACK_LOG_SIZE, "failed to parse offline_cpu");
goto failed;
}
int offline_cpu = json_object_get_int(jobj_offline_cpu);
struct json_object *jobj_online_cpus;
json_object_object_get_ex(jobj_response, ONLINE_CPUS, &jobj_online_cpus);
if (!json_object_is_type(jobj_online_cpus, json_type_array)) {
snprintf(log_msg, NACK_LOG_SIZE, "failed to parse online_cpus");
goto failed;
}
int i, len_response;
len_response = json_object_array_length(jobj_online_cpus);
int *response_online_cpus = malloc(len_response*sizeof(int));
for (i=0; i< len_response; i++){
response_online_cpus[i] = json_object_get_int(json_object_array_get_idx(jobj_online_cpus, i));
}
if (response_online_cpus[len_response] > offline_cpu) {
ERR_LOG("Error: cpu %d is still online in guest\n", offline_cpu);
}
// Yay, everything looks good.
free(response_online_cpus);
free(request_online_cpus);
rc = offline_cpu;
exit(rc);
failed:
send_nack(log_msg, source_instance);
out:
free(request_online_cpus);
exit(rc);
}
// This should call exit(0) on success or exit(-1) on permanent failure().
// Returning will continue listening.
// Theoretically this could come from any instance, need to fix that.
void msg_handler(const char *source_addr, const char *source_instance, struct json_object *jobj_response)
{
// parse version
struct json_object *jobj_version;
char log_msg[NACK_LOG_SIZE];
if (!json_object_object_get_ex(jobj_response, VERSION, &jobj_version)) {
snprintf(log_msg, NACK_LOG_SIZE, "failed to parse version");
goto failed;
}
int version = json_object_get_int(jobj_version);
if (version != CUR_VERSION) {
snprintf(log_msg, NACK_LOG_SIZE, "invalid version %d, expecting %d", version, CUR_VERSION);
goto failed;
}
struct json_object *jobj_resource;
if (!json_object_object_get_ex(jobj_response, RESOURCE, &jobj_resource)) {
snprintf(log_msg, NACK_LOG_SIZE, "failed to parse resource");
goto failed;
}
const char *resource = json_object_get_string(jobj_resource);
struct json_object *jobj_direction;
if (!json_object_object_get_ex(jobj_response, DIRECTION, &jobj_direction)) {
snprintf(log_msg, NACK_LOG_SIZE, "failed to parse direction");
goto failed;
}
const char *direction = json_object_get_string(jobj_direction);
if (!strcmp(resource,"cpu")) {
if (!strcmp(direction,"up")) {
handle_cpu_scale_up(jobj_response, source_instance);
} else if (!strcmp(direction,"down")) {
handle_cpu_scale_down(jobj_response, source_instance);
}
}
// if handle_cpu_scale_up/down is called, program should exit,
// so this is only called when scale up/down are not properly handled.
sprintf(log_msg, "unknown message, resource %s, direction %s",
resource, direction);
failed:
send_nack(log_msg, source_instance);
}
// instance_name will be of the form instance-xxxxxxxx
// We want to make a name of the form scale-xxxxxxxx
void instance_to_addr(const char *instance_name, char *addr)
{
const char *match = "instance-";
const char *replace = "scale-";
char *tmp = strstr(instance_name, match);
if (!tmp) {
ERR_LOG("Instance name %s doesn't match expected pattern\n",
instance_name);
exit(-1);
}
strcpy(addr, replace);
strncpy(addr+strlen(replace), instance_name+strlen(match),
UNIX_ADDR_LEN-strlen(replace)-1);
addr[UNIX_ADDR_LEN-1]='\0';
}
void handle_message(const char *request, const char *instance_name)
{
int rc;
fd_set rfds, rfds_tmp;
int fd;
char addr[UNIX_ADDR_LEN];
INFO_LOG("handling scaling request: %s", request);
// Create a unique address from the instance name. When using a helper app
// this is needed in order to handle simultaneous scale events for different
// servers on the same hypervisor.
instance_to_addr(instance_name, addr);
fd = hg_init(msg_handler, addr, &info);
if (fd == -1) {
if (!info)
ERR_LOG("Unable to allocate memory for info: %m");
else
ERR_LOG("Unable to initialize guest/host messaging: %s\n",
hg_get_error(info));
exit(-1);
}
rc = hg_send_msg(info, SCALE_AGENT_ADDR, instance_name, request);
if (rc < 0) {
ERR_LOG("hg_send_msg failed: %s\n", hg_get_error(info));
exit(-1);
}
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
while(1) {
rfds_tmp = rfds;
rc = select(fd+1, &rfds_tmp, NULL, NULL, NULL);
if (rc > 0) {
if (hg_process_msg(info) < 0) {
ERR_LOG("problem processing messages: %s\n",
hg_get_error(info));
}
} else if (rc < 0) {
ERR_LOG("select(): %m");
}
}
}
void send_nack(char *log_msg, const char *instance_name)
{
ERR_LOG("sending Nack with error: %s\n", log_msg);
struct json_object *jobj_msg = json_object_new_object();
if (jobj_msg == NULL) {
ERR_LOG("failed to allocate json object for nack msg\n");
return;
}
json_object_object_add(jobj_msg, VERSION, json_object_new_int(CUR_VERSION));
json_object_object_add(jobj_msg, MSG_TYPE, json_object_new_string(MSG_TYPE_NACK));
json_object_object_add(jobj_msg, LOG_MSG, json_object_new_string(log_msg));
const char *msg = json_object_to_json_string_ext(jobj_msg, JSON_C_TO_STRING_PLAIN);
hg_send_msg(info, SCALE_AGENT_ADDR, instance_name, msg);
json_object_put(jobj_msg);
}
void handle_timeout(int sig)
{
_exit(-2);
}
void setup_timeout(int timeout_ms)
{
int rc;
struct itimerval itv;
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = timeout_ms * 1000;
// normalize the timer
while(itv.it_value.tv_usec >= 1000000) {
itv.it_value.tv_usec -= 1000000;
itv.it_value.tv_sec += 1;
}
rc = setitimer(ITIMER_REAL, &itv, NULL);
if (rc < 0) {
ERR_LOG("unable to set timeout");
exit(-1);
}
if (signal(SIGALRM, handle_timeout) == SIG_ERR)
ERR_LOG("unable to set timeout handler, continuing anyway: %m");
}
struct json_object *create_new_jobj_msg(int timeout_ms,
const char *resource,
const char *direction,
int cpu,
const char *online_cpus)
{
//validate values
if (timeout_ms < TIMEOUT_OVERHEAD_MS) {
printf("timeout %d too short\n", timeout_ms);
goto invalid_values;
}
if (strcmp(resource, "cpu")!=0) {
printf("invalid resource %s\n", resource);
goto invalid_values;
}
struct json_object *jobj_online_cpus;
if (!strcmp(direction, "up")) {
jobj_online_cpus = json_tokener_parse(online_cpus);
if (!json_object_is_type(jobj_online_cpus, json_type_array)) {
printf("invalid online_cpus %s\n", online_cpus);
goto invalid_values;
}
len_request_online_cpus = json_object_array_length(jobj_online_cpus);
request_online_cpus = malloc(len_request_online_cpus*sizeof(int));
int i;
for (i=0; i< len_request_online_cpus; i++) {
request_online_cpus[i] = json_object_get_int(json_object_array_get_idx(jobj_online_cpus, i));
}
} else if (strcmp(direction, "down")!=0) {
printf("invalid direction %s\n", direction);
goto invalid_values;
}
struct json_object *jobj_msg = json_object_new_object();
if (jobj_msg == NULL) {
printf("failed to allocate json object for msg\n");
return NULL;
}
json_object_object_add(jobj_msg, VERSION, json_object_new_int(CUR_VERSION));
json_object_object_add(jobj_msg, MSG_TYPE, json_object_new_string(MSG_TYPE_SCALE_REQUEST));
json_object_object_add(jobj_msg, TIMEOUT_MS, json_object_new_int(timeout_ms - MIN_SCRIPT_TIMEOUT_MS));
json_object_object_add(jobj_msg, RESOURCE, json_object_new_string(resource));
json_object_object_add(jobj_msg, DIRECTION, json_object_new_string(direction));
if (!strcmp(direction, "up")) {
json_object_object_add(jobj_msg, ONLINE_CPU, json_object_new_int(cpu));
json_object_object_add(jobj_msg, ONLINE_CPUS, jobj_online_cpus);
}
return jobj_msg;
invalid_values:
usage();
return NULL;
}
int main(int argc, char *argv[])
{
int i;
char *instance_name;
// msg values
int cpu;
const char *resource;
const char *direction;
const char *request_online_cpus_str = NULL;
for(i=1;i<argc;i++) {
if (0==strcmp(argv[i], "--timeout")) {
i++;
if (i<argc) {
timeout_ms = atoi(argv[i]);
} else {
printf("timeout option specified without timeout value\n");
usage();
}
} else if (0==strcmp(argv[i], "--instance_name")) {
i++;
if (i<argc) {
int len = strlen(argv[i]) + 1;
if (len > INSTANCE_NAME_SIZE) {
printf("instance name is too large\n");
usage();
} else
instance_name = argv[i];
}
else {
printf("instance_name option specified without name\n");
usage();
}
} else if (0==strcmp(argv[i], "--cpu_add")) {
i++;
if (i<argc) {
cpu = atoi(argv[i]);
i++;
if (i<argc) {
request_online_cpus_str = argv[i];
} else {
printf("cpu_add option specified but missing online cpu range\n");
usage();
}
} else {
printf("cpu_add option specified but missing cpu\n");
usage();
}
resource = "cpu";
direction = "up";
} else if (0==strcmp(argv[i], "--cpu_del")) {
resource = "cpu";
direction = "down";
} else if (0==strcmp(argv[i], "--help")) {
usage();
} else {
printf("Unknown argument %s\n", argv[i]);
usage();
}
}
struct json_object *jobj_msg = create_new_jobj_msg(timeout_ms, resource, direction,
cpu, request_online_cpus_str);
if (jobj_msg == NULL) {
return -1;
}
const char *msg = json_object_to_json_string_ext(jobj_msg, JSON_C_TO_STRING_PLAIN);
// save request data to compare with response
request_cpu = cpu;
setup_timeout(timeout_ms);
handle_message(msg, instance_name);
json_object_put(jobj_msg);
return 0;
}

View File

@ -0,0 +1,81 @@
/**
* Copyright (c) <2015-2016>, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <syslog.h>
#define CUR_VERSION 2
#define LOG_MSG_SIZE 100
#define SCALE_AGENT_ADDR "cgcs.scale"
#define ERRORSIZE 400
// keys for guest scaling messages
#define VERSION "version"
#define TIMEOUT_MS "timeout_ms"
#define RESOURCE "resource"
#define DIRECTION "direction"
#define ONLINE_CPU "online_cpu"
#define OFFLINE_CPU "offline_cpu"
#define ONLINE_CPUS "online_cpus"
#define RESULT "result"
#define ERR_MSG "err_msg"
#define MSG_TYPE "msg_type"
#define LOG_MSG "log_msg" // for Nack
// message types for scaling messages
#define MSG_TYPE_SCALE_REQUEST "scale_request"
#define MSG_TYPE_NACK "nack"
char errorbuf[ERRORSIZE];
#define LOG(priority, format, ...) \
syslog(priority, "%s(%d): " format, __FILE__, __LINE__, ##__VA_ARGS__)
#define ERR_LOG(format, ...) \
do { \
LOG(LOG_DAEMON|LOG_ERR, format, ##__VA_ARGS__); \
fprintf(stderr, format, ##__VA_ARGS__); \
snprintf(errorbuf, sizeof(errorbuf)-1, format, ##__VA_ARGS__); \
} while (0)
#define INFO_LOG(format, ...) \
do { \
LOG(LOG_DAEMON|LOG_INFO, format, ##__VA_ARGS__); \
} while (0)
struct online_cpus {
int numcpus;
char status[];
};
struct online_cpus *range_to_array(const char *range);
struct json_object *new_json_obj_from_array (struct online_cpus *cpuarray);
void print_array(char *buf, int *array, int len);

View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -0,0 +1,150 @@
/**
* Copyright (c) <2013-2016>, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <json-c/json.h>
#include "misc.h"
/* Print a range of numbers in a consistent way. */
char print_range(int start, int end, char *str)
{
int len;
if (start == end)
len = sprintf(str, "%d,", start);
else
len = sprintf(str, "%d-%d,", start, end);
return len;
}
void print_array(char *buf, int *array, int len) {
int i;
for(i = 0; i < len; i++) {
sprintf(buf+strlen(buf),"%d,", array[i]);
}
// remove the last comma
buf[strlen(buf)-1]='\0';
}
#define BUFLEN 1024
/* Takes as input a string representation of online cpus of the form
* "0,1,3-5", and allocates and returns a struct representing whether
* each given cpu is online.
*/
struct online_cpus *range_to_array(const char *range)
{
struct online_cpus *cpuarray = (struct online_cpus *) malloc(BUFLEN);
int start, end;
int inrange = 0;
char *token, *tmp;
int done = 0;
tmp = strdup(range);
strcpy(tmp, range);
token = tmp;
if (*tmp == '\0') {
/* empty string, no online cpus */
cpuarray->numcpus = 0;
return cpuarray;
}
while (1) {
tmp++;
if (*tmp == '\0')
done = 1;
if (done || (*tmp == ',')) {
/* expect single value or ending a range */
if (!token) {
ERR_LOG("format error, missing token, unable to parse range\n");
goto error;
}
*tmp = '\0';
end = atoi(token);
token = 0;
if (inrange) {
int i;
for (i=start; i<= end; i++)
cpuarray->status[i] = 1;
inrange = 0;
} else {
cpuarray->status[end] = 1;
}
} else if (*tmp == '-') {
if (inrange) {
ERR_LOG("format error, unable to parse range\n");
goto error;
}
if (!token) {
ERR_LOG("format error, missing token, unable to parse range\n");
goto error;
}
*tmp = '\0';
start = atoi(token);
token = 0;
inrange = 1;
} else {
/* expect a numerical value */
if ((*tmp < '0') || (*tmp > '9')) {
ERR_LOG("format error, expected a numerical value, unable to parse range\n");
goto error;
}
if (!token)
token = tmp;
}
if (done)
break;
}
cpuarray->numcpus = end+1;
return cpuarray;
error:
free(cpuarray);
return 0;
}
struct json_object *new_json_obj_from_array (struct online_cpus *cpuarray)
{
int i;
struct json_object *jobj_array = json_object_new_array();
if (jobj_array == NULL) {
return NULL;
}
for (i=0;i<cpuarray->numcpus;i++) {
if (cpuarray->status[i]) {
json_object_array_add(jobj_array, json_object_new_int(i));
}
}
return jobj_array;
}

View File

@ -0,0 +1,67 @@
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <misc.h>
void printstruct(struct online_cpus *cpuarray)
{
int i;
printf("num cpus: %d\n", cpuarray->numcpus);
for (i=0;i<cpuarray->numcpus;i++)
printf("%d: %d\n", i, cpuarray->status[i]);
}
struct online_cpus cpus = {15, {1,0,0,0,0,0,1,1,1,0,0,0,1,1,1}};
int main()
{
char *str, *str2;
struct online_cpus *newcpus;
printf("initial: \n");
printstruct(&cpus);
printf("string:\n");
str = "0,6-8,12-14";
newcpus = range_to_array(str);
printf("fromstring: \n");
printstruct(newcpus);
newcpus = range_to_array("");
printf("empty: \n");
printstruct(newcpus);
newcpus = range_to_array("0--2");
newcpus = range_to_array("0-1-2");
newcpus = range_to_array("0,,2");
newcpus = range_to_array("0,-2");
newcpus = range_to_array("1,2-a");
return 0;
}

View File

@ -0,0 +1,107 @@
#!/bin/bash
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This is a basic sample script showing what the script needs to be able to do.
# The script can be edited as needed or replaced by a script or binary that
# works in the same way, or can be deleted entirely if the default behaviour
# of offlining the highest-numbered CPU is satisfactory and you don't care
# about logging scaling events.
#
# We expect to be called in one of the following ways:
#
# "--cpu_add <cpu> <new cpu range>"
#
# This indicates that "cpu" has been set online, and we can now make use of it.
# Do whatever is necessary to start using it, then return 0.
#
#
# "--cpu_del"
# In this case we pick an online cpu to offline, and do whatever we need to in
# order to stop using it, and return the cpu number. Note that CPU 0 must
# always remain online.
info_log()
{
logger -p daemon.info -t $0 "$*"
echo $*
}
err_log()
{
logger -p daemon.err -t $0 "$*"
echo $*
}
usage()
{
err_log "usage: $0 {--cpu_del | --cpu_add <cpu> <new cpu range>}"
exit -1
}
cpu_scale_up ()
{
CPU_NUM=$1
CPU_ONLINE_RANGE=$2
info_log "cpu add notification, cpu: ${CPU_NUM}"
info_log "cpu_online_range: ${CPU_ONLINE_RANGE}"
}
cpu_scale_down ()
{
# Make sure host & guest views of offline cpus are consistent
/usr/sbin/offline_cpus
info_log "cpu del request"
#pick the highest online cpu
CPUS_ONLINE=`cat /sys/devices/system/cpu/online`
CPU_NUM=${CPUS_ONLINE##*[,-]}
info_log "selected cpu ${CPU_NUM} to offline"
return $CPU_NUM
}
if [ $# -lt 1 ]
then
usage
elif [ $1 = "--cpu_add" ]
then
if [ $# = 3 ]
then
cpu_scale_up $2 $3
else
err_log "--cpu_add option called with $# args, expected 3"
usage
fi
elif [ $1 = "--cpu_del" ]
then
cpu_scale_down
else
usage
fi

View File

@ -0,0 +1,13 @@
[Unit]
Description=Guest Scale Agent
After=cloud-init.service
Wants=guest-agent.service
[Service]
ExecStart=/usr/sbin/guest_scale_agent
Type=simple
Restart=always
RestartSec=0
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,64 @@
#!/bin/sh
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
DAEMON=/usr/sbin/offline_cpus
NAME=offline_cpus
DESC="offline cpus marked offline by hypervisor"
ARGS=
test -f $DAEMON || exit 0
case "$1" in
start)
echo -n "running $DESC: $NAME... "
$DAEMON $ARGS
echo "done."
;;
stop)
echo -n "stopping $DESC: $NAME... "
echo "done."
;;
status)
echo -n "$NAME is not running"
;;
restart)
echo "restarting $DESC: $NAME... "
$0 stop
$0 start
echo "done."
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,12 @@
[Unit]
Description=Titanium Cloud agent and helper app to scale VMs up/down
After=cloud-init.service
[Service]
Type=simple
RemainAfterExit=yes
ExecStart=/etc/init.d/offline_cpus start
ExecStop=/etc/init.d/offline_cpus stop
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,54 @@
#!/bin/bash
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Query the metadata server for the set of cpus that are supposed to be offline
# It will be in the form "set([])" for the empty set, and "set([1, 2, 3])" for the
# non-empty set.
CPUSET_OFFLINE=`wget -t 3 -T 5 -qO - http://169.254.169.254/latest/meta-data/offline_cpuset`
RC=$?
if [ $RC -ne 0 ]
then
logger -p daemon.err "${0}: unable to obtain "offline_cpuset" value. rc: ${RC}"
exit -1
fi
OFFLINE_CPUS=`echo ${CPUSET_OFFLINE}|grep -oE [0-9]+`
for CPU in $OFFLINE_CPUS
do
# Offline this cpu to match the underlying virtual machine.
echo 0 > /sys/devices/system/cpu/cpu${CPU}/online
RC=$?
if [ $RC -ne 0 ]
then
logger -p daemon.err "${0}: unable to offline cpu ${CPU}. rc: ${RC}"
exit -1
fi
done

202
guest-client/LICENSE Normal file
View 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.

12
guest-client/PKG-INFO Normal file
View File

@ -0,0 +1,12 @@
Metadata-Version: 1.1
Name: guest-client
Version: 3.0.1
Summary: Titanium Cloud Platform Guest-Client Heartbeat Package
Home-page:
Author: Windriver
Author-email: info@windriver.com
License: Apache-2.0
Description: Guest-Client with heartbeat functionality.
Platform: UNKNOWN

View File

@ -0,0 +1,3 @@
SRC_DIR=$CGCS_BASE/mwa-thales/guest-client
COPY_LIST="$SRC_DIR/*"
TIS_PATCH_VER=5

View File

@ -0,0 +1,114 @@
Summary: Guest-Client
Name: guest-client
Version: 3.0.1
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: guest_heartbeat_msg_defs.h
%define cgcs_sdk_deploy_dir /opt/deploy/cgcs_sdk
%bcond_without systemd
%if %{with systemd}
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
BuildRequires: systemd
%endif
%package -n guest-client-devel
Summary: Guest-Client - Development files
Group: devel
Provides: guest-client-dev(x86_64) = 3.0.1-r1.0
%package -n %{name}-cgts-sdk
Summary: Guest-Client - SDK files
Group: devel
BuildRequires: json-c-devel
%description
Guest-Client with heartbeat functionality.
%description -n guest-client-devel
Guest-Client with heartbeat functionality. This package contains symbolic
links, header files, and related items necessary for software development.
%description -n %{name}-cgts-sdk
Guest-Client SDK files
%prep
%setup
#%build -C guest-client-3.0.1/guest_client/src/heartbeat
#tar czf %{name}-%{version}.tgz %{name}-%{version}
#find . -name "*.tgz"
#echo `pwd`
# Build for guest-client package
cd guest-client-3.0.1
make clean
make build sysconfdir=%{_sysconfdir}
make sample
make tar ARCHIVE_NAME=wrs-guest-heartbeat-%{version}
find build
cd ..
# Install for guest-client package
%install
install -m 750 -d %{buildroot}/usr
install -m 750 -d %{buildroot}%{_includedir}
install -m 750 -d %{buildroot}%{_includedir}/guest-client
install -m 640 -p -D %{name}-%{version}/guest_client/src/heartbeat/guest_heartbeat_msg_defs.h %{buildroot}%{_includedir}/guest-client/guest_heartbeat_msg_defs.h
install -d %{buildroot}%{cgcs_sdk_deploy_dir}
install -m 640 %{name}-%{version}/build/wrs-guest-heartbeat-%{version}.tgz %{buildroot}%{cgcs_sdk_deploy_dir}
%if %{with systemd}
install -m 644 -p -D %{name}-%{version}/guest_client/scripts/guest-client.service %{buildroot}%{_unitdir}/guest-client.service
install -m 744 -p -D %{name}-%{version}/guest_client/scripts/guest-client.systemd %{buildroot}%{_sysconfdir}/guest-client/guest-client.systemd
%endif
install -m 750 -d %{buildroot}%{_sysconfdir}/guest-client/heartbeat
install -m 755 -p -D %{name}-%{version}/guest_client/scripts/guest_heartbeat.conf %{buildroot}%{_sysconfdir}/guest-client/heartbeat/guest_heartbeat.conf
install -m 755 -p -D %{name}-%{version}/guest_client/scripts/sample_event_handling_script %{buildroot}%{_sysconfdir}/guest-client/heartbeat/sample_event_handling_script
install -m 755 -p -D %{name}-%{version}/guest_client/scripts/sample_health_check_script %{buildroot}%{_sysconfdir}/guest-client/heartbeat/sample_health_check_script
install -m 640 -p -D %{name}-%{version}/build/guest-client %{buildroot}/usr/local/bin/guest-client
install -m 640 -p -D %{name}-%{version}/build/libguest_common_api.so.%{version} %{buildroot}/usr/local/lib/libguest_common_api.so.%{version}
install -m 640 -p -D %{name}-%{version}/build/libguest_heartbeat_api.so.%{version} %{buildroot}/usr/local/lib/libguest_heartbeat_api.so.%{version}
%files
%defattr(755,root,root,-)
%{_sysconfdir}/guest-client/heartbeat/guest_heartbeat.conf
%{_sysconfdir}/guest-client/heartbeat/sample_event_handling_script
%{_sysconfdir}/guest-client/heartbeat/sample_health_check_script
%defattr(644,root,root,-)
/usr/local/lib/libguest_common_api.so.%{version}
/usr/local/lib/libguest_heartbeat_api.so.%{version}
%attr(744,-,-) /usr/local/bin/guest-client
%if %{with systemd}
%{_unitdir}/guest-client.service
%attr(744,-,-) %{_sysconfdir}/guest-client/guest-client.systemd
%endif
%preun
%if %{with systemd}
/usr/bin/systemctl stop guest-client >/dev/null 2>&1
%systemd_preun guest-client.service
systemctl reload
%endif
%post
%if %{with systemd}
%systemd_post guest-client.service
systemctl reload
/usr/bin/systemctl enable guest-client >/dev/null 2>&1
%endif
%files -n guest-client-devel
%defattr(644,root,root,-)
/usr/include/guest-client/guest_heartbeat_msg_defs.h
%files -n %{name}-cgts-sdk
%{cgcs_sdk_deploy_dir}/wrs-guest-heartbeat-%{version}.tgz

View 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.

View File

@ -0,0 +1,119 @@
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SHELL = /bin/sh
## Configuration Directory Variables
prefix := /usr/local
exec_prefix := $(prefix)
sysconfdir := $(prefix)/etc
includedir := $(prefix)/include
libdir := $(exec_prefix)/lib
bindir := $(exec_prefix)/bin
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
PARENT_DIR := $(patsubst %/,%,$(dir $(CURRENT_DIR)))
BUILD_DIR := $(CURRENT_DIR)/build
PACKAGE_DIR := $(BUILD_DIR)/package
PACKAGE_ROOT_DIR := $(PACKAGE_DIR)/rootdir
ARCHIVE_NAME := wrs-guest-client-3.0.1
ARCHIVE_PKG_NAME := wrs-guest-client-3.0.1_pkg
INIT_TYPE := sysv
.PHONY: all build sample clean distclean tar package install uninstall
all: build
build:
mkdir -p --mode 755 $(BUILD_DIR)
@(cd guest_client_api; make --no-print-directory build \
sysconfdir=$(sysconfdir) BUILD_DIR=$(BUILD_DIR))
@(cd guest_client; make --no-print-directory build \
sysconfdir=$(sysconfdir) BUILD_DIR=$(BUILD_DIR))
tar:
@(mkdir -p --mode 755 $(BUILD_DIR))
@(ln -sf $(CURRENT_DIR) $(BUILD_DIR)/$(ARCHIVE_NAME))
@(cd $(BUILD_DIR); tar -pczf $(ARCHIVE_NAME).tgz \
$(ARCHIVE_NAME)/Makefile \
$(ARCHIVE_NAME)/LICENSE \
$(ARCHIVE_NAME)/README \
$(ARCHIVE_NAME)/README.build \
$(ARCHIVE_NAME)/README.usage \
$(ARCHIVE_NAME)/TiS-Guest-Heartbeat-Service.pdf \
$(ARCHIVE_NAME)/packaging \
$(ARCHIVE_NAME)/include \
$(ARCHIVE_NAME)/guest_client \
$(ARCHIVE_NAME)/guest_client_api \
--exclude $(ARCHIVE_NAME)/guest_client/build \
--exclude $(ARCHIVE_NAME)/guest_client/src/test \
--exclude $(ARCHIVE_NAME)/guest_client_api/build \
--directory $(BUILD_DIR))
sample:
mkdir -p --mode 755 $(BUILD_DIR)
@(cd guest_client_api; make --no-print-directory sample \
sysconfdir=$(sysconfdir) BUILD_DIR=$(BUILD_DIR))
@(cd guest_client; make --no-print-directory sample \
sysconfdir=$(sysconfdir) BUILD_DIR=$(BUILD_DIR))
clean:
@-(cd guest_client_api; make --no-print-directory clean BUILD_DIR=$(BUILD_DIR))
@-(cd guest_client; make --no-print-directory clean BUILD_DIR=$(BUILD_DIR))
distclean: clean
package:
@(mkdir -p --mode 755 $(PACKAGE_DIR))
@(mkdir -p --mode 755 $(PACKAGE_ROOT_DIR))
@(ln -sf $(PACKAGE_DIR) $(BUILD_DIR)/$(ARCHIVE_PKG_NAME))
@(echo "Packaging guest-client.pkg in $(PACKAGE_DIR)")
@(cp $(CURRENT_DIR)/packaging/guest-client.pkg $(PACKAGE_DIR)/guest-client.pkg)
@(chmod 755 $(PACKAGE_DIR)/guest-client.pkg)
@-(cd guest_client_api; make --no-print-directory package BUILD_DIR=$(BUILD_DIR) \
PACKAGE_DIR=$(PACKAGE_DIR) prefix=$(prefix) exec_prefix=$(exec_prefix) \
sysconfdir=$(sysconfdir) includedir=$(includedir) libdir=$(libdir) \
bindir=$(bindir))
@-(cd guest_client; make --no-print-directory package BUILD_DIR=$(BUILD_DIR) \
PACKAGE_DIR=$(PACKAGE_DIR) prefix=$(prefix) exec_prefix=$(exec_prefix) \
sysconfdir=$(sysconfdir) includedir=$(includedir) libdir=$(libdir) \
bindir=$(bindir))
@(cd $(BUILD_DIR); tar -pczf $(ARCHIVE_PKG_NAME).tgz \
$(ARCHIVE_PKG_NAME)/* --directory $(PACKAGE_DIR))
install: package
@(echo "Installing ...")
@(cd $(PACKAGE_DIR); ./guest-client.pkg install $(INIT_TYPE) $(DESTDIR))
uninstall: package
@(echo "Uninstalling ...")
@(cd $(PACKAGE_DIR); ./guest-client.pkg uninstall $(INIT_TYPE) $(DESTDIR))

View File

@ -0,0 +1,72 @@
Copyright(c) 2013-2017, Wind River Systems, Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Wind River Systems nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------
TITANIUM CLOUD - GUEST HEARTBEAT SDK
===========================================
DESCRIPTION
===========
Titanium Cloud Guest-Client provides a heartbeat service to monitor the
health of guest application(s) within a VM running under WindRiver's
Titanium Cloud. Loss of heartbeat will result in a corrective action
being taken against the VM. The heartbeat interval and corrective action
is specified by the VM.
Titanium Cloud Guest-Client also provides guest application(s) within
a VM running under WindRiver's Titanium Cloud, the ability to receive
notification of and vote to accept or reject actions about to be performed
against the VM. On notifications, the guest application within the VM can
take this opportunity to cleanly shut down or transfer its service to a
peer VM.
+-------- Virtual Machine ------------------------+
| |
| VM-Health-Check-Script |
| / |
| / Guest-Application-1 |
Titanium Cloud <----> TiS-Guest-Client <-----> ... |
| \ Guest-Application-8 |
| \ |
| VM-Event-Script |
| |
+-------------------------------------------------+
See also:
README.build - building and installing.
README.usage - configuring and using the heartbeat, notification
and voting functionality.
DELIVERY
========
Titanium Cloud Guest-Client is delivered as source in a compressed
tarball, wrs-guest-client-v3.0.0.tgz, such that it can be compiled for
the applicable VM Linux distribution.

View File

@ -0,0 +1,291 @@
Copyright(c) 2013-2017, Wind River Systems, Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Wind River Systems nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------
This file contains instructions for building and installing the Titanium Cloud
Guest-Client.
REQUIREMENTS
============
The Guest-Client uses the SIGIO functionality of the virtio-serial device
to track host connection up, down and port unplug events. This functionality
requires a kernel version equal to or greater than 2.6.37.
Compilation:
Linux OS ## Same architecture as the VM.
gnu make
gcc compiler
development libraries and headers for:
libc ## C library
rt ## Real-Time library
json-c ## JSON-C library
VM Runtime:
Linux OS
runtime libraries:
libc ## C library
rt ## Real-Time library
json-c ## JSON-C library
COMPILE
=======
Extract the tarball contents ...
tar -xvf wrs-guest-heartbeat-v3.0.0.tgz
To compile, simply run ...
cd wrs-guest-heartbeat-3.0.0
make
This will create a build output directory called "build" in the
wrs-guest-heartbeat-3.0.0 directory. The build output directory
contains the following relevant files:
libguest_common_api.so.3.0.0
libguest_heartbeat_api.so.3.0.0
guest-client
The libguest_common_api library contains all the common code for
the Guest-Client API libraries.
The libguest_heartbeat_api library contains the heartbeat, voting,
and notification functionality to interact with the Guest-Client.
A guest application wanting to use this functionality needs to link
in the libguest_common_api and libguest_heartbeat_api libraries.
The guest-client executable is the Guest-Client daemon that heartbeats
guest applications, and orchestrates votes on and notifications of
pending actions against the VM. The Guest-Client reports the health,
notification and voting results of guest application(s) to the
Titanium Cloud.
The following variables are available to change the build output
directory and where the system configuration files will be located:
BUILD_DIR - used to change the build output directory, defaults
to the wrs-guest-heartbeat-3.0.0/build directory.
prefix - used to construct other variables below, defaults to
the /usr/local directory.
sysconfdir - directory for configuration files, set to
$(prefix)/etc
Note: all directory variables must specify an absolute path.
Usage: make <variable-name>=<variable-value>
To compile the sample-guest-app, simply run ...
cd wrs-guest-heartbeat-3.0.0
make sample
The sample-guest-app executable is for demonstration purposes only.
It demonstrates how a guest application can use the guest heartbeat
library, libguest_heartbeat_api, to interact with the Guest-Client.
To compile with a different compiler, simply run ...
cd wrs-guest-heartbeat-3.0.0
make CC=/x86_64/buildroot/host/usr/bin/x86_64-buildroot-linux-uclibc-cc
PACKAGE
=======
To build a tar package for installation, simply run ...
cd wrs-guest-heartbeat-3.0.0
make package
This will create a tar file called wrs-guest-heartbeat-3.0.0_pkg.tgz
in the wrs-guest-heartbeat-3.0.0 build directory.
If you changed the build output directory during compile, the BUILD_DIR
variable will have to be specified on the make package. Also if you
specified a different system configuration directory, the sysconfdir
variable, during compile, it will also have to be specified on the
make package.
The following package configuration variables are available to customize
the package for installation:
prefix - used to construct other variables below, defaults to
the /usr/local directory.
exec_prefix - used to construct other executable variables, set to
the 'prefix' variable.
sysconfdir - directory for configuration files, set to
$(prefix)/etc
includedir - directory for installing header files, set to
$(prefix)/include
libdir - directory for installing libraries, set to
$(exec_prefix)/lib
bindir - directory for installing executable programs, set to
$(exec_prefix)/bin
Note: all directory variables must specify an absolute path.
Usage: make package <variable-name>=<variable-value> ...
INSTALL
=======
To install from source directories, simply run ...
cd wrs-guest-heartbeat-3.0.0
make install
This will install the default configuration file, include files,
compiled libraries and executable into the following directories:
guest_heartbeat.conf --> /usr/local/etc/guest-client/heartbeat
guest_api_types.h --> /usr/local/include
guest_heartbeat_api.h --> /usr/local/include
libguest_common_api.so.3.0.0 --> /usr/local/lib
libguest_heartbeat_api.so.3.0.0 --> /usr/local/lib
guest-client --> /usr/local/bin
If you changed the build output directory during compile, the BUILD_DIR
variable will have to be specified on the make install. Also if you
specified a different system configuration directory, the sysconfdir
variable, during compile, it will also have to be specified on the
make install.
The following install configuration variables are available to customize
installation:
INIT_TYPE - the type of initialization the OS is using, one of
( systemd or sysv ). Default to sysv.
DESTDIR - prepended to each install target file, used to provide
an alternate environment to install in (i.e. support
for staged installs).
prefix - used to construct other variables below, defaults to
the /usr/local directory.
exec_prefix - used to construct other executable variables, set to
the 'prefix' variable.
sysconfdir - directory for configuration files, set to
$(prefix)/etc
includedir - directory for installing header files, set to
$(prefix)/include
libdir - directory for installing libraries, set to
$(exec_prefix)/lib
bindir - directory for installing executable programs, set to
$(exec_prefix)/bin
Note: all directory variables must specify an absolute path.
Usage: make <install | uninstall> <variable-name>=<variable-value> ...
To install from a tar package file, simply run ...
tar -xvf wrs-guest-heartbeat-v3.0.0_pkg.tgz
cd wrs-guest-heartbeat-v3.0.0_pkg
guest-client.pkg install
This will install the default configuration file, include files,
compiled libraries and executable into the following directories:
guest_heartbeat.conf --> /usr/local/etc/guest-client/heartbeat
guest_api_types.h --> /usr/local/include
guest_heartbeat_api.h --> /usr/local/include
libguest_common_api.so.3.0.0 --> /usr/local/lib
libguest_heartbeat_api.so.3.0.0 --> /usr/local/lib
guest-client --> /usr/local/bin
To uninstall: guest-client.pkg uninstall
The following install configuration variables can be provided to
customize installation:
INIT_TYPE - the type of initialization the OS is using, one of
( systemd, sysv ). Optional parameter, defaults to
sysv.
DESTDIR - prepended to each install target file, used to provide
an alternate environment to install in (i.e. support
for staged installs). Optional parameter.
Note: all directory variables must specify an absolute path.
guest-client.pkg <install | uninstall> <systemd | sysv> [DESTDIR]
POST-INSTALL
============
Running in the VM:
Test if your platform is using systemd. First look for the systemd
process and then verify that the systemctl tool is available
ps -ef | grep systemd
systemctl --version
In this case use the systemd instructions, otherwise the sysv
instructions.
systemd:
As the root user,
systemctl daemon-reload
systemctl start guest-client.service
systemctl enable guest-client.service
sysv:
As the root user,
chkconfig --add guest-client
/etc/init.d/guest-client start
Building into the VM Image:
systemd:
No post install steps required.
sysv:
ln -s /etc/init.d/guest-client /etc/rc#.d/K##guest-client
ln -s /etc/init.d/guest-client /etc/rc#.d/S##guest-client
... and build the VM image.

View File

@ -0,0 +1,385 @@
Copyright(c) 2013-2017, Wind River Systems, Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Wind River Systems nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------
This file contains instructions for using the Titanium Cloud Guest-Client.
Titanium Cloud Setup
=====================
The following steps are required to setup the Titanium Cloud to heartbeat
a VM.
1. Create and modify a Flavor for your VM.
A flavor extraspec, 'Guest Heartbeat', is used to indicate
that VMs of this flavor support Titanium Cloud Guest Heartbeat.
The default value is 'False'.
If support is indicated, then as soon as the VM's Titanium Cloud
Guest-Client daemon registers with the Titanium Cloud Compute
Services on the compute node host, heartbeating will be enabled.
a) Create a new flavor:
via dashboard ...
- Select 'Admin->Flavors' to bring up the list of flavors
- Select '+ Create Flavor' in the upper right.
- Fill in the fields as desired
- Select 'Create Flavor'
via command line ...
- nova flavor-create ...
b) Modify the newly created flavor or an existing flavor:
via dashboard ...
- Select 'Admin->Flavors' to bring up the list of flavors
- Choose a flavor to modify.
- Select the <flavor-name> to go to the Flavor Detail page
- Select the Extra Specs TAB
- Select '+ Create'
- Select 'Guest Heartbeat' from pull-down Extra Spec menu
- Check the 'Guest Heartbeat' checkbox
- Select 'Create'
via command line ...
- nova flavor-key <flavor-name> set sw:wrs:guest:heartbeat=True
Note: already running instances that were launched with this
flavor are NOT affected.
2) Launch a new instance of your VM.
3) Verify your VM is running with Guest Heartbeat enabled.
Log into the VM.
Guest-Client logs are written to syslog's 'daemon' facility, which
are typically logged by the syslog service to /var/log/daemon.log.
Please refer to syslog for details on log settings in order to
determine location of logged Guest-Client messages.
Guest-Client logs are easy to identify. The logs always contain the
string 'Guest-Client'. A recursive grep of /var/log is one way to
determine where your syslog is sending the Guest-Client logs.
LOG=`grep -r -l 'Guest-Client' /var/log`
echo $LOG
/var/log/daemon.log
A successful connection can be verified by looking for the
following log.
grep "Guest-Client" $USER_LOG | grep "heartbeat state change"
Guest-Client heartbeat state change from enabling to enabled
VM Setup
========
Configuring Guest-Client Initialization/Start Scripts
-----------------------------------------------------
The Titanium Cloud communicates with the Guest-Client through a character
device. The packaged initialization/startup scripts need to be updated to
specify the character device exposed by QEMU to the VM.
+-- Virtual Machine ---+
| |
| |
Titanium Cloud <-------------------> QEMU <------------> Guest-Client |
unix-stream-socket char-device |
| |
+----------------------+
The variable that needs updating in the initialization/start scripts is
called GUEST_CLIENT_DEVICE.
Also the location of the Guest-Client binary needs to be updated in the
initialization/start scripts. The variable that needs updating is called
GUEST_CLIENT.
Configuring Guest Heartbeat & Application Health Check
------------------------------------------------------
The Guest-Client within your VM will register with the Titanium Cloud
Compute Services on the compute node host. Part of that registration
process is the specification of a heartbeat interval and a corrective
action for a failed/unhealthy VM. The values of heartbeat interval and
corrective action come from the guest_heartbeat.conf file and is located
in /etc/guest-client/heartbeat directory by default.
Guest heartbeat works on a challenge response model. The Titanium
Server Compute Services on the compute node host will challenge the
Guest-Client daemon with a message each interval. The Guest-Client
must respond prior to the next interval with a message indicating good
health. If the Titanium Cloud Compute Services does not receive a valid
response, or if the response specifies that the VM is in ill health, then
corrective action is taken.
The mechanism can be extended by allowing additional VM resident application
specific scripts and processes, to register for heartbeating. Each script
or process can specify its own heartbeat interval, and its own corrective
action to be taken against the VM as a whole. On ill health the Guest-Client
reports ill health to the Titanium Cloud Compute Services on the compute node
host on the next challenge, and provoke the corrective action.
This mechanism allows for detection of a failed or hung QEMU/KVM instance,
or a failure of the OS within the VM to schedule the Guest-Client process
or to route basic IO, or an application level error/failure.
Configuring the Guest-Client Heartbeat & Application Health Check ...
The heartbeat interval defaults to every second and can be overridden
by the VM in the guest_heartbeat.conf.
/etc/guest-client/heartbeat/guest_heartbeat.conf:
## This specifies the interval between heartbeats in milliseconds between the
## guest-client heartbeat and the Titanium Cloud Compute Services on the
## compute node host.
HB_INTERVAL=1000
The corrective action defaults to 'reboot' and can be overridden by the
VM in the guest_heartbeat.conf.
/etc/guest-client/heartbeat/guest_heartbeat.conf:
## This specifies the corrective action against the VM in the case of a
## heartbeat failure between the guest-client and Titanium Cloud Compute
## Services on the compute node host and also when the health script
## configured below fails.
##
## Your options are:
## "log" Only a log is issued.
## "reboot" Issue a reboot against this VM.
## "stop" Issue a stop against this VM.
##
CORRECTIVE_ACTION="reboot"
A health check script can be registered to run periodically to verify
the health of the VM. This is specified in the guest_heartbeat.conf.
/etc/guest-client/heartbeat/guest_heartbeat.conf:
## The Path to the health check script. This is optional.
## The script will be called periodically to check for the health of the VM.
## The health check interval is specified in seconds.
HEALTH_CHECK_INTERVAL=30
HEALTH_CHECK_SCRIPT="/etc/guest-client/heartbeat/sample_health_check_script"
Configuring Guest Notifications and Voting
------------------------------------------
The Guest-Client running in the VM can be used as a conduit for
notifications of VM lifecycle events being taken by the Titanium Cloud that
will impact this VM. Reboots, pause/resume and migrations are examples of
the types of events your VM can be notified of. Depending on the event, a
vote on the event maybe required before a notification is sent. Notifications
may precede the event, follow it or both. The full table of events and
notifications is found below.
Titanium Action Event Name Vote* Pre-notification Post-notification Timeout
--------------- ----------------- ---- ---------------- ----------------- -------
stop stop yes yes no shutdown
reboot reboot yes yes no shutdown
pause pause yes yes no suspend
unpause unpause no no yes resume
suspend suspend yes yes no suspend
resume resume no no yes resume
resize resize_begin yes yes no suspend
resize_end no no yes resume
live-migrate live_migrate_begin yes yes no suspend
live_migrate_end no no yes resume
cold-migrate cold_migrate_begin yes yes no suspend
cold_migrate_end no no yes resume**
* voting has its own timeout called 'vote' that is event independent.
** after VM reboot and reconnection which is subject to the 'restart' timeout.
Notifications are an opportunity for the VM to take preparatory actions
in anticipation of the forthcoming event, or recovery actions after
the event has completed. A few examples
- A reboot or stop notification might allow the application to stop
accepting transactions and cleanly wrap up existing transactions.
- A 'resume' notification after a suspend might trigger a time
adjustment.
- Pre and post migrate notifications might trigger the application
to de-register and then re-register with a network load balancer.
If you register a notification handler, it will receive all events. If
an event is not of interest, it should return immediately with a
successful return code.
A process may only register a single notification handler. However
multiple processes may independently register handlers. Also a script
based handler may be registered via the guest_heartbeat.conf. When
multiple processes and scripts register notification handlers, they
will be run in parallel.
Notifications are subject to configurable timeouts. Timeouts are
specified by each registered process and in the guest_heartbeat.conf.
The timeouts in the guest_heartbeat.conf govern the maximum time all
registered notification handlers have to complete.
While pre-notification handlers are running, the event will be delayed.
If the timeout is reached, the event will be allowed to proceed.
While post-notification handlers are running, or waiting to be run,
the Titanium Cloud will not be able to declare the action complete.
Keep in mind that many events that offer a post notification will
require the VM's Guest-Client to reconnect to the compute host, and
that may be further delayed while the VM is rebooted as in a cold
migration. When post-notification is finally triggered, it is subject
to a timeout as well. If the timeout is reached, the event will be
declared complete.
NOTE: A post-event notification that follows a reboot, as in the
cold_migrate_end event, is a special case. It will be triggered as
soon as the local heartbeat server reconnects with the compute host,
and likely before any processes have a chance to register a handler.
The only handler guaranteed to see such a notification is a script
directly registered by the Guest-Client itself via guest_heartbeat.conf.
In addition to notifications, there is also an opportunity for the VM
to vote on any proposed event. Voting precedes all notifications,
and offers the VM a chance to reject the event the Titanium Cloud wishes
to initiate. If multiple handlers are registered, it only takes one
rejection to abort the event.
The same handler that handles notifications also handles voting.
Voting is subject to a configurable timeout. The same timeout applies
regardless of the event. The timeout is specified when the Guest-Client
registers with compute services on the host. The timeout is specified in
the guest_heartbeat.conf file. This timeout governs the maximum time all
registered voting handlers have to complete the vote.
Any voters that fail to vote within the timeout are assumed to have agreed
with the proposed action.
Rejecting an event should be the exception, not the rule, reserved for
cases when the VM is handling an exceptionally sensitive operation,
as well as a slow operation that can't complete in the notification timeout.
An example
- an active-standby application deployment (1:1), where the active
rejects a shutdown or pause or ... due to its peer standby is not
ready or synchronized.
A vote handler should generally not take any action beyond returning its
vote. Just because you vote to accept, doesn't mean all your peers
will also accept (i.e. the event might not happen). Taking an action
against an event that never happens is almost certainly NOT what you want.
Instead save your actions for the notification that follows if no one
rejects. The one exception might be to temporarily block the initiation of
any new task that would cause you to vote to reject an event in the near
future. The theory being that the requester of the event may retry in
the near future.
The Titanium Cloud is not required to offer a vote. Voting may be
bypassed on certain recovery scenarios.
Configuring Guest-Client Notification and Voting ...
## The overall time to vote in seconds regardless of the event being voted
## upon. It should reflect the slowest of all expected voters when in a sane
## and healthy condition, plus some allowance for scheduling and messaging.
VOTE=8
## The overall time to handle a stop or reboot notification in seconds.
## It should reflect the slowest of all expected notification handlers
## when in a sane and healthy condition, plus some allowance for scheduling
## and messaging.
SHUTDOWN_NOTICE=8
## The overall time to handle a pause, suspend or migrate-begin notification
## in seconds. It should reflect the slowest of all expected notification
## handlers when in a sane and healthy condition, plus some allowance for
## scheduling and messaging.
SUSPEND_NOTICE=8
## The overall time to handle an unpause, resume or migrate-end notification
## in seconds. It should reflect the slowest of all expected notification
## handlers when in a sane and healthy condition, plus some allowance for
## scheduling and messaging. It does not include reboot time.
RESUME_NOTICE=13
## The overall time to reboot, up to the point the guest-client heartbeat
## starts in seconds. Allow for some I/O contention.
RESTART=300
## The Path to the event notification script. This is optional.
## The script will be called when an action is initiated that will impact
## the VM.
##
## The event handling script is invoked with two parameters:
##
## event_handling_script <MSG_TYPE> <EVENT>
##
## MSG_TYPE is one of:
## 'revocable' Indicating a vote is called for. Return zero to accept,
## non-zero to reject. For a rejection, the first line of
## stdout emitted by the script will be captured and logged
## logged indicating why the event was rejected.
##
## 'irrevocable' Indicating this is a notification only. Take preparatory
## actions and return zero if successful, or non-zero on
## failure. For a failure, the first line of stdout
## emitted by the script will be captured and logged
## indicating the cause of the failure.
##
## EVENT is one of: ( 'stop', 'reboot', 'pause', 'unpause', 'suspend',
## 'resume', 'live_migrate_begin',
## 'live_migrate_end', 'cold_migrate_begin',
## 'cold_migrate_end' )
##
EVENT_NOTIFICATION_SCRIPT="/etc/guest-client/heartbeat/sample_event_handling_script"
VM Application Setup
====================
An application running in the VM may wish to register directly for voting
and notifications. See the guest_heartbeat_api.h for more details. A
working example can be found in the guest_client_api source directory in the
sample_guest_app.c file.
To compile the sample-guest-app run ...
cd wrs-guest-heartbeat-3.0.0
make sample
This will create an executable called sample-guest-app in the 'build'
directory.
When compiling the guest application ...
include headers:
#include <guest_api_types.h>
#include <guest_ap_debug.h>
#include <guest_heartbeat_api.h>
link with:
-lguest_common_api -lguest_heartbeat_api

View File

@ -0,0 +1,84 @@
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SHELL = /bin/sh
## Configuration Directory Variables
prefix := /usr/local
exec_prefix := $(prefix)
sysconfdir := $(prefix)/etc
includedir := $(prefix)/include
libdir := $(exec_prefix)/lib
bindir := $(exec_prefix)/bin
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
BUILD_DIR := $(CURRENT_DIR)/build
CONFIG_DIR := $(sysconfdir)/guest-client/heartbeat
PACKAGE_DIR := $(BUILD_DIR)/package
PACKAGE_ROOT_DIR := $(PACKAGE_DIR)/rootdir
.PHONY: all build sample clean distclean package
all: build
build:
mkdir -p --mode 755 $(BUILD_DIR)
@(cd src; make --no-print-directory build \
sysconfdir=$(sysconfdir) BUILD_DIR=$(BUILD_DIR))
sample:
@:
clean:
@-(cd src; make --no-print-directory clean BUILD_DIR=$(BUILD_DIR))
distclean: clean
package:
@(mkdir -p --mode 755 $(PACKAGE_DIR))
@(echo "Packaging guest-client.init in $(PACKAGE_DIR)")
@(cp $(CURRENT_DIR)/scripts/guest-client.init $(PACKAGE_DIR)/guest-client.init)
@(chmod 755 $(PACKAGE_DIR)/guest-client.init)
@(echo "Packaging guest-client.service in $(PACKAGE_DIR)")
@(cp $(CURRENT_DIR)/scripts/guest-client.service $(PACKAGE_DIR)/guest-client.service)
@(chmod 644 $(PACKAGE_DIR)/guest-client.service)
@(echo "Packaging guest-client.systemd in $(PACKAGE_DIR)")
@(cp $(CURRENT_DIR)/scripts/guest-client.systemd $(PACKAGE_DIR)/guest-client.systemd)
@(mkdir -p --mode 755 $(PACKAGE_ROOT_DIR)/$(CONFIG_DIR))
@(echo "Packaging guest_heartbeat.conf in $(PACKAGE_ROOT_DIR)/$(CONFIG_DIR)")
@(cp $(CURRENT_DIR)/scripts/guest_heartbeat.conf $(PACKAGE_ROOT_DIR)/$(CONFIG_DIR)/guest_heartbeat.conf)
@(echo "Packaging sample_event_handling_script in $(PACKAGE_ROOT_DIR)/$(CONFIG_DIR)")
@(cp $(CURRENT_DIR)/scripts/sample_event_handling_script $(PACKAGE_ROOT_DIR)/$(CONFIG_DIR)/sample_event_handling_script)
@(echo "Packaging sample_health_check_script in $(PACKAGE_ROOT_DIR)/$(CONFIG_DIR)")
@(cp $(CURRENT_DIR)/scripts/sample_health_check_script $(PACKAGE_ROOT_DIR)/$(CONFIG_DIR)/sample_health_check_script)
@-(cd src; make --no-print-directory package BUILD_DIR=$(BUILD_DIR) \
PACKAGE_DIR=$(PACKAGE_DIR) prefix=$(prefix) exec_prefix=$(exec_prefix) \
sysconfdir=$(sysconfdir) includedir=$(includedir) libdir=$(libdir) \
bindir=$(bindir))

View File

@ -0,0 +1,183 @@
#! /bin/sh
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# chkconfig: - 96 96
#
### BEGIN INIT INFO
# Short-Description: Guest-Client
# Provides: guest-client
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Required-Start:
# Required-Stop:
### END INIT INFO
# Assumes that LSB (Linux Standard Base) scripts are available. On Fedora and
# other Red Hat related distros, the redhat-lsb package is optional.
if [ -f /etc/init.d/functions ]
then
. /etc/init.d/functions
else
. /lib/lsb/init-functions
fi
# LSB Exit Codes
# 0 - success
# 1 - generic or unspecified error
# 2 - invalid or excess arguments
# 3 - unimplemented feature
# 4 - user had insufficient privileges
# 5 - program is not installed
# 6 - program is not configured
# 7 - program is not running
#
# LSB Exit Status Codes
# 0 - program is running or service OK
# 1 - program is dead and /var/run pid file exists
# 2 - program is dead and /var/lock lock file exists
# 3 - program is not running
# 4 - program or service status is unknown
#
RETVAL=0
# Update binary location and device to be used, if necessary.
GUEST_CLIENT_NAME="guest-client"
GUEST_CLIENT_PIDFILE="/var/run/${GUEST_CLIENT_NAME}.pid"
GUEST_CLIENT="/usr/bin/${GUEST_CLIENT_NAME}"
GUEST_CLIENT_DEVICE="/dev/virtio-ports/cgcs.heartbeat"
if [ ! -e "${GUEST_CLIENT}" ]
then
echo "${GUEST_CLIENT} is missing"
exit 5
fi
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
case "$1" in
start)
args=""
if [ -n ${GUEST_CLIENT_DEVICE} ]
then
args="--device ${GUEST_CLIENT_DEVICE}"
fi
echo -n "Starting ${GUEST_CLIENT_NAME}: "
if [ -n "`pidof ${GUEST_CLIENT}`" ]
then
# Something might have started guest-client already.
RETVAL=0
else
start-stop-daemon --start --background --make-pidfile --pidfile ${GUEST_CLIENT_PIDFILE} --exec ${GUEST_CLIENT} -- ${args}
RETVAL=$?
fi
if [ ${RETVAL} -eq 0 ]
then
echo "OK"
else
echo "FAIL"
RETVAL=1
fi
;;
stop)
echo -n "Stopping ${GUEST_CLIENT_NAME}: "
if [ -n "`pidof ${GUEST_CLIENT}`" ]
then
killproc ${GUEST_CLIENT}
fi
SHUTDOWN_TIMEOUT=10
count=0
while [ ${count} -lt ${SHUTDOWN_TIMEOUT} ]
do
pidof ${GUEST_CLIENT} &> /dev/null
rc=$?
if [ ${rc} -eq 1 ]
then
echo "OK"
break
fi
count=`expr ${count} + 1`
sleep 1
done
pidof ${GUEST_CLIENT} &> /dev/null
rc=$?
if [ ${rc} -eq 0 ]
then
echo "FAIL"
RETVAL=1
fi
rm -f ${GUEST_CLIENT_PIDFILE}
;;
status)
pid=`cat ${GUEST_CLIENT_PIDFILE} 2>/dev/null`
if [ -n "${pid}" ]
then
if ps -p ${pid} &>/dev/null
then
echo "${GUEST_CLIENT_NAME} is running"
RETVAL=0
else
echo "${GUEST_CLIENT_NAME} is not running but has pid file"
RETVAL=1
fi
else
echo "${GUEST_CLIENT_NAME} is not running"
RETVAL=3
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
reload)
pid=`cat ${GUEST_CLIENT_PIDFILE} 2>/dev/null`
if [ -n "${pid}" ]
then
echo "${GUEST_CLIENT_NAME} reload"
kill -HUP ${pid}
fi
;;
*)
echo "usage: $0 { start | stop | status | restart | reload }"
;;
esac
exit ${RETVAL}

View File

@ -0,0 +1,57 @@
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
[Unit]
Description=Titanium Guest-Client
After=network.target
[Service]
Type=forking
PIDFile=/var/run/guest-client.pid
EnvironmentFile=/etc/guest-client/heartbeat/guest_heartbeat.conf
ExecStart=/etc/guest-client/guest-client.systemd start
ExecStop=/etc/guest-client/guest-client.systemd stop
ExecReload=/etc/guest-client/guest-client.systemd restart
# We want systemd to give guest-client some time to finish gracefully, but
# still want it to kill guest-client after TimeoutStopSec if something went
# wrong during the graceful stop. Normally, systemd sends SIGTERM signal right
# after the ExecStop, which would kill heartbeat. We are sending useless SIGCONT
# here to give guest-client time to finish.
KillSignal=SIGCONT
# Exit code of 6 indicates it is not configured and no restart.
# if /dev/virtio-ports/cgcs.heartbeat is not found, guest-client
# returns 6 on exit. We don't want to keep restarting guest-client
# if it is not configured.
RestartPreventExitStatus=6
Restart=always
RestartSec=15
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,171 @@
#! /bin/sh
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Assumes that LSB (Linux Standard Base) scripts are available. On Fedora and
# other Red Hat related distros, the redhat-lsb package is optional.
if [ -f /etc/init.d/functions ]
then
. /etc/init.d/functions
else
. /lib/lsb/init-functions
fi
# LSB Exit Codes
# 0 - success
# 1 - generic or unspecified error
# 2 - invalid or excess arguments
# 3 - unimplemented feature
# 4 - user had insufficient privileges
# 5 - program is not installed
# 6 - program is not configured
# 7 - program is not running
#
# LSB Exit Status Codes
# 0 - program is running or service OK
# 1 - program is dead and /var/run pid file exists
# 2 - program is dead and /var/lock lock file exists
# 3 - program is not running
# 4 - program or service status is unknown
#
RETVAL=0
# Update binary location and device to be used, if necessary.
GUEST_CLIENT_NAME="guest-client"
GUEST_CLIENT_PIDFILE="/var/run/${GUEST_CLIENT_NAME}.pid"
GUEST_CLIENT="/usr/local/bin/${GUEST_CLIENT_NAME}"
GUEST_CLIENT_DEVICE="/dev/virtio-ports/cgcs.heartbeat"
if [ ! -e "${GUEST_CLIENT}" ]
then
echo "${GUEST_CLIENT} is missing"
exit 5
fi
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
case "$1" in
start)
args=""
if [ -n ${GUEST_CLIENT_DEVICE} ]
then
args="--device ${GUEST_CLIENT_DEVICE}"
fi
echo -n "Starting ${GUEST_CLIENT_NAME}: "
if [ -n "`pidof ${GUEST_CLIENT}`" ]
then
# Something might have started guest-client already.
RETVAL=0
else
start-stop-daemon --start --background --make-pidfile --pidfile ${GUEST_CLIENT_PIDFILE} --exec ${GUEST_CLIENT} -- ${args}
RETVAL=$?
fi
if [ ${RETVAL} -eq 0 ]
then
echo "OK"
else
echo "FAIL"
RETVAL=1
fi
;;
stop)
echo -n "Stopping ${GUEST_CLIENT_NAME}: "
if [ -n "`pidof ${GUEST_CLIENT}`" ]
then
killproc ${GUEST_CLIENT}
fi
SHUTDOWN_TIMEOUT=10
count=0
while [ ${count} -lt ${SHUTDOWN_TIMEOUT} ]
do
pidof ${GUEST_CLIENT} &> /dev/null
rc=$?
if [ ${rc} -eq 1 ]
then
echo "OK"
break
fi
count=`expr ${count} + 1`
sleep 1
done
pidof ${GUEST_CLIENT} &> /dev/null
rc=$?
if [ ${rc} -eq 0 ]
then
echo "FAIL"
RETVAL=1
fi
rm -f ${GUEST_CLIENT_PIDFILE}
;;
status)
pid=`cat ${GUEST_CLIENT_PIDFILE} 2>/dev/null`
if [ -n "${pid}" ]
then
if ps -p ${pid} &>/dev/null
then
echo "${GUEST_CLIENT_NAME} is running"
RETVAL=0
else
echo "${GUEST_CLIENT_NAME} is not running but has pid file"
RETVAL=1
fi
else
echo "${GUEST_CLIENT_NAME} is not running"
RETVAL=3
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
reload)
pid=`cat ${GUEST_CLIENT_PIDFILE} 2>/dev/null`
if [ -n "${pid}" ]
then
echo "${GUEST_CLIENT_NAME} reload"
kill -HUP ${pid}
fi
;;
*)
echo "usage: $0 { start | stop | status | restart | reload }"
;;
esac
exit ${RETVAL}

View File

@ -0,0 +1,116 @@
###
# Copyright (c) <2013-2017>, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1) Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2) Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
#
# 3) Neither the name of Wind River Systems nor the names of its contributors may be
# used to endorse or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###
##################################################
## Heartbeat health check options
## This specifies the interval between heartbeats in milliseconds between the
## guest-client heartbeat and the Titanium Cloud Compute Services on the
## compute node host.
HB_INTERVAL=1000
## This specifies the corrective action against the VM in the case of a
## heartbeat failure between the guest-client and Titanium Cloud Compute
## Services on the compute node host and also when the health script
## configured below fails.
##
## Your options are:
## "log" Only a log is issued.
## "reboot" Issue a reboot against this VM.
## "stop" Issue a stop against this VM.
##
CORRECTIVE_ACTION="reboot"
##################################################
## Heartbeat event notification and voting options
## The overall time to vote in seconds regardless of the event being voted
## upon. It should reflect the slowest of all expected voters when in a sane
## and healthy condition, plus some allowance for scheduling and messaging.
VOTE=8
## The overall time to handle a stop or reboot notification in seconds.
## It should reflect the slowest of all expected notification handlers
## when in a sane and healthy condition, plus some allowance for scheduling
## and messaging.
SHUTDOWN_NOTICE=8
## The overall time to handle a pause, suspend or migrate-begin notification
## in seconds. It should reflect the slowest of all expected notification
## handlers when in a sane and healthy condition, plus some allowance for
## scheduling and messaging.
SUSPEND_NOTICE=8
## The overall time to handle an unpause, resume or migrate-end notification
## in seconds. It should reflect the slowest of all expected notification
## handlers when in a sane and healthy condition, plus some allowance for
## scheduling and messaging. It does not include reboot time.
RESUME_NOTICE=13
## The overall time to reboot, up to the point the guest-client heartbeat
## starts in seconds. Allow for some I/O contention.
RESTART=600
##################################################
## The Path to the health check script. This is optional.
## The script will be called periodically to check for the health of the VM.
## The health check interval is specified in seconds.
HEALTH_CHECK_INTERVAL=30
HEALTH_CHECK_SCRIPT="/etc/guest-client/heartbeat/sample_health_check_script"
##################################################
## The Path to the event notification script. This is optional.
## The script will be called when an action is initiated that will impact
## the VM.
##
## The event handling script is invoked with two parameters:
##
## event_handling_script <MSG_TYPE> <EVENT>
##
## MSG_TYPE is one of:
## 'revocable' Indicating a vote is called for. Return zero to accept,
## non-zero to reject. For a rejection, the first line of
## stdout emitted by the script will be captured and logged
## logged indicating why the event was rejected.
##
## 'irrevocable' Indicating this is a notification only. Take preparatory
## actions and return zero if successful, or non-zero on
## failure. For a failure, the first line of stdout
## emitted by the script will be captured and logged
## indicating the cause of the failure.
##
## EVENT is one of: ( 'stop', 'reboot', 'pause', 'unpause', 'suspend',
## 'resume', 'live_migrate_begin',
## 'live_migrate_end', 'cold_migrate_begin',
## 'cold_migrate_end' )
##
EVENT_NOTIFICATION_SCRIPT="/etc/guest-client/heartbeat/sample_event_handling_script"

View File

@ -0,0 +1,165 @@
#!/bin/sh
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
MSG_TYPE=$1
EVENT=$2
FILE="/tmp/event_timeout"
if [ -f $FILE ];
then
echo "File $FILE exists."
logger "File $FILE exists. Run slowly to trigger timeout"
sleep 300
logger "$FILE induced delay ends"
else
logger "File $FILE does not exist."
fi
if [ "$MSG_TYPE" == "revocable" ]
then
# Vote on the proposed action ( 0 == agree, 1 == reject )
# Take no actions yet.
# If no other parties have rejected the proposed action, an "irrevocable"
# notification will soon follow.
if [ $EVENT == "stop" ]
then
FILE="/tmp/vote_no_to_stop"
elif [ "$EVENT" == "reboot" ]
then
FILE="/tmp/vote_no_to_reboot"
elif [ "$EVENT" == "suspend" ] || [ "$EVENT" == "pause" ]
then
FILE="/tmp/vote_no_to_suspend"
elif [ "$EVENT" == "live_migrate_begin" ] || [ "$EVENT" == "cold_migrate_begin" ]
then
FILE="/tmp/vote_no_to_migrate"
elif [ "$EVENT" == "resize_begin" ]
then
FILE="/tmp/vote_no_to_resize"
elif [ "$EVENT" == "live_migrate_end" ] || [ "$EVENT" == "cold_migrate_end" ] ||
[ "$EVENT" == "resize_end" ] || [ "$EVENT" == "unpause" ] ||
[ "$EVENT" == "resume" ]
then
logger "Should never be asked to vote on $EVENT"
echo "Should never be asked to vote on $EVENT"
exit 1
fi
if [ -f $FILE ];
then
echo "File $FILE exists."
logger "File $FILE exists."
logger "Vote against $EVENT at this time."
# Vote no to shutdown.
exit 1
else
echo "File $FILE does not exist."
logger "File $FILE does not exists."
logger "Vote to allow $EVENT"
# Vote yes to shutdown.
exit 0
fi
elif [ "$MSG_TYPE" == "irrevocable" ]
then
if [ $EVENT == "stop" ]
then
logger "Notification of pending $EVENT received."
# Place clean shutdown actions here. Idea is to hand off activity and
# cleanly stop the payload application. It is not required to stop the
# kernel, an ACPI power-off event will follow.
elif [ "$EVENT" == "reboot" ]
then
logger "Notification of pending $EVENT received."
# Place clean shutdown actions here. Idea is to hand off activity and
# cleanly stop the application. It is not required to stop/reboot the
# kernel, an ACPI power-off event will follow, and then a power-on
elif [ "$EVENT" == "pause" ] || [ "$EVENT" == "suspend" ]
then
logger "Notification of pending $EVENT received."
# This VM will be paused or suspended but not rebooted.
# Hand off activity and cleanly stop the application if required.
elif [ "$EVENT" == "unpause" ] || [ "$EVENT" == "resume" ]
then
logger "Notification of $EVENT completion received."
# This VM has resumed from a paused or suspended state.
# Restart your application and take activity as required.
elif [ "$EVENT" == "resize_begin" ]
then
logger "Notification of pending resize received. ($EVENT)"
# This VM will soon be resized.
# Hand off activity and cleanly stop the payload application if required.
elif [ "$EVENT" == "resize_end" ]
then
logger "Notification of resize complete received."
# This VM has been resized.
# Restart your application and/or re-establish your network connectivity
# as required.
elif [ "$EVENT" == "live_migrate_begin" ] || [ "$EVENT" == "cold_migrate_begin" ]
then
logger "Notification of pending migration received. ($EVENT)"
# This VM will soon relocate to a different host.
# Network connectivity may change.
# Hand off activity and cleanly stop the payload application if required.
elif [ "$EVENT" == "live_migrate_end" ] || [ "$EVENT" == "cold_migrate_end" ]
then
logger "Notification of migration complete received."
# This VM has finished relocation to a new host.
# Network connectivity may have changed.
# Restart your application and/or re-establish your network connectivity
# as required.
fi
sleep 1
exit 0
else
echo "Unknown message type '$MSG_TYPE'"
logger "Unknown message type '$MSG_TYPE'"
sleep 1
exit -1
fi

View File

@ -0,0 +1,42 @@
#!/bin/sh
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
FILE="/tmp/unhealthy"
if [ -f $FILE ];
then
echo "File $FILE exists."
rm -f $FILE
exit 1
else
echo "File $FILE does not exist."
fi
exit 0

View File

@ -0,0 +1,94 @@
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SHELL = /bin/sh
## Configuration Directory Variables
prefix := /usr/local
exec_prefix := $(prefix)
sysconfdir := $(prefix)/etc
includedir := $(prefix)/include
libdir := $(exec_prefix)/lib
bindir := $(exec_prefix)/bin
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
ifndef BUILD_DIR
$(error BUILD_DIR undefined)
endif
PACKAGE_DIR := $(BUILD_DIR)/package
PACKAGE_ROOT_DIR := $(PACKAGE_DIR)/rootdir
.SUFFIXES:
.SUFFIXES: .c .o
.PHONY: all build heartbeat clean distclean package
heartbeat_C_SRCS := $(wildcard $(CURRENT_DIR)/heartbeat/*.c)
heartbeat_C_SRCS := $(subst $(CURRENT_DIR)/heartbeat/,,$(heartbeat_C_SRCS))
heartbeat_C_OBJS := ${heartbeat_C_SRCS:.c=.o}
program_NAME := guest-client
program_C_INCLUDES := -I$(CURRENT_DIR) -I$(CURRENT_DIR)/heartbeat
program_C_INCLUDES += -I$(CURRENT_DIR)/../../include
program_C_SRCS := $(wildcard *.c)
program_C_OBJS := ${program_C_SRCS:.c=.o}
program_LDLIBS := -lrt
program_BUILD_OBJS := $(addprefix $(BUILD_DIR)/, $(heartbeat_C_OBJS))
program_BUILD_OBJS += $(addprefix $(BUILD_DIR)/, $(program_C_OBJS))
CFLAGS = -g -O2 -Wall -Werror -Wformat -DSYSCONFDIR=$(sysconfdir)
all: build
heartbeat:
@(cd heartbeat; make --no-print-directory build \
sysconfdir=$(sysconfdir) BUILD_DIR=$(BUILD_DIR))
%.o: %.c
$(CC) $(CFLAGS) $(program_C_INCLUDES) -c $^ -o $(BUILD_DIR)/$@
$(program_NAME): heartbeat $(program_C_OBJS)
$(CC) $(CFLAGS) $(program_BUILD_OBJS) $(program_LDLIBS) \
-o $(BUILD_DIR)/$(program_NAME) -ljson-c
build: $(program_NAME)
clean:
@-($(RM) -Rf $(BUILD_DIR)/*)
distclean: clean
package:
@(mkdir -p --mode 755 $(PACKAGE_ROOT_DIR)/$(bindir))
@(echo "Packaging $(program_NAME) in $(PACKAGE_ROOT_DIR)/$(bindir)")
@(cp $(BUILD_DIR)/$(program_NAME) $(PACKAGE_ROOT_DIR)/$(bindir)/$(program_NAME))
@(chmod 755 $(PACKAGE_ROOT_DIR)/$(bindir)/$(program_NAME))

View File

@ -0,0 +1,351 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_channel.h"
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_unix.h"
typedef struct {
bool inuse;
bool char_device;
int sock;
char dev_name[GUEST_DEVICE_NAME_MAX_CHAR];
} GuestChannelT;
static GuestChannelT _channel[GUEST_MAX_CONNECTIONS];
// ****************************************************************************
// Guest Channel - Find Empty
// ==========================
static GuestChannelIdT guest_channel_find_empty( void )
{
GuestChannelT* channel = NULL;
unsigned int channel_id;
for (channel_id=0; GUEST_MAX_CONNECTIONS > channel_id; ++channel_id)
{
channel = &(_channel[channel_id]);
if (!channel->inuse)
return channel_id;
}
return GUEST_CHANNEL_ID_INVALID;
}
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Find
// ====================
static GuestChannelT* guest_channel_find( GuestChannelIdT channel_id )
{
GuestChannelT* channel = NULL;
if ((0 <= channel_id)&&(GUEST_MAX_CONNECTIONS > channel_id))
{
channel = &(_channel[channel_id]);
if (channel->inuse)
return channel;
}
return NULL;
}
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Send
// ====================
GuestErrorT guest_channel_send(
GuestChannelIdT channel_id, void* msg, int msg_size )
{
GuestChannelT* channel;
ssize_t result;
channel = guest_channel_find(channel_id);
if (NULL == channel)
{
DPRINTFE("Invalid channel identifier, channel_id=%i.", channel_id);
return GUEST_FAILED;
}
result = write(channel->sock, msg, msg_size);
if (0 > result)
{
if (ENODEV == errno)
{
DPRINTFI("Channel %i on device %s disconnected.", channel_id,
channel->dev_name);
return GUEST_OKAY;
} else {
DPRINTFE("Failed to write to channel on device %s, error=%s.",
channel->dev_name, strerror(errno));
return GUEST_FAILED;
}
}
DPRINTFV("Sent message over channel on device %s.", channel->dev_name);
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Receive
// =======================
GuestErrorT guest_channel_receive(
GuestChannelIdT channel_id, char* msg_buf, int msg_buf_size,
int* msg_size )
{
GuestChannelT* channel;
ssize_t result;
channel = guest_channel_find(channel_id);
if (NULL == channel)
{
DPRINTFE("Invalid channel identifier, channel_id=%i.", channel_id);
return GUEST_FAILED;
}
result = read(channel->sock, msg_buf, msg_buf_size);
if (0 > result)
{
if (EINTR == errno)
{
DPRINTFD("Interrupted on socket read, error=%s.", strerror(errno));
return GUEST_INTERRUPTED;
} else if (ENODEV == errno) {
DPRINTFI("Channel %i on device %s disconnected.", channel_id,
channel->dev_name);
*msg_size = 0;
return GUEST_OKAY;
} else {
DPRINTFE("Failed to read from socket, error=%s.", strerror(errno));
return GUEST_FAILED;
}
} else if (0 == result) {
DPRINTFD("No message received from socket.");
*msg_size = 0;
return GUEST_OKAY;
} else {
DPRINTFV("Received message, msg_size=%i.", result);
*msg_size = result;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Open
// ====================
GuestErrorT guest_channel_open( char dev_name[], GuestChannelIdT* channel_id )
{
int fd;
int result;
struct stat stat_data;
GuestChannelIdT empty_channel_id;
GuestChannelT* channel;
GuestErrorT error;
empty_channel_id = guest_channel_find_empty();
if (GUEST_CHANNEL_ID_INVALID == empty_channel_id)
{
DPRINTFE("Allocation of channel failed, no free resources.");
return GUEST_FAILED;
}
channel = &(_channel[empty_channel_id]);
memset(channel, 0, sizeof(GuestChannelT));
result = stat(dev_name, &stat_data);
if (0 > result)
{
int err = errno;
if (err == ENOENT)
{
DPRINTFI("Failed to stat, error=%s.", strerror(err));
DPRINTFI("%s file does not exist, guest heartbeat not configured.",
dev_name);
return GUEST_NOT_CONFIGURED;
}
else {
DPRINTFE("Failed to stat, error=%s.", strerror(err));
return GUEST_FAILED;
}
}
if (S_ISCHR(stat_data.st_mode))
{
fd = open(dev_name, O_RDWR);
if (0 > fd)
{
DPRINTFE("Failed to open device %s, error=%s.", dev_name,
strerror(errno));
return GUEST_FAILED;
}
result = fcntl(fd, F_SETFD, FD_CLOEXEC);
if (0 > result)
{
DPRINTFE("Failed to set to close on exec, error=%s.",
strerror(errno));
close(fd);
return GUEST_FAILED;
}
result = fcntl(fd, F_SETOWN, getpid());
if (0 > result)
{
DPRINTFE("Failed to set socket ownership, error=%s.",
strerror(errno));
close(fd);
return GUEST_FAILED;
}
result = fcntl(fd, F_GETFL);
if (0 > result)
{
DPRINTFE("Failed to get socket options, error=%s.",
strerror(errno));
close(fd);
return GUEST_FAILED;
}
result = fcntl(fd, F_SETFL, result | O_NONBLOCK | O_ASYNC);
if (0 > result)
{
DPRINTFE("Failed to set socket options, error=%s.",
strerror(errno));
close(fd);
return GUEST_FAILED;
}
DPRINTFI("Opened character device %s", dev_name);
} else {
error = guest_unix_open(&fd);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to open unix socket %s, error=%s.",
dev_name, guest_error_str(error));
return error;
}
error = guest_unix_connect(fd, dev_name);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to connect unix socket %s, error=%s.",
dev_name, guest_error_str(error));
close(fd);
return error;
}
DPRINTFI("Opened unix socket %s", dev_name);
}
channel->inuse = true;
snprintf(channel->dev_name, sizeof(channel->dev_name), "%s", dev_name);
channel->char_device = S_ISCHR(stat_data.st_mode);
channel->sock = fd;
*channel_id = empty_channel_id;
DPRINTFD("Opened channel over device %s.", channel->dev_name);
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Close
// =====================
GuestErrorT guest_channel_close( GuestChannelIdT channel_id )
{
GuestChannelT* channel;
channel = guest_channel_find(channel_id);
if (NULL != channel)
{
if (channel->inuse)
{
if (0 <= channel->sock)
close(channel->sock);
DPRINTFD("Closed channel over device %s.", channel->dev_name);
memset(channel, 0, sizeof(GuestChannelT));
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Get Selection Object
// ====================================
int guest_channel_get_selobj( GuestChannelIdT channel_id )
{
GuestChannelT *channel;
channel = guest_channel_find(channel_id);
if (NULL != channel)
return channel->sock;
return -1;
}
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Initialize
// ==========================
GuestErrorT guest_channel_initialize( void )
{
memset(_channel, 0, sizeof(_channel));
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Finalize
// ========================
GuestErrorT guest_channel_finalize( void )
{
memset(_channel, 0, sizeof(_channel));
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_CHANNEL_H__
#define __GUEST_CHANNEL_H__
#include <stdbool.h>
#include "guest_limits.h"
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GUEST_CHANNEL_ID_INVALID -1
typedef int GuestChannelIdT;
// ****************************************************************************
// Guest Channel - Send
// ====================
extern GuestErrorT guest_channel_send(
GuestChannelIdT channel_id, void* msg, int msg_size );
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Receive
// =======================
extern GuestErrorT guest_channel_receive(
GuestChannelIdT channel_id, char* msg_buf, int msg_buf_size,
int* msg_size );
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Open
// ====================
extern GuestErrorT guest_channel_open(
char dev_name[], GuestChannelIdT* channel_id );
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Close
// =====================
extern GuestErrorT guest_channel_close( GuestChannelIdT channel_id );
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Get Selection Object
// ====================================
extern int guest_channel_get_selobj( GuestChannelIdT channel_id );
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Initialize
// ==========================
extern GuestErrorT guest_channel_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Channel - Finalize
// ========================
extern GuestErrorT guest_channel_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_CHANNEL_H__ */

View File

@ -0,0 +1,312 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_child_death.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/eventfd.h>
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_selobj.h"
#define GUEST_CHILD_DEATH_MAX_DISPATCH 32
typedef struct {
bool valid;
pid_t pid;
int exit_code;
} GuestChildDeathInfoT;
typedef struct {
bool valid;
pid_t pid;
GuestChildDeathCallbackT death_callback;
} GuestChildDeathCallbackInfoT;
static int _child_death_fd = -1;
static GuestChildDeathCallbackInfoT _callbacks[GUEST_CHILD_PROCESS_MAX];
static GuestChildDeathInfoT _child_deaths[GUEST_CHILD_PROCESS_MAX];
static uint64_t _child_death_count = 0;
// ****************************************************************************
// Guest Child Death - Register
// ============================
GuestErrorT guest_child_death_register(
pid_t pid, GuestChildDeathCallbackT callback )
{
GuestChildDeathCallbackInfoT* callback_info = NULL;
unsigned int callbacks_i;
for (callbacks_i=0; GUEST_CHILD_PROCESS_MAX > callbacks_i; ++callbacks_i)
{
callback_info = &(_callbacks[callbacks_i]);
if (callback_info->valid)
{
if (pid == callback_info->pid)
{
callback_info->death_callback = callback;
break;
}
} else {
callback_info->valid = true;
callback_info->pid = pid;
callback_info->death_callback = callback;
break;
}
}
if (GUEST_CHILD_PROCESS_MAX <= callbacks_i)
{
DPRINTFE("Failed to register child death callback for pid (%i).",
(int) pid);
return GUEST_FAILED;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Child Death - Deregister
// ==============================
GuestErrorT guest_child_death_deregister( pid_t pid )
{
GuestChildDeathCallbackInfoT* callback_info = NULL;
unsigned int callbacks_i;
for (callbacks_i=0; GUEST_CHILD_PROCESS_MAX > callbacks_i; ++callbacks_i)
{
callback_info = &(_callbacks[callbacks_i]);
if (!callback_info->valid)
continue;
if (pid != callback_info->pid)
continue;
callback_info->valid = 0;
callback_info->pid = 0;
callback_info->death_callback = NULL;
break;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Child Death - Save
// ========================
GuestErrorT guest_child_death_save( pid_t pid, int exit_code )
{
uint64_t child_death_count = ++_child_death_count;
GuestChildDeathInfoT* info = NULL;
int result;
result = write(_child_death_fd, &child_death_count,
sizeof(child_death_count));
if (0 > result)
DPRINTFE("Failed to signal child death, error=%s", strerror(errno));
DPRINTFD("Child process (%i) died.", (int) pid);
unsigned int death_i;
for (death_i=0; GUEST_CHILD_PROCESS_MAX > death_i; ++death_i)
{
info = &(_child_deaths[death_i]);
if (info->valid)
{
if (pid == info->pid)
{
info->exit_code = exit_code;
break;
}
} else {
info->valid = true;
info->pid = pid;
info->exit_code = exit_code;
break;
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Child Death - Dispatch
// ============================
static void guest_child_death_dispatch( int selobj )
{
static unsigned int _last_entry = 0;
uint64_t child_death_count;
GuestChildDeathInfoT* info = NULL;
GuestChildDeathCallbackInfoT* callback_info = NULL;
unsigned int num_child_death_dispatched = 0;
int result;
result = read(_child_death_fd, &child_death_count, sizeof(child_death_count));
if (0 > result)
{
if (EINTR == errno)
{
DPRINTFD("Interrupted on read, error=%s.", strerror(errno));
} else {
DPRINTFE("Failed to dispatch, error=%s.", strerror(errno));
}
}
unsigned int death_i;
for( death_i=_last_entry; GUEST_CHILD_PROCESS_MAX > death_i; ++death_i )
{
info = &(_child_deaths[death_i]);
if (!info->valid)
continue;
if (0 == info->pid)
continue;
DPRINTFD("Child process (%i) exited with %i.", (int) info->pid,
info->exit_code);
unsigned int callbacks_i;
for (callbacks_i=0; GUEST_CHILD_PROCESS_MAX > callbacks_i; ++callbacks_i)
{
callback_info = &(_callbacks[callbacks_i]);
if (callback_info->valid)
{
if (info->pid == callback_info->pid)
{
if (NULL != callback_info->death_callback)
{
callback_info->death_callback(info->pid, info->exit_code);
callback_info->valid = false;
}
}
}
}
info->valid = false;
if (GUEST_CHILD_DEATH_MAX_DISPATCH <= ++num_child_death_dispatched)
DPRINTFD("Maximum child process death dispatches (%i) reached.",
GUEST_CHILD_DEATH_MAX_DISPATCH);
}
if (GUEST_CHILD_PROCESS_MAX <= death_i)
_last_entry = 0;
else
_last_entry = death_i;
// Check for outstanding child process deaths to handle.
for (death_i=0; GUEST_CHILD_PROCESS_MAX > death_i; ++death_i)
{
info = &(_child_deaths[death_i]);
if (!info->valid)
continue;
if (0 == info->pid)
continue;
result = write(_child_death_fd, &child_death_count,
sizeof(child_death_count));
if (0 > result)
DPRINTFE("Failed to signal child process death, error=%s",
strerror(errno));
break;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Child Death - Initialize
// ==============================
GuestErrorT guest_child_death_initialize( void )
{
GuestSelObjCallbacksT callbacks;
GuestErrorT error;
_child_death_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
if (0 > _child_death_fd)
{
DPRINTFE("Failed to open child death file descriptor,error=%s.",
strerror(errno));
return GUEST_FAILED;
}
memset(&callbacks, 0, sizeof(callbacks));
callbacks.read_callback = guest_child_death_dispatch;
error = guest_selobj_register(_child_death_fd, &callbacks);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to register selection object, error=%s.",
guest_error_str(error));
close(_child_death_fd);
_child_death_fd = -1;
return error;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Child Death - Finalize
// ============================
GuestErrorT guest_child_death_finalize( void )
{
GuestErrorT error;
if (0 <= _child_death_fd)
{
error = guest_selobj_deregister(_child_death_fd);
if (GUEST_OKAY != error)
DPRINTFE("Failed to deregister selection object, error=%s.",
guest_error_str(error));
close(_child_death_fd);
_child_death_fd = -1;
}
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_CHILD_DEATH_H__
#define __GUEST_CHILD_DEATH_H__
#include <sys/types.h>
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GUEST_CHILD_FAILED -65536
typedef void (*GuestChildDeathCallbackT) (pid_t pid, int exit_code);
// ****************************************************************************
// Guest Child Death - Register
// ============================
extern GuestErrorT guest_child_death_register(
pid_t pid, GuestChildDeathCallbackT callback );
// ****************************************************************************
// ****************************************************************************
// Guest Child Death - Deregister
// ==============================
extern GuestErrorT guest_child_death_deregister( pid_t pid );
// ****************************************************************************
// ****************************************************************************
// Guest Child Death - Save
// ========================
extern GuestErrorT guest_child_death_save( pid_t pid, int exit_code );
// ****************************************************************************
// ****************************************************************************
// Guest Child Death - Initialize
// ==============================
extern GuestErrorT guest_child_death_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Child Death - Finalize
// ============================
extern GuestErrorT guest_child_death_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_CHILD_DEATH_H__ */

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_process.h"
// ****************************************************************************
// Guest Client - Main
// ===================
int main( int argc, char *argv[], char *envp[] )
{
GuestErrorT error;
error = guest_debug_initialize("Guest-Client");
if (GUEST_OKAY != error)
{
printf("Debug initialization failed, error=%s.\n",
guest_error_str(error));
return EXIT_FAILURE;
}
error = guest_process_main(argc, argv, envp);
if (GUEST_OKAY != error)
{
printf("Process failure, error=%s.\n", guest_error_str(error));
return error;
}
error = guest_debug_finalize();
if (GUEST_OKAY != error)
{
printf("Debug finalization failed, error=%s.\n",
guest_error_str(error));
}
return EXIT_SUCCESS;
}
// ****************************************************************************

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "guest_types.h"
#include "guest_debug.h"
#define GUEST_DEFAULT_COMM_DEVICE "/dev/vport1p1"
static GuestConfigT _config;
// ****************************************************************************
// Guest Configuration - Get
// =========================
GuestConfigT* guest_config_get( void )
{
return &_config;
}
// ****************************************************************************
// ****************************************************************************
// Guest Configuration - Show Usage
// ================================
void guest_config_show_usage( void )
{
printf("guest-client [ARGS]\n");
printf(" where ARGS may be any of: \n");
printf(" --name Override the name of the instance\n");
printf(" --device Override default communication channel device\n");
printf("\n");
}
// ****************************************************************************
// ****************************************************************************
// Guest Configuration - Dump
// ==========================
static void guest_config_dump( void )
{
DPRINTFI("Guest-Client Configuration:");
DPRINTFI(" name: %s", _config.name);
DPRINTFI(" device: %s", _config.comm_device);
}
// ****************************************************************************
// ****************************************************************************
// Guest Configuration - Parse Arguments
// =====================================
static GuestErrorT guest_config_parse_args( int argc, char *argv[] )
{
unsigned int arg_i;
for (arg_i=1; arg_i < argc; ++arg_i)
{
if (0 == strcmp("--name", argv[arg_i]))
{
arg_i++;
if (arg_i < argc)
snprintf(_config.name, sizeof(_config.name), "%s", argv[arg_i]);
} else if (0 == strcmp("--device", argv[arg_i])) {
arg_i++;
if (arg_i < argc)
snprintf(_config.comm_device, sizeof(_config.comm_device),
"%s", argv[arg_i]);
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Configuration - Parse Environment
// =======================================
static GuestErrorT guest_config_parse_env( char *envp[] )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Configuration - Initialize
// ================================
GuestErrorT guest_config_initialize( int argc, char *argv[], char *envp[] )
{
char name[GUEST_NAME_MAX_CHAR];
GuestErrorT error;
int result;
result = gethostname(name, sizeof(name));
if (0 > result)
{
DPRINTFE("Failed to get hostname, error=%s.", strerror(errno));
return GUEST_FAILED;
}
DPRINTFI("hostname=%s.", name);
memset(&_config, 0, sizeof(GuestConfigT));
snprintf(_config.name, sizeof(_config.name), "%s", name);
snprintf(_config.comm_device, sizeof(_config.comm_device), "%s",
GUEST_DEFAULT_COMM_DEVICE);
error = guest_config_parse_args(argc, argv);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to parse arguments, error=%s.",
guest_error_str(error));
return error;
}
error = guest_config_parse_env(envp);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to parse environment, error=%s.",
guest_error_str(error));
return error;
}
guest_config_dump();
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Configuration - Finalize
// ==============================
GuestErrorT guest_config_finalize( void )
{
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_CONFIGURATION_H__
#define __GUEST_CONFIGURATION_H__
#include "guest_limits.h"
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
char name[GUEST_NAME_MAX_CHAR];
char comm_device[GUEST_DEVICE_NAME_MAX_CHAR];
} GuestConfigT;
// ****************************************************************************
// Guest Configuration - Get
// =========================
extern GuestConfigT* guest_config_get( void );
// ****************************************************************************
// ****************************************************************************
// Guest Configuration - Show Usage
// ================================
extern void guest_config_show_usage( void );
// ****************************************************************************
// ****************************************************************************
// Guest Configuration - Initialize
// ================================
extern GuestErrorT guest_config_initialize(
int argc, char *argv[], char *envp[] );
// ****************************************************************************
// ****************************************************************************
// Guest Configuration - Finalize
// ==============================
extern GuestErrorT guest_config_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_CONFIGURATION_H__ */

View File

@ -0,0 +1,146 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_debug.h"
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "guest_types.h"
#define GUEST_DEBUG_WANT_SYSLOG
#ifdef GUEST_DEBUG_WANT_SYSLOG
#include <syslog.h>
#endif
static char _process_name[30];
static GuestDebugLogLevelT _log_level = GUEST_DEBUG_LOG_LEVEL_INFO;
// ****************************************************************************
// Guest Debug - Log Level String
// ==============================
const char* guest_debug_log_level_str( GuestDebugLogLevelT level )
{
switch (level) {
case GUEST_DEBUG_LOG_LEVEL_ERROR: return "error";
case GUEST_DEBUG_LOG_LEVEL_INFO: return " info";
case GUEST_DEBUG_LOG_LEVEL_DEBUG: return "debug";
case GUEST_DEBUG_LOG_LEVEL_VERBOSE: return " verb";
default:
return "???";
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Set Log Level
// ===========================
void guest_debug_set_log_level( GuestDebugLogLevelT level )
{
_log_level = level;
}
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Want Log
// ======================
bool guest_debug_want_log( GuestDebugLogLevelT level )
{
return (level <= _log_level);
}
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Log
// =================
void guest_debug_log( const char* format, ... )
{
char time_str[80];
char date_str[32];
struct tm t_real;
struct timespec ts_real;
va_list arguments;
char log_data[512];
va_start(arguments, format);
vsnprintf(log_data, sizeof(log_data), format, arguments);
va_end(arguments);
clock_gettime(CLOCK_REALTIME, &ts_real);
if (NULL == localtime_r(&(ts_real.tv_sec), &t_real))
{
snprintf( time_str, sizeof(time_str),
"YYYY:MM:DD HH:MM:SS.xxx" );
} else {
strftime( date_str, sizeof(date_str), "%b %e %H:%M:%S",
&t_real );
snprintf( time_str, sizeof(time_str), "%s.%03ld", date_str,
ts_real.tv_nsec/1000000 );
}
#ifdef GUEST_DEBUG_WANT_SYSLOG
syslog(LOG_DEBUG, "%s", log_data);
#else
printf("%s %s: %s\n", time_str, _process_name, log_data);
#endif
}
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Initialize
// ========================
GuestErrorT guest_debug_initialize( char process_name[] )
{
_log_level = GUEST_DEBUG_LOG_LEVEL_INFO;
snprintf(_process_name, sizeof(_process_name), "%s", process_name);
#ifdef GUEST_DEBUG_WANT_SYSLOG
openlog(_process_name, LOG_PID | LOG_NDELAY, LOG_DAEMON);
#endif
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Finalize
// ======================
GuestErrorT guest_debug_finalize( void )
{
_log_level = GUEST_DEBUG_LOG_LEVEL_INFO;
_process_name[0] = '\0';
#ifdef GUEST_DEBUG_WANT_SYSLOG
closelog();
#endif
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_DEBUG_H__
#define __GUEST_DEBUG_H__
#include <stdbool.h>
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
GUEST_DEBUG_LOG_LEVEL_ERROR,
GUEST_DEBUG_LOG_LEVEL_INFO,
GUEST_DEBUG_LOG_LEVEL_DEBUG,
GUEST_DEBUG_LOG_LEVEL_VERBOSE,
} GuestDebugLogLevelT;
#define DPRINTF(level, format, args...) \
if (guest_debug_want_log(level)) \
guest_debug_log("%s: %s(%i): " format, \
guest_debug_log_level_str(level), \
__FILE__, __LINE__, ##args)
#define DPRINTFE(format, args...) \
DPRINTF(GUEST_DEBUG_LOG_LEVEL_ERROR, format, ##args)
#define DPRINTFI(format, args...) \
DPRINTF(GUEST_DEBUG_LOG_LEVEL_INFO, format, ##args)
#define DPRINTFD(format, args...) \
DPRINTF(GUEST_DEBUG_LOG_LEVEL_DEBUG, format, ##args)
#define DPRINTFV(format, args... ) \
DPRINTF(GUEST_DEBUG_LOG_LEVEL_VERBOSE, format, ##args)
// ****************************************************************************
// Guest Debug - Log Level String
// ==============================
extern const char* guest_debug_log_level_str( GuestDebugLogLevelT level );
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Set Log Level
// ===========================
extern void guest_debug_set_log_level( GuestDebugLogLevelT level );
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Want Log
// ======================
extern bool guest_debug_want_log( GuestDebugLogLevelT level );
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Log
// =================
extern void guest_debug_log( const char* format, ... );
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Initialize
// ========================
extern GuestErrorT guest_debug_initialize( char process_name[] );
// ****************************************************************************
// ****************************************************************************
// Guest Debug - Finalize
// ======================
extern GuestErrorT guest_debug_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_DEBUG_H__ */

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_LIMITS_H__
#define __GUEST_LIMITS_H__
#ifdef __cplusplus
extern "C" {
#endif
#define GUEST_NAME_MAX_CHAR 64
#define GUEST_DEVICE_NAME_MAX_CHAR 255
#define GUEST_MIN_TICK_INTERVAL_IN_MS 25
#define GUEST_TICK_INTERVAL_IN_MS 300
#define GUEST_SCHEDULING_MAX_DELAY_IN_MS 800
#define GUEST_SCHEDULING_DELAY_DEBOUNCE_IN_MS 2000
#define GUEST_TIMERS_MAX 128
#define GUEST_MAX_TIMERS_PER_TICK GUEST_TIMERS_MAX / 4
#define GUEST_SELECT_OBJS_MAX 128
#define GUEST_MAX_SIGNALS 32
#define GUEST_MAX_CONNECTIONS 32
#define GUEST_CHILD_PROCESS_MAX 16
#define GUEST_APPLICATIONS_MAX 16
#define GUEST_HEARTBEAT_MIN_INTERVAL_MS 400
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_LIMITS_H__ */

View File

@ -0,0 +1,375 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_process.h"
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_signal.h"
#include "guest_config.h"
#include "guest_selobj.h"
#include "guest_timer.h"
#include "guest_channel.h"
#include "guest_stream.h"
#include "guest_unix.h"
#include "guest_script.h"
#include "guest_heartbeat.h"
#include "guest_child_death.h"
static sig_atomic_t _stay_on = 1;
static sig_atomic_t _reload = 0;
static sig_atomic_t _reap_children = 0;
// ****************************************************************************
// Guest Process - Reload
// ======================
static void guest_process_reload( void )
{
int result;
DPRINTFI("Reload signal handled.");
_reload = 0;
result = access("/tmp/guest_debug_debug", F_OK);
if (0 == result)
{
DPRINTFI("Debug log level set to debug.");
guest_debug_set_log_level(GUEST_DEBUG_LOG_LEVEL_DEBUG);
return;
}
result = access("/tmp/guest_debug_verbose", F_OK);
if (0 == result)
{
DPRINTFI("Debug log level set to verbose.");
guest_debug_set_log_level(GUEST_DEBUG_LOG_LEVEL_VERBOSE);
return;
}
DPRINTFI("Debug log level set to info.");
guest_debug_set_log_level(GUEST_DEBUG_LOG_LEVEL_INFO);
}
// ****************************************************************************
// ****************************************************************************
// Guest Process - Reap Children
// =============================
static void guest_process_reap_children( void )
{
pid_t pid;
int status;
if (_reap_children)
{
_reap_children = 0;
while (0 < (pid = waitpid(-1, &status, WNOHANG | WUNTRACED)))
{
if (WIFEXITED(status))
guest_child_death_save(pid, WEXITSTATUS(status));
else
guest_child_death_save(pid, GUEST_CHILD_FAILED);
}
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Process - Signal Handler
// ==============================
static void guest_process_signal_handler( int signum )
{
switch (signum)
{
case SIGINT:
case SIGTERM:
case SIGQUIT:
_stay_on = 0;
break;
case SIGHUP:
_reload = 1;
break;
case SIGCHLD:
_reap_children = 1;
break;
case SIGCONT:
DPRINTFD("Ignoring signal SIGCONT (%i).", signum);
break;
case SIGPIPE:
DPRINTFD("Ignoring signal SIGPIPE (%i).", signum);
break;
default:
DPRINTFD("Signal (%i) ignored.", signum);
break;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Process - Initialize
// ==========================
static GuestErrorT guest_process_initialize(
int argc, char *argv[], char *envp[] )
{
GuestConfigT* config = NULL;
GuestErrorT error;
error = guest_config_initialize(argc, argv, envp);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize configuration module, error=%s.",
guest_error_str(error));
guest_config_show_usage();
return error;
}
error = guest_selobj_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize selection object module, error=%s.",
guest_error_str(error));
return GUEST_FAILED;
}
error = guest_timer_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize timer module, error=%s.",
guest_error_str(error));
return GUEST_FAILED;
}
error = guest_child_death_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize child death module, error=%s.",
guest_error_str(error));
return GUEST_FAILED;
}
error = guest_unix_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize unix module, error=%s.",
guest_error_str(error));
return GUEST_FAILED;
}
error = guest_channel_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize channel module, error=%s.",
guest_error_str(error));
return GUEST_FAILED;
}
error = guest_stream_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize stream module, error=%s.",
guest_error_str(error));
return GUEST_FAILED;
}
error = guest_script_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize script module, error=%s.",
guest_error_str(error));
return GUEST_FAILED;
}
config = guest_config_get();
error = guest_heartbeat_initialize(config->comm_device);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize heartbeat module, error=%s.",
guest_error_str(error));
return error;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Process - Finalize
// ========================
static GuestErrorT guest_process_finalize( void )
{
GuestErrorT error;
error = guest_heartbeat_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize heartbeat module, error=%s.",
guest_error_str(error));
}
error = guest_script_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize script module, error=%s.",
guest_error_str(error));
}
error = guest_stream_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize stream module, error=%s.",
guest_error_str(error));
}
error = guest_channel_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize channel module, error=%s.",
guest_error_str(error));
}
error = guest_unix_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize unix module, error=%s.",
guest_error_str(error));
}
error = guest_child_death_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize child death module, error=%s.",
guest_error_str(error));
}
error = guest_timer_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize timer module, error=%s.",
guest_error_str(error));
}
error = guest_selobj_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finialize selection object module, error=%s.",
guest_error_str(error));
}
error = guest_config_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finialize configuration module, error=%s.",
guest_error_str(error));
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Process - Main
// ====================
GuestErrorT guest_process_main( int argc, char *argv[], char *envp[] )
{
unsigned int next_interval_in_ms;
GuestErrorT error;
DPRINTFI("Starting.");
guest_signal_register_handler(SIGINT, guest_process_signal_handler);
guest_signal_register_handler(SIGTERM, guest_process_signal_handler);
guest_signal_register_handler(SIGQUIT, guest_process_signal_handler);
guest_signal_register_handler(SIGHUP, guest_process_signal_handler);
guest_signal_register_handler(SIGCHLD, guest_process_signal_handler);
guest_signal_register_handler(SIGCONT, guest_process_signal_handler);
guest_signal_register_handler(SIGPIPE, guest_process_signal_handler);
guest_signal_ignore(SIGIO);
error = guest_process_initialize(argc, argv, envp);
if (GUEST_OKAY != error)
{
if (error != GUEST_NOT_CONFIGURED)
{
DPRINTFE("Failed initialize process restarting in 20 seconds,"
"error=%s.", guest_error_str(error));
sleep(20);
}
else {
DPRINTFI("Application is not configured, will be not restarted,"
" exit code=%s", guest_error_str(error));
}
return error;
}
DPRINTFI("Started.");
while (_stay_on)
{
next_interval_in_ms = guest_timer_schedule();
error = guest_selobj_dispatch(next_interval_in_ms);
if (GUEST_OKAY != error)
{
DPRINTFE("Selection object dispatch failed, error=%s.",
guest_error_str(error));
break;
}
guest_process_reap_children();
if (_reload)
guest_process_reload();
}
DPRINTFI("Shutting down.");
error = guest_process_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed finalize process, error=%s.",
guest_error_str(error) );
}
DPRINTFI("Shutdown complete.");
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_PROCESS_H__
#define __GUEST_PROCESS_H__
#include <sys/types.h>
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
// ****************************************************************************
// Guest Process - Main
// ====================
extern GuestErrorT guest_process_main( int argc, char *argv[], char *envp[] );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_PROCESS_H__ */

View File

@ -0,0 +1,410 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_script.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_selobj.h"
#include "guest_utils.h"
#include "guest_child_death.h"
#define GUEST_SCRIPT_SETUP_FAILURE -65535
typedef struct {
bool inuse;
int pid;
int fd;
int log_end_ptr;
char log_msg[256];
GuestScriptIdT script_id;
GuestScriptCallbackT callback;
} GuestScriptDataT;
static GuestScriptDataT _scripts[GUEST_CHILD_PROCESS_MAX];
// ****************************************************************************
// Guest Script - Abort
// ====================
void guest_script_abort( GuestScriptIdT script_id )
{
int result;
GuestScriptDataT* entry;
GuestErrorT error;
if (GUEST_SCRIPT_ID_INVALID == script_id)
return;
if (GUEST_CHILD_PROCESS_MAX <= script_id)
return;
entry = &(_scripts[script_id]);
if (entry->inuse)
{
if (-1 != entry->pid)
{
error = guest_child_death_deregister(entry->pid);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to deregister for child death %i, error=%s.",
entry->pid, guest_error_str(error));
}
result = kill(entry->pid, SIGKILL);
if (0 > result)
{
if (ESRCH == errno)
{
DPRINTFV("Script pid (%i) not running.", entry->pid);
} else {
DPRINTFE("Failed to send kill signal to script pid %i, "
"error=%s.", entry->pid, strerror(errno));
}
} else {
DPRINTFD("Script pid (%i) killed.", entry->pid);
}
}
if (-1 != entry->fd)
{
error = guest_selobj_deregister(entry->fd);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to deregister selection object %i, error=%s.",
entry->fd, guest_error_str(error));
}
close(entry->fd);
}
memset(entry, 0, sizeof(GuestScriptDataT));
entry->pid = -1;
entry->fd = -1;
entry->script_id = GUEST_SCRIPT_ID_INVALID;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Script - Dispatch
// =======================
static void guest_script_dispatch( int selobj )
{
int bytes_avail;
int result;
GuestScriptDataT* entry;
unsigned int script_i;
for (script_i=0; GUEST_CHILD_PROCESS_MAX > script_i; ++script_i)
{
entry = &(_scripts[script_i]);
if (entry->inuse)
if (selobj == entry->fd)
break;
}
if (GUEST_CHILD_PROCESS_MAX <= script_i)
return;
bytes_avail = sizeof(entry->log_msg) - entry->log_end_ptr;
result = read(selobj, &(entry->log_msg[entry->log_end_ptr]), bytes_avail);
if (0 > result)
{
if (EINTR == errno) {
DPRINTFD("Interrupted on read, error=%s.", strerror(errno));
return;
} else {
DPRINTFE("Failed to read, error=%s.", strerror(errno));
return;
}
} else if (0 == result) {
DPRINTFD("No message received.");
return;
} else {
DPRINTFD("Received message, msg_size=%i.", result);
entry->log_end_ptr += result;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Script - Callback
// =======================
static void guest_script_callback( pid_t pid, int exit_code )
{
GuestScriptDataT* entry;
unsigned int script_i;
for (script_i=0; GUEST_CHILD_PROCESS_MAX > script_i; ++script_i)
{
entry = &(_scripts[script_i]);
if (entry->inuse)
if ((int) pid == entry->pid)
break;
}
if (GUEST_CHILD_PROCESS_MAX <= script_i)
return;
DPRINTFD("PID %i exited with %i", (int) pid, exit_code);
if (NULL != entry->callback)
entry->callback(entry->script_id, exit_code, entry->log_msg);
guest_script_abort(entry->script_id);
}
// ****************************************************************************
// ****************************************************************************
// Guest Script - Invoke
// =====================
GuestErrorT guest_script_invoke(
char script[], char* script_argv[], GuestScriptCallbackT callback,
GuestScriptIdT* script_id )
{
int fd[2];
pid_t pid;
struct stat stat_data;
char* script_name = guest_utils_basename(script);
char* script_exec = script;
int result;
GuestScriptDataT* entry;
GuestSelObjCallbacksT callbacks;
GuestErrorT error;
*script_id = GUEST_SCRIPT_ID_INVALID;
unsigned int script_i;
for (script_i=1; GUEST_CHILD_PROCESS_MAX > script_i; ++script_i)
{
entry = &(_scripts[script_i]);
if (!entry->inuse)
break;
}
if (GUEST_CHILD_PROCESS_MAX <= script_i)
{
DPRINTFE("Failed to allocate script data.");
return GUEST_FAILED;
}
memset(entry, 0, sizeof(GuestScriptDataT));
entry->script_id = script_i;
entry->callback = callback;
entry->pid = -1;
entry->fd = -1;
result = access(script_exec, F_OK | X_OK);
if (0 > result)
{
DPRINTFE("Script %s access failed, error=%s.", script_exec,
strerror(errno));
return GUEST_FAILED;
}
result = stat(script_exec, &stat_data);
if (0 > result)
{
DPRINTFE("Script %s stat failed, error=%s.", script_exec,
strerror( errno ) );
return GUEST_FAILED;
}
if (0 >= stat_data.st_size)
{
DPRINTFE("Script %s has zero size.", script_exec);
return GUEST_FAILED;
}
result = pipe(fd);
if (0 > result)
{
DPRINTFE("Script %s pipe creation failed, error=%s.", script_exec,
strerror(errno));
return GUEST_FAILED;
}
result = fcntl(fd[0], F_SETFL, O_NONBLOCK);
if (0 > result)
{
DPRINTFE("Script %s pipe failed to make read end non-blocking, "
"error=%s.", script_exec, strerror(errno));
close(fd[0]);
close(fd[1]);
return GUEST_FAILED;
}
pid = fork();
if (0 > pid)
{
DPRINTFE("Failed to fork process for script %s, error=%s.",
script_exec, strerror(errno));
close(fd[0]);
close(fd[1]);
return GUEST_FAILED;
} else if (0 == pid) {
// Child process.
struct rlimit file_limits;
close(fd[0]); // close read end of pipe
result = setpgid(0, 0);
if (0 > result)
{
DPRINTFE("Failed to set process group id for script %s, "
"error=%s.", script_exec, strerror( errno ) );
exit(GUEST_SCRIPT_SETUP_FAILURE);
}
result = getrlimit(RLIMIT_NOFILE, &file_limits);
if (0 > result)
{
DPRINTFE("Failed to get file limits for script %s, error=%s.",
script_exec, strerror(errno));
exit(GUEST_SCRIPT_SETUP_FAILURE);
}
unsigned int fd_i;
for (fd_i=0; fd_i < file_limits.rlim_cur; ++fd_i)
if (fd_i != fd[1])
close(fd_i);
result = dup2(fd[1], 1); // make stdout into writable end of pipe
if (0 > result)
{
DPRINTFE("Failed to make stdout into writable end of pipe for "
"script %s, error=%s.", script_exec, strerror(errno));
exit(GUEST_SCRIPT_SETUP_FAILURE);
}
result = execv(script_exec, (char**) script_argv);
if (0 > result)
DPRINTFE("Failed to exec command for script %s, error=%s.",
script_exec, strerror(errno));
exit(GUEST_SCRIPT_SETUP_FAILURE);
} else {
// Parent process.
close(fd[1]); // close write end of pipe
entry->pid = (int) pid;
entry->fd = fd[0];
entry->inuse = true;
DPRINTFD("Child process %i created for script %s, script_id=%i.",
entry->pid, script_name, entry->script_id);
error = guest_child_death_register(pid, guest_script_callback);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to register for child death %i, error=%s.",
entry->pid, guest_error_str(error));
guest_script_abort(entry->script_id);
return error;
}
memset(&callbacks, 0, sizeof(callbacks));
callbacks.read_callback = guest_script_dispatch;
error = guest_selobj_register(entry->fd, &callbacks);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to register selection object %i, error=%s.",
entry->fd, guest_error_str(error));
guest_script_abort(entry->script_id);
return error;
}
*script_id = entry->script_id;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Script - Initialize
// =========================
GuestErrorT guest_script_initialize( void )
{
GuestScriptDataT* entry;
memset(_scripts, 0, sizeof(_scripts));
unsigned int script_i;
for (script_i=0; GUEST_CHILD_PROCESS_MAX > script_i; ++script_i)
{
entry = &(_scripts[script_i]);
entry->pid = -1;
entry->fd = -1;
entry->script_id = GUEST_SCRIPT_ID_INVALID;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Script - Finalize
// =======================
GuestErrorT guest_script_finalize( void )
{
GuestScriptDataT* entry;
unsigned int script_i;
for (script_i=0; GUEST_CHILD_PROCESS_MAX > script_i; ++script_i)
{
entry = &(_scripts[script_i]);
if (entry->inuse)
guest_script_abort(entry->script_id);
}
memset(_scripts, 0, sizeof(_scripts));
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_SCRIPT_H__
#define __GUEST_SCRIPT_H__
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GUEST_SCRIPT_ID_INVALID -1
typedef int GuestScriptIdT;
typedef void (*GuestScriptCallbackT)
(GuestScriptIdT script_id,int exit_code, char* log_msg);
// ****************************************************************************
// Guest Script - Abort
// ====================
extern void guest_script_abort( GuestScriptIdT script_id );
// ****************************************************************************
// ****************************************************************************
// Guest Script - Invoke
// =====================
extern GuestErrorT guest_script_invoke(
char script[], char* script_argv[], GuestScriptCallbackT callback,
GuestScriptIdT* script_id );
// ****************************************************************************
// ****************************************************************************
// Guest Script - Initialize
// =========================
extern GuestErrorT guest_script_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Script - Finalize
// =======================
extern GuestErrorT guest_script_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_SCRIPT_H__ */

View File

@ -0,0 +1,254 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_selobj.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_debug.h"
typedef struct {
bool inuse;
int selobj;
GuestSelObjCallbacksT callbacks;
} GuestSelObjEntryT;
typedef GuestSelObjEntryT GuestSelObjTableT[GUEST_SELECT_OBJS_MAX];
static int _num_poll_fds = 0;
static struct pollfd _poll_fds[GUEST_SELECT_OBJS_MAX];
static GuestSelObjTableT _select_objs;
// ****************************************************************************
// Guest Selection Object - Find Selection Object
// ==============================================
static GuestSelObjEntryT* guest_selobj_find( int selobj )
{
GuestSelObjEntryT* entry;
unsigned int entry_i;
for (entry_i=0; GUEST_SELECT_OBJS_MAX > entry_i; ++entry_i)
{
entry = &(_select_objs[entry_i]);
if (entry->inuse)
if (selobj == entry->selobj)
return entry;
}
return NULL;
}
// ****************************************************************************
// ****************************************************************************
// Guest Selection Object - Register
// =================================
GuestErrorT guest_selobj_register (
int selobj, GuestSelObjCallbacksT* callbacks )
{
GuestSelObjEntryT* entry;
entry = guest_selobj_find(selobj);
if (NULL == entry)
{
unsigned int entry_i;
for (entry_i=0; GUEST_SELECT_OBJS_MAX > entry_i; ++entry_i)
{
entry = &(_select_objs[entry_i]);
if (!entry->inuse )
{
entry->inuse = true;
entry->selobj = selobj;
memcpy(&(entry->callbacks), callbacks,
sizeof(GuestSelObjCallbacksT));
break;
}
}
// Rebuild polling file descriptors.
_num_poll_fds =0;
for (entry_i=0; GUEST_SELECT_OBJS_MAX > entry_i; ++entry_i)
{
entry = &(_select_objs[entry_i]);
if (entry->inuse)
{
memset(&_poll_fds[_num_poll_fds], 0, sizeof(struct pollfd));
_poll_fds[_num_poll_fds].fd = entry->selobj;
if (NULL != entry->callbacks.read_callback)
_poll_fds[_num_poll_fds].events |= POLLIN;
if (NULL != entry->callbacks.write_callback)
_poll_fds[_num_poll_fds].events |= POLLOUT;
if (NULL != entry->callbacks.hangup_callback)
_poll_fds[_num_poll_fds].events |= POLLHUP;
++_num_poll_fds;
}
}
} else {
memcpy(&(entry->callbacks), callbacks, sizeof(GuestSelObjCallbacksT));
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Selection Object - Deregister
// ===================================
GuestErrorT guest_selobj_deregister( int selobj )
{
GuestSelObjEntryT* entry;
entry = guest_selobj_find(selobj);
if (NULL != entry)
memset(entry, 0, sizeof(GuestSelObjEntryT));
// Rebuild polling file descriptors.
_num_poll_fds =0;
unsigned int entry_i;
for (entry_i=0; GUEST_SELECT_OBJS_MAX > entry_i; ++entry_i)
{
entry = &(_select_objs[entry_i]);
if (entry->inuse)
{
memset(&_poll_fds[_num_poll_fds], 0, sizeof(struct pollfd));
_poll_fds[_num_poll_fds].fd = entry->selobj;
if (NULL != entry->callbacks.read_callback)
_poll_fds[_num_poll_fds].events |= POLLIN;
if (NULL != entry->callbacks.write_callback)
_poll_fds[_num_poll_fds].events |= POLLOUT;
if (NULL != entry->callbacks.hangup_callback)
_poll_fds[_num_poll_fds].events |= POLLHUP;
++_num_poll_fds;
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Selection Object - Dispatch
// =================================
GuestErrorT guest_selobj_dispatch( unsigned int timeout_in_ms )
{
struct pollfd* poll_entry;
GuestSelObjEntryT* entry;
int result;
result = poll(_poll_fds, _num_poll_fds, timeout_in_ms);
if (0 > result)
{
if (errno == EINTR)
{
DPRINTFD("Interrupted by a signal.");
return GUEST_OKAY;
} else {
DPRINTFE("Select failed, error=%s.", strerror(errno));
return GUEST_FAILED;
}
} else if (0 == result) {
DPRINTFV("Nothing selected.");
return GUEST_OKAY;
}
unsigned int entry_i;
for (entry_i=0; _num_poll_fds > entry_i; ++entry_i)
{
poll_entry = &(_poll_fds[entry_i]);
entry = guest_selobj_find(poll_entry->fd);
if (NULL != entry)
{
if (0 != (poll_entry->revents & POLLIN))
if (NULL != entry->callbacks.read_callback)
{
DPRINTFD("Read on selection object %i", poll_entry->fd);
entry->callbacks.read_callback(entry->selobj);
}
if (0 != (poll_entry->revents & POLLOUT))
if (NULL != entry->callbacks.write_callback)
{
DPRINTFD("Write on selection object %i", poll_entry->fd);
entry->callbacks.write_callback(entry->selobj);
}
if (0 != (poll_entry->revents & POLLHUP))
if (NULL != entry->callbacks.hangup_callback)
{
DPRINTFD("Hangup on selection object %i", poll_entry->fd);
entry->callbacks.hangup_callback(entry->selobj);
}
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Selection Object - Initialize
// ===================================
GuestErrorT guest_selobj_initialize( void )
{
_num_poll_fds = 0;
memset(_poll_fds, 0, sizeof(_poll_fds));
memset(_select_objs, 0, sizeof(GuestSelObjTableT));
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Selection Object - Finalize
// =================================
GuestErrorT guest_selobj_finalize( void )
{
_num_poll_fds = 0;
memset(_poll_fds, 0, sizeof(_poll_fds));
memset(_select_objs, 0, sizeof(GuestSelObjTableT));
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_SELECTION_OBJECT_H__
#define __GUEST_SELECTION_OBJECT_H__
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*GuestSelObjReadCallbackT) (int selobj);
typedef void (*GuestSelObjWriteCallbackT) (int selobj);
typedef void (*GuestSelObjHangupCallbackT) (int selobj);
typedef struct {
GuestSelObjReadCallbackT read_callback;
GuestSelObjWriteCallbackT write_callback;
GuestSelObjHangupCallbackT hangup_callback;
} GuestSelObjCallbacksT;
// ****************************************************************************
// Guest Selection Object - Register
// =================================
extern GuestErrorT guest_selobj_register(
int selobj, GuestSelObjCallbacksT* callbacks );
// ****************************************************************************
// ****************************************************************************
// Guest Selection Object - Deregister
// ===================================
extern GuestErrorT guest_selobj_deregister( int selobj );
// ****************************************************************************
// ****************************************************************************
// Guest Selection Object - Dispatch
// =================================
extern GuestErrorT guest_selobj_dispatch( unsigned int timeout_in_ms );
// ****************************************************************************
// ****************************************************************************
// Guest Selection Object - Initialize
// ===================================
extern GuestErrorT guest_selobj_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Selection Object - Finalize
// =================================
extern GuestErrorT guest_selobj_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_SELECTION_OBJECT_H__ */

View File

@ -0,0 +1,129 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_signal.h"
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_debug.h"
typedef struct {
bool inuse;
int signum;
GuestSignalHandlerT handler;
} GuestSignalT;
static GuestSignalT _signal[GUEST_MAX_SIGNALS];
// ****************************************************************************
// Guest Signal - Map
// ==================
static GuestSignalT* guest_signal_map( int signum )
{
switch (signum)
{
case SIGINT: return &(_signal[0]);
case SIGTERM: return &(_signal[1]);
case SIGQUIT: return &(_signal[2]);
case SIGHUP: return &(_signal[3]);
case SIGCHLD: return &(_signal[4]);
case SIGCONT: return &(_signal[5]);
case SIGPIPE: return &(_signal[6]);
case SIGIO: return &(_signal[7]);
default:
DPRINTFE("Mapping for signal %i missing.", signum);
}
return NULL;
}
// ****************************************************************************
// ****************************************************************************
// Guest Signal - Handler
// ======================
static void guest_signal_handler( int signum )
{
GuestSignalT* entry;
DPRINTFD("Signal %i received.", signum);
entry = guest_signal_map(signum);
if (NULL != entry)
if (entry->inuse)
if (NULL != entry->handler)
entry->handler(signum);
}
// ****************************************************************************
// ****************************************************************************
// Guest Signal - Register Handler
// ===============================
void guest_signal_register_handler( int signum, GuestSignalHandlerT handler )
{
GuestSignalT* entry;
entry = guest_signal_map(signum);
if (NULL != entry)
{
entry->inuse = true;
entry->signum = signum;
entry->handler = handler;
signal(signum, guest_signal_handler);
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Signal - Deregister Handler
// =================================
void guest_signal_deregister_handler( int signum )
{
GuestSignalT* entry;
entry = guest_signal_map(signum);
if (NULL != entry)
{
memset(entry, 0, sizeof(GuestSignalT));
signal(signum, SIG_DFL);
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Signal - Ignore
// =====================
void guest_signal_ignore( int signum )
{
guest_signal_deregister_handler(signum);
signal(signum, SIG_IGN);
}
// ****************************************************************************

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_SIGNAL_H__
#define __GUEST_SIGNAL_H__
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*GuestSignalHandlerT) (int signum);
// ****************************************************************************
// Guest Signal - Register Handler
// ===============================
extern void guest_signal_register_handler(
int signum, GuestSignalHandlerT handler);
// ****************************************************************************
// ****************************************************************************
// Guest Signal - Deregister Handler
// =================================
extern void guest_signal_deregister_handler( int signum );
// ****************************************************************************
// ****************************************************************************
// Guest Signal - Ignore
// =====================
extern void guest_signal_ignore( int signum );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_SIGNAL_H__ */

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_stream.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "guest_types.h"
#include "guest_debug.h"
// ****************************************************************************
// Guest Stream - Get
// ==================
int guest_stream_get( GuestStreamT* stream )
{
char* byte_ptr;
int delimiter_i = 0;
if (stream->delimiter_size > stream->size)
return -1;
for (byte_ptr = stream->bytes; byte_ptr != stream->end_ptr; ++byte_ptr)
{
if (stream->delimiter[delimiter_i] == *byte_ptr)
{
++delimiter_i;
if (delimiter_i == stream->delimiter_size)
{
return (byte_ptr - stream->bytes);
}
} else {
delimiter_i = 0;
}
}
return -1;
}
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Get Next
// =======================
bool guest_stream_get_next( GuestStreamT* stream )
{
char* byte_ptr;
int delimiter_i = 0;
if (stream->delimiter_size > stream->size)
return false;
for (byte_ptr = stream->bytes; byte_ptr != stream->end_ptr; ++byte_ptr)
{
--stream->size;
if (stream->delimiter[delimiter_i] == *byte_ptr)
{
++delimiter_i;
if (delimiter_i == stream->delimiter_size)
{
byte_ptr -= (stream->delimiter_size-1);
stream->size += stream->delimiter_size;
memmove(stream->bytes, byte_ptr, stream->size);
stream->avail = stream->max_size - stream->size;
stream->end_ptr = stream->bytes + stream->size;
break;
}
} else {
delimiter_i = 0;
}
}
if (byte_ptr == stream->end_ptr)
{
// Empty the stream
memset(stream->bytes, 0, stream->max_size);
stream->avail = stream->max_size;
stream->size = 0;
stream->end_ptr = stream->bytes;
return false;
}
return true;
}
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Advance
// ======================
void guest_stream_advance( int adv, GuestStreamT* stream )
{
stream->size -= adv;
memmove(stream->bytes, stream->bytes+adv, stream->size);
stream->avail = stream->max_size - stream->size;
stream->end_ptr = stream->bytes + stream->size;
}
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Reset
// ====================
void guest_stream_reset( GuestStreamT* stream )
{
memset(stream->bytes, 0, stream->max_size);
stream->avail = stream->max_size;
stream->size = 0;
stream->end_ptr = stream->bytes;
}
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Setup
// ====================
GuestErrorT guest_stream_setup(
const char* delimiter, int delimiter_size, int stream_size,
GuestStreamT* stream )
{
stream->delimiter = malloc(delimiter_size);
if (NULL == stream->delimiter)
{
DPRINTFE("Failed to allocated delimiter storage, needed=%i.",
delimiter_size);
return GUEST_FAILED;
}
stream->bytes = malloc(stream_size);
if (NULL == stream->delimiter)
{
DPRINTFE("Failed to allocated stream storage, needed=%i.", stream_size);
free(stream->delimiter);
return GUEST_FAILED;
}
memcpy(stream->delimiter, delimiter, delimiter_size);
stream->delimiter_size = delimiter_size;
memset(stream->bytes, 0, stream_size);
stream->end_ptr = stream->bytes;
stream->avail = stream_size;
stream->size = 0;
stream->max_size = stream_size;
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Release
// ======================
GuestErrorT guest_stream_release( GuestStreamT* stream )
{
if (NULL != stream->delimiter)
free(stream->delimiter);
if (NULL != stream->bytes)
free(stream->bytes);
memset(stream, 0, sizeof(GuestStreamT));
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Initialize
// =========================
GuestErrorT guest_stream_initialize( void )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Finalize
// =======================
GuestErrorT guest_stream_finalize( void )
{
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_STREAM_H__
#define __GUEST_STREAM_H__
#include <stdbool.h>
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
char* delimiter;
int delimiter_size;
char* end_ptr;
char* bytes;
int avail;
int size;
int max_size;
} GuestStreamT;
// ****************************************************************************
// Guest Stream - Get
// ==================
extern int guest_stream_get( GuestStreamT* stream );
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Get Next
// =======================
extern bool guest_stream_get_next( GuestStreamT* stream );
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Advance
// ======================
extern void guest_stream_advance( int adv, GuestStreamT* stream );
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Reset
// ====================
extern void guest_stream_reset( GuestStreamT* stream );
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Setup
// ====================
extern GuestErrorT guest_stream_setup(
const char* delimiter, int delimiter_size, int stream_size,
GuestStreamT* stream );
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Release
// ======================
extern GuestErrorT guest_stream_release( GuestStreamT* stream );
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Initialize
// =========================
extern GuestErrorT guest_stream_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Stream - Finalize
// =======================
extern GuestErrorT guest_stream_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_STREAM_H__ */

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_time.h"
#include <time.h>
// ****************************************************************************
// Guest Time - Get
// ================
void guest_time_get( GuestTimeT* time )
{
#ifdef CLOCK_MONOTONIC_RAW
clock_gettime(CLOCK_MONOTONIC_RAW, time);
#else
clock_gettime(CLOCK_MONOTONIC, time);
#endif
}
// ****************************************************************************
// ****************************************************************************
// Guest Time - Get Elapsed Milliseconds
// =====================================
long guest_time_get_elapsed_ms( GuestTimeT* time )
{
GuestTimeT now;
guest_time_get(&now);
if (NULL == time)
return ((now.tv_sec*1000) + (now.tv_nsec/1000000));
else
return (guest_time_delta_in_ms(&now, time));
}
// ****************************************************************************
// ****************************************************************************
// Guest Time - Delta in Milliseconds
// ==================================
long guest_time_delta_in_ms( GuestTimeT* end, GuestTimeT* start )
{
long start_in_ms = (start->tv_sec*1000) + (start->tv_nsec/1000000);
long end_in_ms = (end->tv_sec*1000) + (end->tv_nsec/1000000);
return (end_in_ms - start_in_ms);
}
// ****************************************************************************
// ****************************************************************************
// Guest Time - Convert Milliseconds
// =================================
void guest_time_convert_ms( long ms, GuestTimeT* time )
{
time->tv_sec = ms / 1000;
time->tv_nsec = (ms % 1000) * 1000000;
}
// ****************************************************************************

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_TIME_H__
#define __GUEST_TIME_H__
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct timespec GuestTimeT;
// ****************************************************************************
// Guest Time - Get
// ================
extern void guest_time_get( GuestTimeT* time );
// ****************************************************************************
// ****************************************************************************
// Guest Time - Get Elapsed Milliseconds
// =====================================
extern long guest_time_get_elapsed_ms( GuestTimeT* time );
// ****************************************************************************
// ****************************************************************************
// Guest Time - Delta in Milliseconds
// ==================================
extern long guest_time_delta_in_ms( GuestTimeT* end, GuestTimeT* start );
// ****************************************************************************
// ****************************************************************************
// Guest Time - Convert Milliseconds
// =================================
extern void guest_time_convert_ms( long ms, GuestTimeT* time );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_TIME_H__ */

View File

@ -0,0 +1,323 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_timer.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_time.h"
typedef uint64_t GuestTimerInstanceT;
typedef struct {
bool inuse;
GuestTimerInstanceT timer_instance;
GuestTimerIdT timer_id;
unsigned int ms_interval;
GuestTimeT arm_timestamp;
GuestTimerCallbackT callback;
} GuestTimerEntryT;
typedef GuestTimerEntryT GuestTimerTableT[GUEST_TIMERS_MAX];
static bool _scheduling_on_time = true;
static GuestTimerInstanceT _timer_instance = 0;
static GuestTimerIdT _last_timer_dispatched = 0;
static GuestTimerTableT _timers;
static GuestTimeT _delay_timestamp;
static GuestTimeT _schedule_timestamp;
// ****************************************************************************
// Guest Timer - Scheduling On Time
// ================================
bool guest_timer_scheduling_on_time( void )
{
return _scheduling_on_time;
}
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Scheduling On Time Within
// =======================================
bool guest_timer_scheduling_on_time_within( unsigned int period_in_ms )
{
long ms_expired;
ms_expired = guest_time_get_elapsed_ms(&_delay_timestamp);
return (period_in_ms < ms_expired);
}
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Reset
// ===================
GuestErrorT guest_timer_reset( GuestTimerIdT timer_id )
{
GuestTimerEntryT* timer_entry = NULL;
if ((GUEST_TIMER_ID_INVALID == timer_id)||(GUEST_TIMERS_MAX <= timer_id))
return GUEST_FAILED;
timer_entry = &(_timers[timer_id]);
guest_time_get(&timer_entry->arm_timestamp);
DPRINTFD("Timer (%i) reset.", timer_entry->timer_id);
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Register
// ======================
GuestErrorT guest_timer_register(
unsigned int ms, GuestTimerCallbackT callback, GuestTimerIdT* timer_id )
{
GuestTimerEntryT* timer_entry;
*timer_id = GUEST_TIMER_ID_INVALID;
unsigned int timer_i;
for (timer_i=1; GUEST_TIMERS_MAX > timer_i; ++timer_i)
{
timer_entry = &(_timers[timer_i]);
if (timer_entry->inuse)
continue;
memset(timer_entry, 0, sizeof(GuestTimerEntryT));
timer_entry->inuse = true;
timer_entry->timer_instance = ++_timer_instance;
timer_entry->timer_id = timer_i;
timer_entry->ms_interval = ms;
guest_time_get(&timer_entry->arm_timestamp);
timer_entry->callback = callback;
break;
}
if (GUEST_TIMERS_MAX <= timer_i)
{
DPRINTFE("No space available to create timer, exiting...");
abort();
}
*timer_id = timer_i;
DPRINTFD("Created timer, id=%i.", timer_entry->timer_id);
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Deregister
// ========================
GuestErrorT guest_timer_deregister( GuestTimerIdT timer_id )
{
GuestTimerEntryT* timer_entry = NULL;
if ((GUEST_TIMER_ID_INVALID == timer_id)||(GUEST_TIMERS_MAX <= timer_id))
return GUEST_OKAY;
timer_entry = &(_timers[timer_id]);
timer_entry->inuse = false;
timer_entry->timer_instance = 0;
DPRINTFD("Cancelled timer, id=%i.", timer_entry->timer_id);
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Schedule Next
// ===========================
static unsigned int guest_timer_schedule_next( void )
{
GuestTimerEntryT* timer_entry;
long ms_expired, ms_remaining;
unsigned int interval_in_ms = GUEST_TICK_INTERVAL_IN_MS;
unsigned int timer_i;
for (timer_i=0; GUEST_TIMERS_MAX > timer_i; ++timer_i)
{
timer_entry = &(_timers[timer_i]);
if (timer_entry->inuse)
{
ms_expired = guest_time_get_elapsed_ms(&timer_entry->arm_timestamp);
if (ms_expired < timer_entry->ms_interval)
{
ms_remaining = timer_entry->ms_interval - ms_expired;
if (ms_remaining < interval_in_ms)
interval_in_ms = ms_remaining;
} else {
interval_in_ms = GUEST_MIN_TICK_INTERVAL_IN_MS;
break;
}
}
}
if (GUEST_MIN_TICK_INTERVAL_IN_MS > interval_in_ms)
interval_in_ms = GUEST_MIN_TICK_INTERVAL_IN_MS;
else if (GUEST_TICK_INTERVAL_IN_MS < interval_in_ms)
interval_in_ms = GUEST_TICK_INTERVAL_IN_MS;
DPRINTFV("Scheduling timers in %d ms.", interval_in_ms);
return interval_in_ms;
}
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Schedule
// ======================
unsigned int guest_timer_schedule( void )
{
long ms_expired;
GuestTimeT time_prev;
GuestTimerEntryT* timer_entry;
unsigned int total_timers_fired =0;
ms_expired = guest_time_get_elapsed_ms(&_schedule_timestamp);
if (ms_expired >= GUEST_SCHEDULING_MAX_DELAY_IN_MS)
{
if (_scheduling_on_time)
{
_scheduling_on_time = false;
DPRINTFI("Not scheduling on time, elapsed=%li ms.", ms_expired);
}
guest_time_get(&_delay_timestamp);
} else if (!_scheduling_on_time) {
ms_expired = guest_time_get_elapsed_ms(&_delay_timestamp);
if (GUEST_SCHEDULING_DELAY_DEBOUNCE_IN_MS < ms_expired)
{
_scheduling_on_time = true;
DPRINTFI("Now scheduling on time.");
}
}
guest_time_get(&time_prev);
unsigned int timer_i;
for (timer_i=_last_timer_dispatched; GUEST_TIMERS_MAX > timer_i; ++timer_i)
{
timer_entry = &(_timers[timer_i]);
if (timer_entry->inuse)
{
ms_expired = guest_time_get_elapsed_ms(&timer_entry->arm_timestamp);
if (ms_expired >= timer_entry->ms_interval)
{
bool rearm;
GuestTimerInstanceT timer_instance;
DPRINTFD("Timer %i fire, ms_interval=%d, ms_expired=%li.",
timer_entry->timer_id, timer_entry->ms_interval,
ms_expired);
timer_instance = timer_entry->timer_instance;
rearm = timer_entry->callback(timer_entry->timer_id);
if (timer_instance == timer_entry->timer_instance)
{
if (rearm)
{
guest_time_get(&timer_entry->arm_timestamp);
DPRINTFD("Timer (%i) rearmed.", timer_entry->timer_id);
} else {
timer_entry->inuse = 0;
DPRINTFD("Timer (%i) removed.", timer_entry->timer_id);
}
} else {
DPRINTFD("Timer (%i) instance changed since callback, "
"rearm=%d.", timer_entry->timer_id, (int) rearm);
}
if (GUEST_MAX_TIMERS_PER_TICK <= ++total_timers_fired)
{
DPRINTFD("Maximum timers per tick (%d) reached.",
GUEST_MAX_TIMERS_PER_TICK);
break;
}
}
}
}
if (GUEST_TIMERS_MAX <= timer_i)
_last_timer_dispatched = 0;
else
_last_timer_dispatched = timer_i;
ms_expired = guest_time_get_elapsed_ms(&time_prev);
if (ms_expired >= GUEST_SCHEDULING_MAX_DELAY_IN_MS)
{
_scheduling_on_time = false;
guest_time_get(&_delay_timestamp);
DPRINTFI("Not scheduling on time, timer callbacks are taking too "
"long to execute, elapsed_time=%li ms.", ms_expired);
} else {
DPRINTFV("Timer callbacks took %li ms.", ms_expired);
}
guest_time_get(&_schedule_timestamp);
return guest_timer_schedule_next();
}
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Initialize
// ========================
GuestErrorT guest_timer_initialize( void )
{
_scheduling_on_time = true;
_last_timer_dispatched = 0;
memset(_timers, 0, sizeof(GuestTimerTableT));
guest_time_get(&_schedule_timestamp);
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Finalize
// ======================
GuestErrorT guest_timer_finalize( void )
{
memset(_timers, 0, sizeof(GuestTimerTableT));
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_TIMER_H__
#define __GUEST_TIMER_H__
#include <stdbool.h>
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GUEST_TIMER_ID_INVALID -1
typedef int GuestTimerIdT;
typedef bool (*GuestTimerCallbackT) (GuestTimerIdT timer_id);
// ****************************************************************************
// Guest Timer - Scheduling On Time
// ================================
extern bool guest_timer_scheduling_on_time( void );
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Scheduling On Time Within
// =======================================
extern bool guest_timer_scheduling_on_time_within( unsigned int period_in_ms );
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Reset
// ===================
extern GuestErrorT guest_timer_reset( GuestTimerIdT timer_id );
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Register
// ======================
extern GuestErrorT guest_timer_register(
unsigned int ms, GuestTimerCallbackT callback, GuestTimerIdT* timer_id );
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Deregister
// ========================
extern GuestErrorT guest_timer_deregister( GuestTimerIdT timer_id );
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Schedule
// ======================
extern unsigned int guest_timer_schedule( void );
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Initialize
// ========================
extern GuestErrorT guest_timer_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Timer - Finalize
// ======================
extern GuestErrorT guest_timer_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_TIMER_H__ */

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_types.h"
// ****************************************************************************
// Guest Types - Error String
// ==========================
const char* guest_error_str( GuestErrorT error )
{
switch (error)
{
case GUEST_OKAY: return "OKAY";
case GUEST_FAILED: return "FAILED";
case GUEST_INTERRUPTED: return "INTERRUPTED";
case GUEST_TRY_AGAIN: return "TRY_AGAIN";
case GUEST_NOT_CONFIGURED: return "NOT_CONFIGURED";
default:
return "???";
}
}
// ****************************************************************************

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_TYPES_H__
#define __GUEST_TYPES_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
GUEST_OKAY,
GUEST_FAILED,
GUEST_INTERRUPTED,
GUEST_TRY_AGAIN,
GUEST_NOT_CONFIGURED=6,
} GuestErrorT;
// ****************************************************************************
// Guest Types - Error String
// ==========================
extern const char* guest_error_str( GuestErrorT error );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_TYPES_H__ */

View File

@ -0,0 +1,331 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_unix.h"
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_selobj.h"
GuestUnixConnectCallbackT _callback = NULL;
// ****************************************************************************
// Guest Unix - Connect
// ====================
GuestErrorT guest_unix_connect( int s, char* address )
{
struct sockaddr_un remote;
int len, result;
memset(&remote, 0, sizeof(remote));
remote.sun_family = AF_UNIX;
len = sizeof(remote.sun_family);
len += snprintf(remote.sun_path, sizeof(remote.sun_path), "%s", address);
result = connect(s, (struct sockaddr*) &remote, sizeof(remote));
if (0 > result)
{
DPRINTFE("Failed to connect to %s, error=%s.", address,
strerror(errno));
return GUEST_FAILED;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Dispatch Connection
// ================================
static void guest_unix_dispatch_connection( int s )
{
int sock;
struct sockaddr_un remote;
socklen_t len;
int result;
memset(&remote, 0, sizeof(remote));
len = sizeof(remote);
result = accept(s, (struct sockaddr*) &remote, &len);
if (0 > result)
{
DPRINTFE("Failed to accept on socket, error=%s.", strerror(errno));
return;
}
sock = result;
result = fcntl(sock, F_SETFD, FD_CLOEXEC);
if (0 > result)
{
DPRINTFE("Failed to set to close on exec, error=%s.", strerror(errno));
close(sock);
return;
}
result = fcntl(sock, F_GETFL);
if (0 > result)
{
DPRINTFE("Failed to get socket options, error=%s.", strerror(errno));
close(sock);
return;
}
result = fcntl(sock, F_SETFL, result | O_NONBLOCK);
if (0 > result)
{
DPRINTFE("Failed to set socket options, error=%s.", strerror(errno));
close(sock);
return;
}
if (NULL == _callback)
close(sock);
_callback(sock, remote.sun_path);
}
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Listen
// ===================
GuestErrorT guest_unix_listen(
int s, char* address, GuestUnixConnectCallbackT callback )
{
struct sockaddr_un local;
int len, result;
GuestSelObjCallbacksT callbacks;
GuestErrorT error;
memset(&local, 0, sizeof(local));
local.sun_family = AF_UNIX;
len = sizeof(local.sun_family);
len += snprintf(local.sun_path, sizeof(local.sun_path), "%s", address);
unlink(address);
result = bind(s, (struct sockaddr*) &local, len);
if (0 > result)
{
DPRINTFE("Failed to bind socket to address %s, error=%s.", address,
strerror(errno));
return GUEST_FAILED;
}
result = listen(s, GUEST_MAX_CONNECTIONS);
if (0 > result)
{
DPRINTFE("Failed to listen on %s, error=%s.", address,
strerror(errno));
return GUEST_FAILED;
}
memset(&callbacks, 0, sizeof(callbacks));
callbacks.read_callback = guest_unix_dispatch_connection;
error = guest_selobj_register(s, &callbacks);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to register selection object, error=%s.",
guest_error_str(error));
return error;
}
_callback = callback;
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Send
// =================
GuestErrorT guest_unix_send( int s, void* msg, int msg_size )
{
int result;
result = write(s, msg, msg_size);
if (0 > result)
{
DPRINTFE("Failed to write to socket, error=%s.", strerror(errno));
return GUEST_FAILED;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Receive
// ====================
GuestErrorT guest_unix_receive(
int s, void* msg_buf, int msg_buf_size, int* msg_size )
{
int result;
result = read(s, msg_buf, msg_buf_size);
if (0 > result)
{
if (EINTR == errno)
{
DPRINTFD("Interrupted on socket read, error=%s.", strerror(errno));
return GUEST_INTERRUPTED;
} else if (ECONNRESET == errno) {
DPRINTFD("Peer connection reset, error=%s.", strerror(errno));
*msg_size = 0;
return GUEST_OKAY;
} else {
DPRINTFE("Failed to read from socket, error=%s.", strerror(errno));
return GUEST_FAILED;
}
} else if (0 == result) {
DPRINTFD("No message received from socket.");
*msg_size = 0;
return GUEST_OKAY;
} else {
DPRINTFV("Received message, msg_size=%i.", result);
*msg_size = result;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Open
// =================
GuestErrorT guest_unix_open( int* s )
{
int sock;
int reuse_addr = 1;
struct sockaddr_un local;
int result;
*s = -1;
memset(&local, 0, sizeof(local));
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (0 > sock)
{
DPRINTFE("Failed to open socket, error=%s.", strerror(errno));
return GUEST_FAILED;
}
result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,
sizeof(reuse_addr));
if (0 > result)
{
DPRINTFE("Failed to set socket option (REUSEADDR), error=%s.",
strerror(errno));
close(sock);
return GUEST_FAILED;
}
result = fcntl(sock, F_SETFD, FD_CLOEXEC);
if (0 > result)
{
DPRINTFE("Failed to set to close on exec, error=%s.", strerror(errno));
close(sock);
return GUEST_FAILED;
}
result = fcntl(sock, F_GETFL);
if (0 > result)
{
DPRINTFE("Failed to get socket options, error=%s.", strerror(errno));
close(sock);
return GUEST_FAILED;
}
result = fcntl(sock, F_SETFL, result | O_NONBLOCK);
if (0 > result)
{
DPRINTFE("Failed to set socket options, error=%s.", strerror(errno));
close(sock);
return GUEST_FAILED;
}
*s = sock;
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Close
// ==================
GuestErrorT guest_unix_close( int s )
{
GuestErrorT error;
if (0 <= s)
{
error = guest_selobj_deregister(s);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to deregister selection object, error=%s.",
guest_error_str(error));
}
close(s);
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Initialize
// =======================
GuestErrorT guest_unix_initialize( void )
{
_callback = NULL;
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Finalize
// =====================
GuestErrorT guest_unix_finalize( void )
{
_callback = NULL;
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_UNIX_H__
#define __GUEST_UNIX_H__
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*GuestUnixConnectCallbackT) (int selobj, char* address);
// ****************************************************************************
// Guest Unix - Connect
// ====================
extern GuestErrorT guest_unix_connect( int s, char* address );
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Listen
// ===================
extern GuestErrorT guest_unix_listen(
int s, char* address, GuestUnixConnectCallbackT callback );
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Send
// =================
extern GuestErrorT guest_unix_send( int s, void* msg, int msg_size );
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Receive
// ====================
extern GuestErrorT guest_unix_receive(
int s, void* msg_buf, int msg_buf_size, int* msg_size );
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Open
// =================
extern GuestErrorT guest_unix_open( int* s );
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Close
// ==================
extern GuestErrorT guest_unix_close( int s );
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Initialize
// =======================
extern GuestErrorT guest_unix_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Unix - Finalize
// =====================
extern GuestErrorT guest_unix_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_UNIX_H__ */

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_utils.h"
#include "guest_debug.h"
#include <ctype.h>
#include <string.h>
// ****************************************************************************
// Guest Utilities - Trim
// ======================
char* guest_utils_trim( char* str, char* discard )
{
int len;
int max_len;
if (NULL == str)
return NULL;
// Remove leading characters
max_len = strlen(str);
for (len=0; max_len > len; ++len)
{
if (isspace(*str) || '\n' == *str)
++str;
else if ((NULL != discard) && (NULL != strchr(discard, *str)))
++str;
}
// Remove trailing characters
for (len=strlen(str)-1; 0 <= len; --len)
{
if (isspace(str[len]) || '\n' == str[len])
str[len] = '\0';
else if ((NULL != discard) && (NULL != strchr(discard, str[len])))
str[len] = '\0';
}
return str;
}
// ****************************************************************************
// ****************************************************************************
// Guest Utilities - Base Name
// ===========================
char* guest_utils_basename( char* str )
{
const char* basename = str;
while ('\0' != *str)
{
if (*str++ == '/')
basename = str;
}
return (char*) basename;
}
// ****************************************************************************
// ****************************************************************************
// Guest Utilities - Get JSON Value from Key
// return 0 if success, -1 if fail.
// =========================================
int guest_utils_json_get_value( struct json_object* jobj,
const char* key, void * value )
{
struct json_object *jobj_value;
if (!json_object_object_get_ex(jobj, key, &jobj_value))
{
DPRINTFE("failed to parse %s\n", key);
return -1;
}
enum json_type type = json_object_get_type(jobj_value);
switch(type)
{
case json_type_boolean:
*(unsigned int *)value = json_object_get_boolean(jobj_value);
break;
case json_type_int:
*(unsigned int *)value = json_object_get_int(jobj_value);
break;
case json_type_double:
*(double *)value = json_object_get_double(jobj_value);
break;
case json_type_string:
strcpy(value, json_object_get_string(jobj_value));
break;
default:
DPRINTFE("failed to parse %s, type %d is not supported\n", key, type);
return -1;
break;
}
return 0;
}
// ****************************************************************************

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_UTILITIES_H__
#define __GUEST_UTILITIES_H__
#include <json-c/json.h>
#ifdef __cplusplus
extern "C" {
#endif
#define STRINGIZE(str) #str
#define MAKE_STRING(str) STRINGIZE(str)
// ****************************************************************************
// Guest Utilities - Trim
// ======================
extern char* guest_utils_trim( char* str, char* discard );
// ****************************************************************************
// ****************************************************************************
// Guest Utilities - Base Name
// ===========================
extern char* guest_utils_basename( char* str );
// ****************************************************************************
// ****************************************************************************
// Guest Utilities - Get JSON Value from Key
// return 0 if success, -1 if fail.
// =========================================
extern int guest_utils_json_get_value( struct json_object* jobj,
const char* key, void * value );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_UTILITIES_H__ */

View File

@ -0,0 +1,62 @@
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SHELL = /bin/sh
## Configuration Directory Variables
prefix := /usr/local
exec_prefix := $(prefix)
sysconfdir := $(prefix)/etc
includedir := $(prefix)/include
libdir := $(exec_prefix)/lib
bindir := $(exec_prefix)/bin
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
ifndef BUILD_DIR
$(error BUILD_DIR undefined)
endif
.SUFFIXES:
.SUFFIXES: .c .o
.PHONY: build
heartbeat_C_INCLUDES := -I$(CURRENT_DIR) -I$(CURRENT_DIR)/../
heartbeat_C_INCLUDES += -I$(CURRENT_DIR)/../../../include
heartbeat_C_SRCS := $(wildcard *.c)
heartbeat_C_OBJS := ${heartbeat_C_SRCS:.c=.o}
CFLAGS = -g -O2 -Wall -Werror -Wformat -DSYSCONFDIR=$(sysconfdir)
%.o: %.c
$(CC) $(CFLAGS) $(heartbeat_C_INCLUDES) -c $< -o $(BUILD_DIR)/$@ -ljson-c
build: $(heartbeat_C_OBJS)

View File

@ -0,0 +1,318 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat.h"
#include <stdlib.h>
#include <string.h>
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_timer.h"
#include "guest_heartbeat_config.h"
#include "guest_heartbeat_msg.h"
#include "guest_heartbeat_fsm.h"
#include "guest_heartbeat_health_script.h"
#include "guest_heartbeat_event_script.h"
#include "guest_heartbeat_mgmt_api.h"
static GuestTimerIdT _release_timer_id = GUEST_TIMER_ID_INVALID;
// ****************************************************************************
// Guest Heartbeat - Release
// =========================
static bool guest_heartbeat_release(GuestTimerIdT timer_id)
{
GuestErrorT error;
error = guest_heartbeat_fsm_event_handler(GUEST_HEARTBEAT_FSM_RELEASE,
NULL);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to handle release event, error=%s.",
guest_error_str(error));
return true;
}
return false; // don't rearm
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat - Channel State Change
// ======================================
static void guest_heartbeat_channel_state_change( bool state )
{
GuestErrorT error;
if (state)
{
error = guest_heartbeat_fsm_event_handler(
GUEST_HEARTBEAT_FSM_CHANNEL_UP, NULL);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to handle channel up event, error=%s.",
guest_error_str(error));
return;
}
} else {
error = guest_heartbeat_fsm_event_handler(
GUEST_HEARTBEAT_FSM_CHANNEL_DOWN, NULL);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to handle channel down event, error=%s.",
guest_error_str(error));
return;
}
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat - Receive Init Ack Message
// ==========================================
static void guest_heartbeat_recv_init_ack_msg( int invocation_id )
{
void* event_data[] = {&invocation_id};
GuestErrorT error;
error = guest_heartbeat_fsm_event_handler(GUEST_HEARTBEAT_FSM_INIT_ACK,
event_data);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to handle heartbeat-init-ack event, error=%s.",
guest_error_str(error));
return;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat - Receive Challenge Message
// ===========================================
static void guest_heartbeat_recv_challenge_msg( void )
{
GuestErrorT error;
error = guest_heartbeat_fsm_event_handler(GUEST_HEARTBEAT_FSM_CHALLENGE,
NULL);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to handle heartbeat-challenge event, error=%s.",
guest_error_str(error));
return;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat - Receive Action Notify Message
// ===============================================
static void guest_heartbeat_recv_action_notify_msg(
int invocation_id, GuestHeartbeatEventT event,
GuestHeartbeatNotifyT notify, int timeout_ms)
{
void* event_data[] = {&invocation_id, &event, &notify, &timeout_ms};
GuestHeartbeatFsmStateT state = guest_heartbeat_fsm_get_state();
GuestErrorT error;
if (GUEST_HEARTBEAT_FSM_ENABLED_STATE == state)
{
error = guest_heartbeat_fsm_event_handler(GUEST_HEARTBEAT_FSM_ACTION,
event_data);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to handle action notify for event %s, error=%s.",
guest_heartbeat_event_str(event), guest_error_str(error));
return;
}
} else {
error = guest_heartbeat_msg_send_action_response(
invocation_id, event, notify,
GUEST_HEARTBEAT_VOTE_RESULT_COMPLETE, "");
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to send action response for event %s, error=%s.",
guest_heartbeat_event_str(event), guest_error_str(error));
return;
}
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat - Initialize
// ============================
GuestErrorT guest_heartbeat_initialize( char* comm_device )
{
GuestHeartbeatMsgCallbacksT callbacks;
GuestErrorT error;
_release_timer_id = GUEST_TIMER_ID_INVALID;
error = guest_heartbeat_config_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize heartbeat configuration, error=%s.",
guest_error_str(error));
return error;
}
memset(&callbacks, 0, sizeof(callbacks));
callbacks.channel_state_change = guest_heartbeat_channel_state_change;
callbacks.recv_init_ack = guest_heartbeat_recv_init_ack_msg;
callbacks.recv_challenge = guest_heartbeat_recv_challenge_msg;
callbacks.recv_action_notify = guest_heartbeat_recv_action_notify_msg;
error = guest_heartbeat_msg_initialize(comm_device, &callbacks);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize heartbeat messaging, error=%s.",
guest_error_str(error));
return error;
}
error = guest_heartbeat_fsm_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize heartbeat fsm, error=%s.",
guest_error_str(error));
return error;
}
error = guest_heartbeat_mgmt_api_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize heartbeat management api, error=%s.",
guest_error_str(error));
return error;
}
error = guest_heartbeat_health_script_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize heartbeat health script handling, "
"error=%s.", guest_error_str(error));
return error;
}
error = guest_heartbeat_event_script_initialize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to initialize heartbeat event script handling, "
"error=%s.", guest_error_str(error));
return error;
}
error = guest_timer_register(1000, guest_heartbeat_release,
&_release_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to start release timer, error=%s.",
guest_error_str(error));
return error;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat - Finalize
// ==========================
GuestErrorT guest_heartbeat_finalize( void )
{
GuestErrorT error;
error = guest_heartbeat_fsm_event_handler(GUEST_HEARTBEAT_FSM_SHUTDOWN,
NULL);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to handle shutdown event, error=%s.",
guest_error_str(error));
}
if (GUEST_TIMER_ID_INVALID != _release_timer_id)
{
error = guest_timer_deregister(_release_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel release timer, error=%s.",
guest_error_str(error));
}
_release_timer_id = GUEST_TIMER_ID_INVALID;
}
error = guest_heartbeat_event_script_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize heartbeat event script handling, "
"error=%s.", guest_error_str(error));
}
error = guest_heartbeat_health_script_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize heartbeat health script handling, "
"error=%s.", guest_error_str(error));
}
error = guest_heartbeat_mgmt_api_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize heartbeat management api, error=%s.",
guest_error_str(error));
}
error = guest_heartbeat_fsm_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize heartbeat fsm, error=%s.",
guest_error_str(error));
}
error = guest_heartbeat_msg_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize heartbeat messaging, error=%s.",
guest_error_str(error));
}
error = guest_heartbeat_config_finalize();
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to finalize heartbeat configuration, error=%s.",
guest_error_str(error));
}
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_H__
#define __GUEST_HEARTBEAT_H__
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
// ****************************************************************************
// Guest Heartbeat - Initialize
// ============================
extern GuestErrorT guest_heartbeat_initialize( char* comm_device );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat - Finalize
// ==========================
extern GuestErrorT guest_heartbeat_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_H__ */

View File

@ -0,0 +1,235 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_utils.h"
#include "guest_heartbeat_types.h"
#ifndef SYSCONFDIR
#define GUEST_HEARTBEAT_DEFAULT_CONFIG_FILE \
"/etc/guest-client/heartbeat/guest_heartbeat.conf"
#else
#define GUEST_HEARTBEAT_DEFAULT_CONFIG_FILE \
MAKE_STRING(SYSCONFDIR) "/guest-client/heartbeat/guest_heartbeat.conf"
#endif
#define GUEST_HEARTBEAT_DEFAULT_HEARTBEAT_INIT_RETRY_MS 5000
#define GUEST_HEARTBEAT_DEFAULT_HEARTBEAT_MIN_TIMEOUT_MS 5000
#define GUEST_HEARTBEAT_DEFAULT_HEARTBEAT_INTERVAL_MS 1000
#define GUEST_HEARTBEAT_DEFAULT_VOTE_MS 10000
#define GUEST_HEARTBEAT_DEFAULT_SHUTDOWN_MS 10000
#define GUEST_HEARTBEAT_DEFAULT_SUSPEND_MS 10000
#define GUEST_HEARTBEAT_DEFAULT_RESUME_MS 10000
#define GUEST_HEARTBEAT_DEFAULT_RESTART_MS 120000
static GuestHeartbeatConfigT _config;
// ****************************************************************************
// Guest Heartbeat Configuration - Read
// ====================================
static GuestErrorT guest_heartbeat_config_read( char filename[] )
{
char* s;
char* key;
char* value;
char delimiter[] = "=";
char discard[] = "\'\"";
char buf[1024];
FILE* fp;
fp = fopen(filename, "r");
if (NULL == fp)
{
DPRINTFE("Failed to open file %s.", filename);
return GUEST_FAILED;
}
while (NULL != (s = fgets(buf, sizeof(buf), fp)))
{
s = guest_utils_trim(s, NULL);
// Skip empty string and comments
if (('\0' == *s) || ('#' == *s))
continue;
key = strtok(s, delimiter);
value = strtok(NULL, delimiter);
key = guest_utils_trim(key, discard);
value = guest_utils_trim(value, discard);
if ((NULL != key) && (NULL != value))
{
if (0 == strcmp("HB_INIT_RETRY", key))
{
_config.heartbeat_init_retry_ms = atoi(value);
} else if (0 == strcmp("HB_MIN_TIMEOUT", key)) {
_config.heartbeat_min_timeout_ms = atoi(value);
} else if (0 == strcmp("HB_INTERVAL", key)) {
_config.heartbeat_interval_ms = atoi(value);
} else if (0 == strcmp("VOTE", key)) {
_config.vote_ms = atoi(value) * 1000;
} else if (0 == strcmp("SHUTDOWN_NOTICE", key)) {
_config.shutdown_notice_ms = atoi(value) * 1000;
} else if (0 == strcmp("SUSPEND_NOTICE", key)) {
_config.suspend_notice_ms = atoi(value) * 1000;
} else if (0 == strcmp("RESUME_NOTICE", key)) {
_config.resume_notice_ms = atoi(value) * 1000;
} else if (0 == strcmp("RESTART", key)) {
_config.restart_ms = atoi(value) * 1000;
} else if (0 == strcmp("CORRECTIVE_ACTION", key)) {
if (0 == strcmp("reboot", value))
{
_config.corrective_action = GUEST_HEARTBEAT_ACTION_REBOOT;
} else if (0 == strcmp("stop", value)) {
_config.corrective_action = GUEST_HEARTBEAT_ACTION_STOP;
} else if (0 == strcmp("log", value)) {
_config.corrective_action = GUEST_HEARTBEAT_ACTION_LOG;
}
} else if (0 == strcmp("HEALTH_CHECK_INTERVAL", key)) {
_config.health_check_interval_ms = atoi(value) * 1000;
} else if (0 == strcmp("HEALTH_CHECK_SCRIPT", key)) {
snprintf(_config.health_check_script,
sizeof(_config.health_check_script), "%s", value);
} else if (0 == strcmp("EVENT_NOTIFICATION_SCRIPT", key)) {
snprintf(_config.event_handling_script,
sizeof(_config.event_handling_script), "%s", value);
} else {
DPRINTFE("Unknown key %s in configuration file %s.", key,
filename);
}
}
}
fclose(fp);
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Configuration - Dump
// ====================================
static void guest_heartbeat_config_dump( void )
{
DPRINTFI("Guest-Client Heartbeat Configuration:");
DPRINTFI(" heartbeat-init-retry: %i ms", _config.heartbeat_init_retry_ms);
DPRINTFI(" heartbeat-interval: %i ms", _config.heartbeat_interval_ms);
DPRINTFI(" heartbeat-min-timeout: %i ms", _config.heartbeat_min_timeout_ms);
DPRINTFI(" vote: %i ms", _config.vote_ms);
DPRINTFI(" shutdown-notice: %i ms", _config.shutdown_notice_ms);
DPRINTFI(" suspend-notice: %i ms", _config.suspend_notice_ms);
DPRINTFI(" resume-notice: %i ms", _config.resume_notice_ms);
DPRINTFI(" restart: %i ms", _config.restart_ms);
DPRINTFI(" health-check-interval: %i ms", _config.health_check_interval_ms);
DPRINTFI(" health-check-script: %s", _config.health_check_script);
DPRINTFI(" event-handling-script: %s", _config.event_handling_script);
DPRINTFI(" corrective-action: %s",
guest_heartbeat_action_str(_config.corrective_action));
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Configuration - Get
// ===================================
GuestHeartbeatConfigT* guest_heartbeat_config_get( void )
{
return &_config;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Configuration - Initialize
// ==========================================
GuestErrorT guest_heartbeat_config_initialize( void )
{
GuestErrorT error;
memset(&_config, 0, sizeof(GuestHeartbeatConfigT));
_config.heartbeat_init_retry_ms = GUEST_HEARTBEAT_DEFAULT_HEARTBEAT_INIT_RETRY_MS;
_config.heartbeat_min_timeout_ms = GUEST_HEARTBEAT_DEFAULT_HEARTBEAT_MIN_TIMEOUT_MS;
_config.heartbeat_interval_ms = GUEST_HEARTBEAT_DEFAULT_HEARTBEAT_INTERVAL_MS;
_config.vote_ms = GUEST_HEARTBEAT_DEFAULT_VOTE_MS;
_config.shutdown_notice_ms = GUEST_HEARTBEAT_DEFAULT_SHUTDOWN_MS;
_config.suspend_notice_ms = GUEST_HEARTBEAT_DEFAULT_SUSPEND_MS;
_config.resume_notice_ms = GUEST_HEARTBEAT_DEFAULT_RESUME_MS;
_config.restart_ms = GUEST_HEARTBEAT_DEFAULT_RESTART_MS;
_config.corrective_action = GUEST_HEARTBEAT_ACTION_REBOOT;
error = guest_heartbeat_config_read(GUEST_HEARTBEAT_DEFAULT_CONFIG_FILE);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to read guest heartbeat configuration, error=%s.",
guest_error_str(error));
return error;
}
guest_heartbeat_config_dump();
if (GUEST_HEARTBEAT_MIN_INTERVAL_MS > _config.heartbeat_interval_ms)
{
DPRINTFE("Guest heartbeat interval configuration is less than %i ms.",
GUEST_HEARTBEAT_MIN_INTERVAL_MS);
return GUEST_FAILED;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Configuration - Finalize
// ========================================
GuestErrorT guest_heartbeat_config_finalize( void )
{
memset(&_config, 0, sizeof(GuestHeartbeatConfigT));
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HERATBEAT_CONFIGURATION_H__
#define __GUEST_HEARTBEAT_CONFIGURATION_H__
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_heartbeat_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int heartbeat_init_retry_ms;
int heartbeat_interval_ms;
int heartbeat_min_timeout_ms;
int vote_ms;
int shutdown_notice_ms;
int suspend_notice_ms;
int resume_notice_ms;
int restart_ms;
GuestHeartbeatActionT corrective_action;
int health_check_interval_ms;
char health_check_script[255];
char event_handling_script[255];
} GuestHeartbeatConfigT;
// ****************************************************************************
// Guest Heartbeat Configuration - Get
// ===================================
extern GuestHeartbeatConfigT* guest_heartbeat_config_get( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Configuration - Initialize
// ==========================================
extern GuestErrorT guest_heartbeat_config_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Configuration - Finalize
// ========================================
extern GuestErrorT guest_heartbeat_config_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_CONFIGURATION_H__ */

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat_disabled_state.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_timer.h"
#include "guest_heartbeat_fsm.h"
// ****************************************************************************
// Guest Heartbeat Disabled State - Enter
// ======================================
GuestErrorT guest_heartbeat_disabled_state_enter( void )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Exit
// =====================================
GuestErrorT guest_heartbeat_disabled_state_exit( void )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Transition
// ===========================================
GuestErrorT guest_heartbeat_disabled_state_transition(
GuestHeartbeatFsmStateT from_state )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Event Handler
// ==============================================
GuestErrorT guest_heartbeat_disabled_state_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] )
{
switch (event)
{
case GUEST_HEARTBEAT_FSM_RELEASE:
case GUEST_HEARTBEAT_FSM_INIT_ACK:
case GUEST_HEARTBEAT_FSM_CHALLENGE:
case GUEST_HEARTBEAT_FSM_CHALLENGE_TIMEOUT:
case GUEST_HEARTBEAT_FSM_CHANNEL_DOWN:
case GUEST_HEARTBEAT_FSM_ACTION:
// Ignore
break;
case GUEST_HEARTBEAT_FSM_CHANNEL_UP:
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_ENABLING_STATE);
break;
case GUEST_HEARTBEAT_FSM_SHUTDOWN:
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_INITIAL_STATE);
break;
default:
DPRINTFE("Ignoring event %s.",
guest_heartbeat_fsm_event_str(event));
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Initialize
// ===========================================
GuestErrorT guest_heartbeat_disabled_state_initialize( void )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Finalize
// =========================================
GuestErrorT guest_heartbeat_disabled_state_finalize( void )
{
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_DISABLED_STATE_H__
#define __GUEST_HEARTBEAT_DISABLED_STATE_H__
#include "guest_types.h"
#include "guest_heartbeat_fsm.h"
#ifdef __cplusplus
extern "C" {
#endif
// ****************************************************************************
// Guest Heartbeat Disabled State - Enter
// ======================================
extern GuestErrorT guest_heartbeat_disabled_state_enter( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Exit
// =====================================
extern GuestErrorT guest_heartbeat_disabled_state_exit( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Transition
// ===========================================
extern GuestErrorT guest_heartbeat_disabled_state_transition(
GuestHeartbeatFsmStateT from_state );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Event Handler
// ==============================================
extern GuestErrorT guest_heartbeat_disabled_state_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Initialize
// ===========================================
extern GuestErrorT guest_heartbeat_disabled_state_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Disabled State - Finalize
// =========================================
extern GuestErrorT guest_heartbeat_disabled_state_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_DISABLED_STATE_H__ */

View File

@ -0,0 +1,698 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat_enabled_state.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_time.h"
#include "guest_timer.h"
#include "guest_heartbeat_config.h"
#include "guest_heartbeat_msg.h"
#include "guest_heartbeat_fsm.h"
#include "guest_heartbeat_health_script.h"
#include "guest_heartbeat_event_script.h"
#include "guest_heartbeat_mgmt_api.h"
static bool _wait_application;
static bool _wait_script;
static int _action_invocation_id;
static GuestHeartbeatEventT _action_event;
static GuestHeartbeatNotifyT _action_notify;
GuestHeartbeatVoteResultT _vote_result;
static int _action_timeout_ms;
static GuestTimerIdT _health_check_timer_id = GUEST_TIMER_ID_INVALID;
static GuestTimerIdT _challenge_timeout_timer_id = GUEST_TIMER_ID_INVALID;
static GuestTimerIdT _action_timeout_timer_id = GUEST_TIMER_ID_INVALID;
static bool _health = true;
static char _health_log_msg[GUEST_HEARTBEAT_MAX_LOG_MSG_SIZE];
static char _action_log_msg[GUEST_HEARTBEAT_MAX_LOG_MSG_SIZE];
static GuestTimeT _last_time_reported;
static bool _last_health_reported = true;
static GuestHeartbeatActionT _last_corrective_action_reported;
// ****************************************************************************
// Guest Heartbeat Enabled State - Health Callback
// ===============================================
static void guest_heartbeat_enabled_state_health_callback(
bool health, char* log_msg )
{
if (_health && !health)
{
DPRINTFI("Transition from healthy to unhealthy, msg=%s.", log_msg);
} else if (!_health && health) {
DPRINTFI("Transition from unhealthy to healthy, msg=%s.", log_msg);
}
_health = health;
snprintf(_health_log_msg, sizeof(_health_log_msg), "%s", log_msg);
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Health Check
// ============================================
static bool guest_heartbeat_enabled_state_health_check(
GuestTimerIdT timer_id )
{
GuestHeartbeatConfigT* config = guest_heartbeat_config_get();
GuestErrorT error;
guest_heartbeat_health_script_abort();
if ('\0' != config->health_check_script[0])
{
error = guest_heartbeat_health_script_invoke(
config->health_check_script,
guest_heartbeat_enabled_state_health_callback);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to invoke health script %s.",
config->event_handling_script);
return true; // rearm
}
}
return true; // rearm
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Challenge Timeout
// =================================================
static bool guest_heartbeat_enabled_state_challenge_timeout(
GuestTimerIdT timer_id )
{
GuestHeartbeatConfigT* config = guest_heartbeat_config_get();
GuestErrorT error;
int max_heartbeat_delay;
max_heartbeat_delay = config->heartbeat_interval_ms*2;
if (max_heartbeat_delay < config->heartbeat_min_timeout_ms)
max_heartbeat_delay = config->heartbeat_min_timeout_ms;
if (!guest_timer_scheduling_on_time_within(max_heartbeat_delay))
{
DPRINTFE("Failed to receive a challenge in %i ms, but we are not "
"scheduling on time.", max_heartbeat_delay);
return true; // rearm
}
DPRINTFE("Failed to receive a challenge in %i ms.", max_heartbeat_delay);
error = guest_heartbeat_fsm_event_handler(GUEST_HEARTBEAT_FSM_CHALLENGE_TIMEOUT,
NULL);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to handle heartbeat-challenge-timeout event, "
"error=%s.", guest_error_str(error));
return true; // rearm
}
return true; // rearm
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Action Timeout
// ==============================================
static bool guest_heartbeat_enabled_state_action_timeout(
GuestTimerIdT timer_id )
{
char log_msg[GUEST_HEARTBEAT_MAX_LOG_MSG_SIZE];
GuestHeartbeatVoteResultT vote_result;
GuestErrorT error;
if (!guest_timer_scheduling_on_time_within(_action_timeout_ms))
{
DPRINTFE("Failed to receive action script response in %i ms, but we "
"are not scheduling on time.", _action_timeout_ms);
return true;
}
DPRINTFE("Failed to receive action responses in %i ms.",
_action_timeout_ms);
guest_heartbeat_mgmt_api_action_abort();
guest_heartbeat_event_script_abort();
if (((!_wait_application) || (!_wait_script)) &&
(GUEST_HEARTBEAT_VOTE_RESULT_REJECT == _vote_result))
{
vote_result = _vote_result;
snprintf(log_msg, sizeof(log_msg), "%s", _action_log_msg);
} else {
vote_result = GUEST_HEARTBEAT_VOTE_RESULT_TIMEOUT;
snprintf(log_msg, sizeof(log_msg), "Timeout on application and/or "
"script action responses.");
}
error = guest_heartbeat_msg_send_action_response(
_action_invocation_id, _action_event, _action_notify,
vote_result, log_msg);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to send action script response for event %s, "
"notification=%s, error=%s.",
guest_heartbeat_event_str(_action_event),
guest_heartbeat_notify_str(_action_notify),
guest_error_str(error));
}
_action_timeout_timer_id = GUEST_TIMER_ID_INVALID;
return false; // don't rearm
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Action Application Callback
// ===========================================================
static void guest_heartbeat_enabled_state_action_app_callback(
GuestHeartbeatEventT event, GuestHeartbeatNotifyT notify,
GuestHeartbeatVoteResultT vote_result, char* log_msg )
{
bool update;
GuestErrorT error;
DPRINTFI("Received action application response, event=%s, notify=%s, "
"vote-result=%s, msg=%s.", guest_heartbeat_event_str(event),
guest_heartbeat_notify_str(notify),
guest_heartbeat_vote_result_str(vote_result), log_msg);
_wait_application = false;
update = false;
switch (vote_result)
{
case GUEST_HEARTBEAT_VOTE_RESULT_REJECT:
update = true;
break;
case GUEST_HEARTBEAT_VOTE_RESULT_ACCEPT:
case GUEST_HEARTBEAT_VOTE_RESULT_COMPLETE:
if (GUEST_HEARTBEAT_VOTE_RESULT_REJECT != _vote_result)
update = true;
break;
default:
update = false;
break;
}
if (update)
{
_action_event = event;
_action_notify = notify;
_vote_result = vote_result;
snprintf(_action_log_msg, sizeof(_action_log_msg), "%s", log_msg);
}
if (!_wait_script)
{
error = guest_heartbeat_msg_send_action_response(
_action_invocation_id, _action_event, _action_notify,
_vote_result, _action_log_msg);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to send action response for event %s, "
"notification=%s, error=%s.",
guest_heartbeat_event_str(_action_event),
guest_heartbeat_notify_str(_action_notify),
guest_error_str(error));
}
if (GUEST_TIMER_ID_INVALID != _action_timeout_timer_id)
{
error = guest_timer_deregister(_action_timeout_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel action script timeout timer, "
"error=%s.", guest_error_str(error));
}
_action_timeout_timer_id = GUEST_TIMER_ID_INVALID;
}
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Action Script Callback
// ======================================================
static void guest_heartbeat_enabled_state_action_script_callback(
GuestHeartbeatEventT event, GuestHeartbeatNotifyT notify,
GuestHeartbeatVoteResultT vote_result, char* log_msg )
{
bool update;
GuestErrorT error;
DPRINTFI("Received event script response, event=%s, notify=%s, "
"vote-result=%s, msg=%s.", guest_heartbeat_event_str(event),
guest_heartbeat_notify_str(notify),
guest_heartbeat_vote_result_str(vote_result), log_msg);
_wait_script = false;
update = false;
switch (vote_result)
{
case GUEST_HEARTBEAT_VOTE_RESULT_REJECT:
update = true;
break;
case GUEST_HEARTBEAT_VOTE_RESULT_ACCEPT:
case GUEST_HEARTBEAT_VOTE_RESULT_COMPLETE:
if (GUEST_HEARTBEAT_VOTE_RESULT_REJECT != _vote_result)
update = true;
break;
default:
update = false;
break;
}
if (update)
{
_action_event = event;
_action_notify = notify;
_vote_result = vote_result;
snprintf(_action_log_msg, sizeof(_action_log_msg), "%s", log_msg);
}
if (!_wait_application)
{
error = guest_heartbeat_msg_send_action_response(
_action_invocation_id, _action_event, _action_notify,
_vote_result, _action_log_msg);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to send action response for event %s, "
"notification=%s, error=%s.",
guest_heartbeat_event_str(_action_event),
guest_heartbeat_notify_str(_action_notify),
guest_error_str(error));
}
if (GUEST_TIMER_ID_INVALID != _action_timeout_timer_id)
{
error = guest_timer_deregister(_action_timeout_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel action script timeout timer, "
"error=%s.", guest_error_str(error));
}
_action_timeout_timer_id = GUEST_TIMER_ID_INVALID;
}
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Enter
// =====================================
GuestErrorT guest_heartbeat_enabled_state_enter( void )
{
int heartbeat_timeout;
GuestHeartbeatConfigT* config = guest_heartbeat_config_get();
GuestErrorT error;
_health = true;
_last_health_reported = true;
heartbeat_timeout = config->heartbeat_interval_ms*2;
if (heartbeat_timeout < config->heartbeat_min_timeout_ms)
heartbeat_timeout = config->heartbeat_min_timeout_ms;
error = guest_timer_register(heartbeat_timeout,
guest_heartbeat_enabled_state_challenge_timeout,
&_challenge_timeout_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to start challenge timeout timer, error=%s.",
guest_error_str(error));
return error;
}
if ((0 != config->health_check_interval_ms) &&
('\0' != config->health_check_script[0]))
{
error = guest_timer_register(config->health_check_interval_ms,
guest_heartbeat_enabled_state_health_check,
&_health_check_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to start health check timer, error=%s.",
guest_error_str(error));
return error;
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Exit
// ====================================
GuestErrorT guest_heartbeat_enabled_state_exit( void )
{
GuestErrorT error;
if (GUEST_TIMER_ID_INVALID != _challenge_timeout_timer_id)
{
error = guest_timer_deregister(_challenge_timeout_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel challenge timeout timer, error=%s.",
guest_error_str(error));
}
_challenge_timeout_timer_id = GUEST_TIMER_ID_INVALID;
}
if (GUEST_TIMER_ID_INVALID != _health_check_timer_id)
{
error = guest_timer_deregister(_health_check_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel health check timer, error=%s.",
guest_error_str(error));
}
_health_check_timer_id = GUEST_TIMER_ID_INVALID;
}
if (GUEST_TIMER_ID_INVALID != _action_timeout_timer_id)
{
error = guest_timer_deregister(_action_timeout_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel action timeout timer, error=%s.",
guest_error_str(error));
}
_action_timeout_timer_id = GUEST_TIMER_ID_INVALID;
}
guest_heartbeat_health_script_abort();
guest_heartbeat_event_script_abort();
guest_heartbeat_mgmt_api_action_abort();
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Transition
// ==========================================
GuestErrorT guest_heartbeat_enabled_state_transition(
GuestHeartbeatFsmStateT from_state )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Event Handler
// =============================================
GuestErrorT guest_heartbeat_enabled_state_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] )
{
bool health = true;
GuestHeartbeatActionT corrective_action = GUEST_HEARTBEAT_ACTION_NONE;
char log_msg[GUEST_HEARTBEAT_MAX_LOG_MSG_SIZE];
GuestHeartbeatConfigT* config = guest_heartbeat_config_get();
GuestErrorT error;
switch (event) {
case GUEST_HEARTBEAT_FSM_RELEASE:
case GUEST_HEARTBEAT_FSM_INIT_ACK:
case GUEST_HEARTBEAT_FSM_CHANNEL_UP:
// Ignore.
break;
case GUEST_HEARTBEAT_FSM_CHANNEL_DOWN:
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_DISABLED_STATE);
break;
case GUEST_HEARTBEAT_FSM_CHALLENGE:
guest_timer_reset(_challenge_timeout_timer_id);
error = guest_heartbeat_mgmt_api_get_health(&health,
&corrective_action, log_msg,
GUEST_HEARTBEAT_MAX_LOG_MSG_SIZE);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to get application health, error=%s.",
guest_error_str(error));
}
if (health)
{
// Applications are healthy, use the last health script status.
health = _health;
corrective_action = config->corrective_action;
snprintf(log_msg, GUEST_HEARTBEAT_MAX_LOG_MSG_SIZE, "%s",
_health_log_msg);
} else if (!_health) {
// Applications are not healthy and the health script status
// is not healthy, need to merge the corrective action taken.
corrective_action = guest_heartbeat_merge_action(
corrective_action,
config->corrective_action);
if (corrective_action == config->corrective_action)
{
snprintf(log_msg, GUEST_HEARTBEAT_MAX_LOG_MSG_SIZE, "%s",
_health_log_msg);
}
}
if (!health)
{
if ((health == _last_health_reported) &&
(corrective_action == _last_corrective_action_reported) &&
(60000 > guest_time_get_elapsed_ms(&_last_time_reported)))
{
DPRINTFD("Unhealthy, already reported corrective action "
"%s, setting corrective action to none.",
guest_heartbeat_action_str(corrective_action));
// Don't keep asking for a corrective action to be taken
// over and over again at the heartbeat interval if it has
// already been reported.
corrective_action = GUEST_HEARTBEAT_ACTION_NONE;
} else {
_last_health_reported = health;
_last_corrective_action_reported = corrective_action;
memset(&_last_time_reported, 0, sizeof(_last_time_reported));
DPRINTFI("Unhealthy, reporting corrective action %s.",
guest_heartbeat_action_str(corrective_action));
}
} else {
_last_health_reported = true;
_last_corrective_action_reported = GUEST_HEARTBEAT_ACTION_NONE;
memset(&_last_time_reported, 0, sizeof(_last_time_reported));
}
error = guest_heartbeat_msg_send_challenge_response(health,
corrective_action, log_msg);
if (GUEST_OKAY == error)
{
if (GUEST_HEARTBEAT_ACTION_NONE != corrective_action)
{
guest_time_get(&_last_time_reported);
}
} else {
DPRINTFE("Failed to send challenge response, error=%s.",
guest_error_str(error));
return GUEST_OKAY;
}
break;
case GUEST_HEARTBEAT_FSM_CHALLENGE_TIMEOUT:
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_ENABLING_STATE);
break;
case GUEST_HEARTBEAT_FSM_ACTION:
guest_heartbeat_mgmt_api_action_abort();
guest_heartbeat_event_script_abort();
_wait_application = false;
_wait_script = false;
_action_invocation_id = *(int*) event_data[0];
_action_event = *(GuestHeartbeatEventT*) event_data[1];
_action_notify = *(GuestHeartbeatNotifyT*) event_data[2];
_action_timeout_ms = *(int*) event_data[3];
_vote_result = GUEST_HEARTBEAT_VOTE_RESULT_UNKNOWN;
error = guest_heartbeat_mgmt_api_action_notify(
_action_event, _action_notify, &_wait_application,
guest_heartbeat_enabled_state_action_app_callback);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to notify applications for event %s, "
"notification=%s.",
guest_heartbeat_event_str(_action_event),
guest_heartbeat_notify_str(_action_notify));
}
if ('\0' != config->event_handling_script[0])
{
DPRINTFI("Invoke event script %s for event %s, "
"notification=%s.", config->event_handling_script,
guest_heartbeat_event_str(_action_event),
guest_heartbeat_notify_str(_action_notify));
error = guest_heartbeat_event_script_invoke(
config->event_handling_script,
_action_event, _action_notify,
guest_heartbeat_enabled_state_action_script_callback);
if (GUEST_OKAY == error)
{
_wait_script = true;
} else {
DPRINTFE("Failed to invoke event script %s for event %s, "
"notification=%s.", config->event_handling_script,
guest_heartbeat_event_str(_action_event),
guest_heartbeat_notify_str(_action_notify));
}
}
if (_wait_application || _wait_script)
{
error = guest_timer_register(_action_timeout_ms,
guest_heartbeat_enabled_state_action_timeout,
&_action_timeout_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to start action timeout timer, error=%s.",
guest_error_str(error));
guest_heartbeat_mgmt_api_action_abort();
guest_heartbeat_event_script_abort();
return GUEST_OKAY;
}
} else {
error = guest_heartbeat_msg_send_action_response(
_action_invocation_id, _action_event,
_action_notify, GUEST_HEARTBEAT_VOTE_RESULT_COMPLETE,
"");
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to send action response for event %s, "
"notification=%s, error=%s.",
guest_heartbeat_event_str(_action_event),
guest_heartbeat_notify_str(_action_notify),
guest_error_str(error));
}
}
break;
case GUEST_HEARTBEAT_FSM_SHUTDOWN:
error = guest_heartbeat_msg_send_exit("Exiting...");
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to send exit, error=%s.",
guest_error_str(error));
}
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_INITIAL_STATE);
break;
default:
DPRINTFE("Ignoring event %s.",
guest_heartbeat_fsm_event_str(event));
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Initialize
// ==========================================
GuestErrorT guest_heartbeat_enabled_state_initialize( void )
{
_health = true;
_health_check_timer_id = GUEST_TIMER_ID_INVALID;
_challenge_timeout_timer_id = GUEST_TIMER_ID_INVALID;
_action_timeout_timer_id = GUEST_TIMER_ID_INVALID;
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Finalize
// ========================================
GuestErrorT guest_heartbeat_enabled_state_finalize( void )
{
GuestErrorT error;
if (GUEST_TIMER_ID_INVALID != _challenge_timeout_timer_id)
{
error = guest_timer_deregister(_challenge_timeout_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel challenge timeout timer, error=%s.",
guest_error_str(error));
}
_challenge_timeout_timer_id = GUEST_TIMER_ID_INVALID;
}
if (GUEST_TIMER_ID_INVALID != _health_check_timer_id)
{
error = guest_timer_deregister(_health_check_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel health check timer, error=%s.",
guest_error_str(error));
}
_health_check_timer_id = GUEST_TIMER_ID_INVALID;
}
if (GUEST_TIMER_ID_INVALID != _action_timeout_timer_id)
{
error = guest_timer_deregister(_action_timeout_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel action timeout timer, error=%s.",
guest_error_str(error));
}
_action_timeout_timer_id = GUEST_TIMER_ID_INVALID;
}
_health = false;
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_ENABLED_STATE_H__
#define __GUEST_HEARTBEAT_ENABLED_STATE_H__
#include "guest_types.h"
#include "guest_heartbeat_fsm.h"
#ifdef __cplusplus
extern "C" {
#endif
// ****************************************************************************
// Guest Heartbeat Enabled State - Enter
// =====================================
extern GuestErrorT guest_heartbeat_enabled_state_enter( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Exit
// ====================================
extern GuestErrorT guest_heartbeat_enabled_state_exit( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Transition
// ==========================================
extern GuestErrorT guest_heartbeat_enabled_state_transition(
GuestHeartbeatFsmStateT from_state );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Event Handler
// =============================================
extern GuestErrorT guest_heartbeat_enabled_state_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Initialize
// ==========================================
extern GuestErrorT guest_heartbeat_enabled_state_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabled State - Finalize
// ========================================
extern GuestErrorT guest_heartbeat_enabled_state_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_ENABLED_STATE_H__ */

View File

@ -0,0 +1,211 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat_enabling_state.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_timer.h"
#include "guest_config.h"
#include "guest_heartbeat_config.h"
#include "guest_heartbeat_msg.h"
#include "guest_heartbeat_fsm.h"
static int _prev_invocation_id;
static int _invocation_id;
static GuestTimerIdT _connect_timer_id = GUEST_TIMER_ID_INVALID;
// ****************************************************************************
// Guest Heartbeat Enabling State - Attempt Connect
// ================================================
static bool guest_heartbeat_enabling_state_connect( GuestTimerIdT timer_id )
{
GuestConfigT* cfg = guest_config_get();
GuestHeartbeatMsgInitDataT data;
GuestHeartbeatConfigT* config = guest_heartbeat_config_get();
GuestErrorT error;
_prev_invocation_id = _invocation_id;
_invocation_id = rand();
memset(&data, 0, sizeof(data));
snprintf(data.name, GUEST_NAME_MAX_CHAR, "%s", cfg->name);
data.heartbeat_interval_ms = config->heartbeat_interval_ms;
data.vote_ms = config->vote_ms;
data.shutdown_notice_ms = config->shutdown_notice_ms;
data.suspend_notice_ms = config->suspend_notice_ms;
data.resume_notice_ms = config->resume_notice_ms;
data.restart_ms = config->restart_ms;
data.corrective_action = config->corrective_action;
error = guest_heartbeat_msg_send_init(_invocation_id, &data);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to send heartbeat init message, error=%s.",
guest_error_str(error));
return true;
}
return true; // rearm
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Enter
// ======================================
GuestErrorT guest_heartbeat_enabling_state_enter( void )
{
GuestHeartbeatConfigT* config = guest_heartbeat_config_get();
GuestErrorT error;
error = guest_timer_register(config->heartbeat_init_retry_ms,
guest_heartbeat_enabling_state_connect,
&_connect_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to start connect timer, error=%s.",
guest_error_str(error));
return error;
}
guest_heartbeat_enabling_state_connect(_connect_timer_id);
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Exit
// =====================================
GuestErrorT guest_heartbeat_enabling_state_exit( void )
{
GuestErrorT error;
if (GUEST_TIMER_ID_INVALID != _connect_timer_id)
{
error = guest_timer_deregister(_connect_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel connect timer, error=%s.",
guest_error_str(error));
}
_connect_timer_id = GUEST_TIMER_ID_INVALID;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Transition
// ===========================================
GuestErrorT guest_heartbeat_enabling_state_transition(
GuestHeartbeatFsmStateT from_state )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Event Handler
// ==============================================
GuestErrorT guest_heartbeat_enabling_state_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] )
{
int invocation_id;
switch (event)
{
case GUEST_HEARTBEAT_FSM_RELEASE:
case GUEST_HEARTBEAT_FSM_CHALLENGE:
case GUEST_HEARTBEAT_FSM_CHALLENGE_TIMEOUT:
case GUEST_HEARTBEAT_FSM_ACTION:
case GUEST_HEARTBEAT_FSM_CHANNEL_UP:
// Ignore.
break;
case GUEST_HEARTBEAT_FSM_CHANNEL_DOWN:
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_DISABLED_STATE);
break;
case GUEST_HEARTBEAT_FSM_INIT_ACK:
invocation_id = *(int*) event_data[0];
if ((invocation_id == _invocation_id) ||
(invocation_id == _prev_invocation_id))
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_ENABLED_STATE);
break;
case GUEST_HEARTBEAT_FSM_SHUTDOWN:
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_INITIAL_STATE);
break;
default:
DPRINTFE("Ignoring event %s.",
guest_heartbeat_fsm_event_str(event));
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Initialize
// ===========================================
GuestErrorT guest_heartbeat_enabling_state_initialize( void )
{
_connect_timer_id = GUEST_TIMER_ID_INVALID;
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Finalize
// =========================================
GuestErrorT guest_heartbeat_enabling_state_finalize( void )
{
GuestErrorT error;
if (GUEST_TIMER_ID_INVALID != _connect_timer_id)
{
error = guest_timer_deregister(_connect_timer_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to cancel connect timer, error=%s.",
guest_error_str(error));
}
_connect_timer_id = GUEST_TIMER_ID_INVALID;
}
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_ENABLING_STATE_H__
#define __GUEST_HEARTBEAT_ENABLING_STATE_H__
#include "guest_types.h"
#include "guest_heartbeat_fsm.h"
#ifdef __cplusplus
extern "C" {
#endif
// ****************************************************************************
// Guest Heartbeat Enabling State - Enter
// ======================================
extern GuestErrorT guest_heartbeat_enabling_state_enter( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Exit
// =====================================
extern GuestErrorT guest_heartbeat_enabling_state_exit( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Transition
// ===========================================
extern GuestErrorT guest_heartbeat_enabling_state_transition(
GuestHeartbeatFsmStateT from_state );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Event Handler
// ==============================================
extern GuestErrorT guest_heartbeat_enabling_state_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Initialize
// ===========================================
extern GuestErrorT guest_heartbeat_enabling_state_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Enabling State - Finalize
// =========================================
extern GuestErrorT guest_heartbeat_enabling_state_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_ENABLING_STATE_H__ */

View File

@ -0,0 +1,204 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat_event_script.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_script.h"
#include "guest_heartbeat_types.h"
static GuestScriptIdT _script_id = GUEST_SCRIPT_ID_INVALID;
static GuestHeartbeatEventT _event;
static GuestHeartbeatNotifyT _notify;
static GuestHeartbeatEventScriptCallbackT _callback = NULL;
// ****************************************************************************
// Guest Heartbeat Event Script - Event Argument
// =============================================
const char* guest_heartbeat_event_script_event_arg( GuestHeartbeatEventT event )
{
switch (event)
{
case GUEST_HEARTBEAT_EVENT_STOP: return "stop";
case GUEST_HEARTBEAT_EVENT_REBOOT: return "reboot";
case GUEST_HEARTBEAT_EVENT_SUSPEND: return "suspend";
case GUEST_HEARTBEAT_EVENT_PAUSE: return "pause";
case GUEST_HEARTBEAT_EVENT_UNPAUSE: return "unpause";
case GUEST_HEARTBEAT_EVENT_RESUME: return "resume";
case GUEST_HEARTBEAT_EVENT_RESIZE_BEGIN: return "resize_begin";
case GUEST_HEARTBEAT_EVENT_RESIZE_END: return "resize_end";
case GUEST_HEARTBEAT_EVENT_LIVE_MIGRATE_BEGIN: return "live_migrate_begin";
case GUEST_HEARTBEAT_EVENT_LIVE_MIGRATE_END: return "live_migrate_end";
case GUEST_HEARTBEAT_EVENT_COLD_MIGRATE_BEGIN: return "cold_migrate_begin";
case GUEST_HEARTBEAT_EVENT_COLD_MIGRATE_END: return "cold_migrate_end";
default:
return NULL;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Event Script - Notify Argument
// ==============================================
const char* guest_heartbeat_event_script_notify_arg( GuestHeartbeatNotifyT notify )
{
switch (notify)
{
case GUEST_HEARTBEAT_NOTIFY_REVOCABLE: return "revocable";
case GUEST_HEARTBEAT_NOTIFY_IRREVOCABLE: return "irrevocable";
default:
return NULL;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Event Script - Abort
// ====================================
void guest_heartbeat_event_script_abort( void )
{
if (GUEST_SCRIPT_ID_INVALID != _script_id)
{
DPRINTFI("Aborting event script for event %s, notification=%s, "
"script_id=%i.", guest_heartbeat_event_str(_event),
guest_heartbeat_notify_str(_notify), _script_id);
guest_script_abort(_script_id);
_script_id = GUEST_SCRIPT_ID_INVALID;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Event Script - Callback
// =======================================
static void guest_heartbeat_event_script_callback(
GuestScriptIdT script_id, int exit_code, char* log_msg )
{
GuestHeartbeatVoteResultT vote_result;
if (script_id == _script_id)
{
switch (exit_code)
{
case 0:
vote_result = GUEST_HEARTBEAT_VOTE_RESULT_ACCEPT;
break;
case 1:
vote_result = GUEST_HEARTBEAT_VOTE_RESULT_REJECT;
break;
default:
vote_result = GUEST_HEARTBEAT_VOTE_RESULT_ERROR;
break;
}
if (NULL != _callback)
_callback(_event, _notify, vote_result, log_msg);
_script_id = GUEST_SCRIPT_ID_INVALID;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Event Script - Invoke
// =====================================
GuestErrorT guest_heartbeat_event_script_invoke(
char script[], GuestHeartbeatEventT event, GuestHeartbeatNotifyT notify,
GuestHeartbeatEventScriptCallbackT callback)
{
const char* event_arg = guest_heartbeat_event_script_event_arg(event);
const char* notify_arg = guest_heartbeat_event_script_notify_arg(notify);
const char* script_argv[] = {script, notify_arg, event_arg, NULL};
GuestErrorT error;
_event = event;
_notify = notify;
_callback = callback;
if (NULL == event_arg)
{
DPRINTFE("Event argument invalid, event=%s.",
guest_heartbeat_event_str(event));
return GUEST_FAILED;
}
if (NULL == notify_arg)
{
DPRINTFE("Notify argument invalid, event=%s.",
guest_heartbeat_notify_str(notify));
return GUEST_FAILED;
}
error = guest_script_invoke(script, (char**) script_argv,
guest_heartbeat_event_script_callback,
&_script_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to invoke script %s, error=%s.", script,
guest_error_str(error));
return error;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Event Script - Initialize
// =========================================
GuestErrorT guest_heartbeat_event_script_initialize( void )
{
_script_id = GUEST_SCRIPT_ID_INVALID;
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Event Script - Finalize
// =======================================
GuestErrorT guest_heartbeat_event_script_finalize( void )
{
guest_heartbeat_event_script_abort();
_script_id = GUEST_SCRIPT_ID_INVALID;
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_EVENT_SCRIPT_H__
#define __GUEST_HEARTBEAT_EVENT_SCRIPT_H__
#include "guest_types.h"
#include "guest_heartbeat_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*GuestHeartbeatEventScriptCallbackT)
(GuestHeartbeatEventT event, GuestHeartbeatNotifyT notify,
GuestHeartbeatVoteResultT vote_result, char* log_msg);
// ****************************************************************************
// Guest Heartbeat Event Script - Abort
// ====================================
extern void guest_heartbeat_event_script_abort( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Event Script - Invoke
// =====================================
extern GuestErrorT guest_heartbeat_event_script_invoke(
char script[], GuestHeartbeatEventT event, GuestHeartbeatNotifyT notify,
GuestHeartbeatEventScriptCallbackT callback );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Event Script - Initialize
// =========================================
extern GuestErrorT guest_heartbeat_event_script_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Event Script - Finalize
// =======================================
extern GuestErrorT guest_heartbeat_event_script_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_EVENT_SCRIPT_H__ */

View File

@ -0,0 +1,369 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat_fsm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_heartbeat_initial_state.h"
#include "guest_heartbeat_enabling_state.h"
#include "guest_heartbeat_enabled_state.h"
#include "guest_heartbeat_disabled_state.h"
typedef GuestErrorT (*GuestHeartbeatFsmStateEnterT) (void);
typedef GuestErrorT (*GuestHeartbeatFsmStateExitT) (void);
typedef GuestErrorT (*GuestHeartbeatFsmStateTransitionT)
(GuestHeartbeatFsmStateT from_state);
typedef GuestErrorT (*GuestHeartbeatFsmStateEventHandlerT)
(GuestHeartbeatFsmEventT event, void* event_data[]);
typedef GuestErrorT (*GuestHeartbeatFsmStateInitializeT) (void);
typedef GuestErrorT (*GuestHeartbeatFsmStateFinalizeT) (void);
typedef struct {
char name[40];
GuestHeartbeatFsmStateEnterT enter;
GuestHeartbeatFsmStateExitT exit;
GuestHeartbeatFsmStateTransitionT transition;
GuestHeartbeatFsmStateEventHandlerT event_handler;
GuestHeartbeatFsmStateInitializeT initialize;
GuestHeartbeatFsmStateFinalizeT finalize;
} GuestHeartbeatFsmStateEntryT;
static GuestHeartbeatFsmStateEntryT _states[GUEST_HEARTBEAT_FSM_MAX_STATES];
static GuestHeartbeatFsmStateT _current_state = GUEST_HEARTBEAT_FSM_INITIAL_STATE;
// ****************************************************************************
// Guest Heartbeat FSM - State String
// ==================================
const char* guest_heartbeat_fsm_state_str( GuestHeartbeatFsmStateT state )
{
if ((0 > state) || (GUEST_HEARTBEAT_FSM_MAX_STATES <= state))
{
return "state-???";
}
return _states[state].name;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Event String
// ==================================
const char* guest_heartbeat_fsm_event_str( GuestHeartbeatFsmEventT event )
{
switch (event)
{
case GUEST_HEARTBEAT_FSM_RELEASE: return "release";
case GUEST_HEARTBEAT_FSM_INIT_ACK: return "init-ack";
case GUEST_HEARTBEAT_FSM_CHALLENGE: return "challenge";
case GUEST_HEARTBEAT_FSM_CHALLENGE_TIMEOUT: return "challenge-timeout";
case GUEST_HEARTBEAT_FSM_ACTION: return "action";
case GUEST_HEARTBEAT_FSM_CHANNEL_UP: return "channel-up";
case GUEST_HEARTBEAT_FSM_CHANNEL_DOWN: return "channel-down";
case GUEST_HEARTBEAT_FSM_SHUTDOWN: return "shutdown";
default:
return "event-???";
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Get State
// ===============================
GuestHeartbeatFsmStateT guest_heartbeat_fsm_get_state( void )
{
return _current_state;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Enter State
// =================================
static GuestErrorT guest_heartbeat_fsm_enter_state( GuestHeartbeatFsmStateT state )
{
GuestHeartbeatFsmStateEntryT* entry = &(_states[state]);
GuestErrorT error;
if (NULL != entry->enter)
{
error = entry->enter();
if (GUEST_OKAY != error)
{
DPRINTFE("Unable to enter state %s, error=%s.", entry->name,
guest_error_str(error));
return error;
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Exit State
// ================================
static GuestErrorT guest_heartbeat_fsm_exit_state( GuestHeartbeatFsmStateT state )
{
GuestHeartbeatFsmStateEntryT* entry = &(_states[state]);
GuestErrorT error;
if (NULL != entry->exit)
{
error = entry->exit();
if (GUEST_OKAY != error)
{
DPRINTFE("Unable to exit state %s, error=%s.", entry->name,
guest_error_str(error));
return error;
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Transition State
// ======================================
static GuestErrorT guest_heartbeat_fsm_transition_state(
GuestHeartbeatFsmStateT from_state )
{
GuestHeartbeatFsmStateEntryT* entry = &(_states[from_state]);
GuestErrorT error;
if (NULL != entry->transition)
{
error = entry->transition(from_state);
if (GUEST_OKAY != error)
{
DPRINTFE("Unable to transition from state %s, error=%s.",
entry->name, guest_error_str(error));
return error;
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Set State
// ===============================
GuestErrorT guest_heartbeat_fsm_set_state( GuestHeartbeatFsmStateT state )
{
GuestHeartbeatFsmStateT prev_state = _current_state;
GuestHeartbeatFsmStateEntryT* prev_entry;
GuestHeartbeatFsmStateEntryT* entry;
GuestErrorT error, error2;
if ((0 > state) || (GUEST_HEARTBEAT_FSM_MAX_STATES <= state))
{
DPRINTFE("Invalid state %i given.", state);
return GUEST_FAILED;
}
prev_entry = &(_states[prev_state]);
entry = &(_states[state]);
error = guest_heartbeat_fsm_exit_state(prev_state);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to exit state %s, error=%s.", prev_entry->name,
guest_error_str(error));
return( error );
}
_current_state = state;
error = guest_heartbeat_fsm_transition_state(prev_state);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to transition to state %s, error=%s.",
prev_entry->name, guest_error_str(error));
goto STATE_CHANGE_TRANSITION_ERROR;
}
error = guest_heartbeat_fsm_enter_state(state);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to enter state %s, error=%s.", entry->name,
guest_error_str(error));
goto STATE_CHANGE_ENTER_ERROR;
}
return( GUEST_OKAY );
STATE_CHANGE_ENTER_ERROR:
error2 = guest_heartbeat_fsm_transition_state(state);
if (GUEST_OKAY != error2)
{
DPRINTFE("Failed to transition from state %s, error=%s.",
entry->name, guest_error_str(error2));
abort();
}
STATE_CHANGE_TRANSITION_ERROR:
_current_state = prev_state;
error2 = guest_heartbeat_fsm_enter_state(prev_state);
if (GUEST_OKAY != error2)
{
DPRINTFE("Failed to enter state (%s), error=%s.", prev_entry->name,
guest_error_str(error2));
abort();
}
return error;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Event Handler
// ===================================
GuestErrorT guest_heartbeat_fsm_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] )
{
GuestHeartbeatFsmStateT prev_state = _current_state;
GuestHeartbeatFsmStateEntryT* entry = &(_states[_current_state]);
GuestErrorT error;
if (NULL != entry->event_handler)
{
error = entry->event_handler(event, event_data);
if (GUEST_OKAY != error)
{
DPRINTFE("Unable to handle event %s in state %s, error=%s.",
guest_heartbeat_fsm_event_str(event), entry->name,
guest_error_str(error));
return error;
}
if (prev_state != _current_state)
{
DPRINTFI("Guest-Client heartbeat state change from %s to %s, "
"event=%s.", guest_heartbeat_fsm_state_str(prev_state),
guest_heartbeat_fsm_state_str(_current_state),
guest_heartbeat_fsm_event_str(event));
} else {
DPRINTFV("Guest-Client heartbeat no state change from %s, "
"event=%s.", guest_heartbeat_fsm_state_str(prev_state),
guest_heartbeat_fsm_event_str(event));
}
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Initialize
// ================================
GuestErrorT guest_heartbeat_fsm_initialize( void )
{
GuestHeartbeatFsmStateEntryT* entry;
memset(_states, 0, sizeof(_states));
_current_state = GUEST_HEARTBEAT_FSM_INITIAL_STATE;
// Initial State
entry = &(_states[GUEST_HEARTBEAT_FSM_INITIAL_STATE]);
snprintf(entry->name, sizeof(entry->name), "initial");
entry->enter = guest_heartbeat_initial_state_enter;
entry->exit = guest_heartbeat_initial_state_exit;
entry->transition = guest_heartbeat_initial_state_transition;
entry->event_handler = guest_heartbeat_initial_state_event_handler;
entry->initialize = guest_heartbeat_initial_state_initialize;
entry->finalize = guest_heartbeat_initial_state_finalize;
// Enabling State
entry = &(_states[GUEST_HEARTBEAT_FSM_ENABLING_STATE]);
snprintf(entry->name, sizeof(entry->name), "enabling");
entry->enter = guest_heartbeat_enabling_state_enter;
entry->exit = guest_heartbeat_enabling_state_exit;
entry->transition = guest_heartbeat_enabling_state_transition;
entry->event_handler = guest_heartbeat_enabling_state_event_handler;
entry->initialize = guest_heartbeat_enabling_state_initialize;
entry->finalize = guest_heartbeat_enabling_state_finalize;
// Enabled State
entry = &(_states[GUEST_HEARTBEAT_FSM_ENABLED_STATE]);
snprintf(entry->name, sizeof(entry->name), "enabled");
entry->enter = guest_heartbeat_enabled_state_enter;
entry->exit = guest_heartbeat_enabled_state_exit;
entry->transition = guest_heartbeat_enabled_state_transition;
entry->event_handler = guest_heartbeat_enabled_state_event_handler;
entry->initialize = guest_heartbeat_enabled_state_initialize;
entry->finalize = guest_heartbeat_enabled_state_finalize;
// Disabled State
entry = &(_states[GUEST_HEARTBEAT_FSM_DISABLED_STATE]);
snprintf(entry->name, sizeof(entry->name), "disabled");
entry->enter = guest_heartbeat_disabled_state_enter;
entry->exit = guest_heartbeat_disabled_state_exit;
entry->transition = guest_heartbeat_disabled_state_transition;
entry->event_handler = guest_heartbeat_disabled_state_event_handler;
entry->initialize = guest_heartbeat_disabled_state_initialize;
entry->finalize = guest_heartbeat_disabled_state_finalize;
unsigned int state_i;
for (state_i=0; GUEST_HEARTBEAT_FSM_MAX_STATES > state_i; ++state_i)
{
entry = &(_states[state_i]);
if (NULL != entry->initialize)
entry->initialize();
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Finalize
// ==============================
GuestErrorT guest_heartbeat_fsm_finalize( void )
{
GuestHeartbeatFsmStateEntryT* entry;
unsigned int state_i;
for (state_i=0; GUEST_HEARTBEAT_FSM_MAX_STATES > state_i; ++state_i)
{
entry = &(_states[state_i]);
if (NULL != entry->finalize)
entry->finalize();
}
memset(_states, 0, sizeof(_states));
_current_state = GUEST_HEARTBEAT_FSM_INITIAL_STATE;
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_FSM_H__
#define __GUEST_HEARTBEAT_FSM_H__
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
GUEST_HEARTBEAT_FSM_INITIAL_STATE,
GUEST_HEARTBEAT_FSM_ENABLING_STATE,
GUEST_HEARTBEAT_FSM_ENABLED_STATE,
GUEST_HEARTBEAT_FSM_DISABLED_STATE,
GUEST_HEARTBEAT_FSM_MAX_STATES
} GuestHeartbeatFsmStateT;
typedef enum {
GUEST_HEARTBEAT_FSM_RELEASE,
GUEST_HEARTBEAT_FSM_INIT_ACK,
GUEST_HEARTBEAT_FSM_CHALLENGE,
GUEST_HEARTBEAT_FSM_CHALLENGE_TIMEOUT,
GUEST_HEARTBEAT_FSM_ACTION,
GUEST_HEARTBEAT_FSM_CHANNEL_UP,
GUEST_HEARTBEAT_FSM_CHANNEL_DOWN,
GUEST_HEARTBEAT_FSM_SHUTDOWN,
GUEST_HEARTBEAT_FSM_MAX_EVENTS
} GuestHeartbeatFsmEventT;
// ****************************************************************************
// Guest Heartbeat FSM - State String
// ==================================
extern const char* guest_heartbeat_fsm_state_str( GuestHeartbeatFsmStateT state );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Event String
// ==================================
extern const char* guest_heartbeat_fsm_event_str( GuestHeartbeatFsmEventT event );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Get State
// ===============================
extern GuestHeartbeatFsmStateT guest_heartbeat_fsm_get_state( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Set State
// ===============================
extern GuestErrorT guest_heartbeat_fsm_set_state( GuestHeartbeatFsmStateT state );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Event Handler
// ===================================
extern GuestErrorT guest_heartbeat_fsm_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Initialize
// ================================
extern GuestErrorT guest_heartbeat_fsm_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat FSM - Finalize
// ==============================
extern GuestErrorT guest_heartbeat_fsm_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_FSM_H__ */

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat_health_script.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_script.h"
static GuestScriptIdT _script_id = GUEST_SCRIPT_ID_INVALID;
static GuestHeartbeatHealthScriptCallbackT _callback = NULL;
// ****************************************************************************
// Guest Heartbeat Health Script - Abort
// =====================================
void guest_heartbeat_health_script_abort( void )
{
if (GUEST_SCRIPT_ID_INVALID != _script_id)
{
DPRINTFI("Aborting health script, script_id=%i.", _script_id);
guest_script_abort(_script_id);
_script_id = GUEST_SCRIPT_ID_INVALID;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Health Script - Callback
// ========================================
static void guest_heartbeat_health_script_callback(
GuestScriptIdT script_id, int exit_code, char* log_msg )
{
if (script_id == _script_id)
{
if (NULL != _callback)
_callback((1 != exit_code), log_msg);
_script_id = GUEST_SCRIPT_ID_INVALID;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Health Script - Invoke
// ======================================
GuestErrorT guest_heartbeat_health_script_invoke(
char script[], GuestHeartbeatHealthScriptCallbackT callback)
{
const char* script_argv[] = {script, NULL};
GuestErrorT error;
_callback = callback;
error = guest_script_invoke(script, (char**) script_argv,
guest_heartbeat_health_script_callback,
&_script_id);
if (GUEST_OKAY != error)
{
DPRINTFE("Failed to invoke script %s, error=%s.", script,
guest_error_str(error));
return error;
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Health Script - Initialize
// ==========================================
GuestErrorT guest_heartbeat_health_script_initialize( void )
{
_script_id = GUEST_SCRIPT_ID_INVALID;
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Health Script - Finalize
// ========================================
GuestErrorT guest_heartbeat_health_script_finalize( void )
{
guest_heartbeat_health_script_abort();
_script_id = GUEST_SCRIPT_ID_INVALID;
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_HEALTH_SCRIPT_H__
#define __GUEST_HEARTBEAT_HEALTH_SCRIPT_H__
#include <stdbool.h>
#include "guest_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*GuestHeartbeatHealthScriptCallbackT) (bool health, char* log_msg);
// ****************************************************************************
// Guest Heartbeat Health Script - Abort
// =====================================
extern void guest_heartbeat_health_script_abort( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Health Script - Invoke
// ======================================
extern GuestErrorT guest_heartbeat_health_script_invoke(
char script[], GuestHeartbeatHealthScriptCallbackT callback );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Health Script - Initialize
// ==========================================
extern GuestErrorT guest_heartbeat_health_script_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Health Script - Finalize
// ========================================
extern GuestErrorT guest_heartbeat_health_script_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_HEALTH_SCRIPT_H__ */

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat_initial_state.h"
#include "guest_types.h"
#include "guest_debug.h"
#include "guest_heartbeat_fsm.h"
// ****************************************************************************
// Guest Heartbeat Initial State - Enter
// =====================================
GuestErrorT guest_heartbeat_initial_state_enter( void )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Exit
// ====================================
GuestErrorT guest_heartbeat_initial_state_exit( void )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Transition
// ==========================================
GuestErrorT guest_heartbeat_initial_state_transition(
GuestHeartbeatFsmStateT from_state )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Event Handler
// =============================================
GuestErrorT guest_heartbeat_initial_state_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] )
{
switch (event)
{
case GUEST_HEARTBEAT_FSM_INIT_ACK:
case GUEST_HEARTBEAT_FSM_CHALLENGE:
case GUEST_HEARTBEAT_FSM_CHALLENGE_TIMEOUT:
case GUEST_HEARTBEAT_FSM_ACTION:
case GUEST_HEARTBEAT_FSM_SHUTDOWN:
// Ignore
break;
case GUEST_HEARTBEAT_FSM_RELEASE:
case GUEST_HEARTBEAT_FSM_CHANNEL_UP:
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_ENABLING_STATE);
break;
case GUEST_HEARTBEAT_FSM_CHANNEL_DOWN:
guest_heartbeat_fsm_set_state(GUEST_HEARTBEAT_FSM_DISABLED_STATE);
break;
default:
DPRINTFV("Ignoring event %s.",
guest_heartbeat_fsm_event_str(event));
}
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Initialize
// ==========================================
GuestErrorT guest_heartbeat_initial_state_initialize( void )
{
return GUEST_OKAY;
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Finalize
// ========================================
GuestErrorT guest_heartbeat_initial_state_finalize( void )
{
return GUEST_OKAY;
}
// ****************************************************************************

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_INITIAL_STATE_H__
#define __GUEST_HEARTBEAT_INITIAL_STATE_H__
#include "guest_types.h"
#include "guest_heartbeat_fsm.h"
#ifdef __cplusplus
extern "C" {
#endif
// ****************************************************************************
// Guest Heartbeat Initial State - Enter
// =====================================
extern GuestErrorT guest_heartbeat_initial_state_enter( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Exit
// ====================================
extern GuestErrorT guest_heartbeat_initial_state_exit( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Transition
// ==========================================
extern GuestErrorT guest_heartbeat_initial_state_transition(
GuestHeartbeatFsmStateT from_state );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Event Handler
// =============================================
extern GuestErrorT guest_heartbeat_initial_state_event_handler(
GuestHeartbeatFsmEventT event, void* event_data[] );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Initialize
// ==========================================
extern GuestErrorT guest_heartbeat_initial_state_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Initial State - Finalize
// ========================================
extern GuestErrorT guest_heartbeat_initial_state_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_INITIAL_STATE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HERATBEAT_MGMT_API_H__
#define __GUEST_HEARTBEAT_MGMT_API_H__
#include <stdbool.h>
#include "guest_types.h"
#include "guest_heartbeat_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*GuestHeartbeatMgmtApiActionResponseT)
(GuestHeartbeatEventT event, GuestHeartbeatNotifyT notify,
GuestHeartbeatVoteResultT vote_result, char log_msg[]);
// ****************************************************************************
// Guest Heartbeat Management API - Get Health
// ===========================================
extern GuestErrorT guest_heartbeat_mgmt_api_get_health(
bool* health, GuestHeartbeatActionT* corrective_action, char log_msg[],
int log_msg_size );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Management API - Action Abort
// =============================================
extern void guest_heartbeat_mgmt_api_action_abort( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Management API - Action Notify
// ==============================================
extern GuestErrorT guest_heartbeat_mgmt_api_action_notify(
GuestHeartbeatEventT event, GuestHeartbeatNotifyT notify, bool* wait,
GuestHeartbeatMgmtApiActionResponseT callback );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Management API - Initialize
// ===========================================
extern GuestErrorT guest_heartbeat_mgmt_api_initialize( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Management API - Finalize
// =========================================
extern GuestErrorT guest_heartbeat_mgmt_api_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_MGMT_API_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HERATBEAT_MESSAGE_H__
#define __GUEST_HEARTBEAT_MESSAGE_H__
#include <stdint.h>
#include <stdbool.h>
#include "guest_limits.h"
#include "guest_types.h"
#include "guest_heartbeat_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GUEST_HEARTBEAT_MAX_LOG_MSG_SIZE 192
typedef struct {
char name[GUEST_NAME_MAX_CHAR];
unsigned int heartbeat_interval_ms;
unsigned int vote_ms;
unsigned int shutdown_notice_ms;
unsigned int suspend_notice_ms;
unsigned int resume_notice_ms;
unsigned int restart_ms;
GuestHeartbeatActionT corrective_action;
} GuestHeartbeatMsgInitDataT;
typedef void (*GuestHeartbeatMsgChannelStateChangeT) (bool state);
typedef void (*GuestHeartbeatMsgRecvInitT)
(int invocation_id, GuestHeartbeatMsgInitDataT* data);
typedef void (*GuestHeartbeatMsgRecvInitAckT) (int invocation_id);
typedef void (*GuestHeartbeatMsgRecvExitT) (char log_msg[]);
typedef void (*GuestHeartbeatMsgRecvChallengeT) (void);
typedef void (*GuestHeartbeatMsgRecvChallengeAckT)
(bool health, GuestHeartbeatActionT corrective_action, char log_msg[]);
typedef void (*GuestHeartbeatMsgRecvActionNotifyT)
(int invocation_id, GuestHeartbeatEventT event,
GuestHeartbeatNotifyT notify, int timeout_ms);
typedef void (*GuestHeartbeatMsgRecvActionResponseT)
(int invocation_id, GuestHeartbeatEventT event,
GuestHeartbeatNotifyT notify, GuestHeartbeatVoteResultT vote_result,
char log_msg[]);
typedef struct {
GuestHeartbeatMsgChannelStateChangeT channel_state_change;
GuestHeartbeatMsgRecvInitT recv_init;
GuestHeartbeatMsgRecvInitAckT recv_init_ack;
GuestHeartbeatMsgRecvExitT recv_exit;
GuestHeartbeatMsgRecvChallengeT recv_challenge;
GuestHeartbeatMsgRecvChallengeAckT recv_challenge_ack;
GuestHeartbeatMsgRecvActionNotifyT recv_action_notify;
GuestHeartbeatMsgRecvActionResponseT recv_action_response;
} GuestHeartbeatMsgCallbacksT;
// ****************************************************************************
// Guest Heartbeat Message - Send Init
// ===================================
extern GuestErrorT guest_heartbeat_msg_send_init( int invocation_id,
GuestHeartbeatMsgInitDataT* data );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Message - Send Init Ack
// =======================================
extern GuestErrorT guest_heartbeat_msg_send_init_ack( int invocation_id );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Message - Send Exit
// ===================================
extern GuestErrorT guest_heartbeat_msg_send_exit( char log_msg[] );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Message - Send Challenge
// ========================================
extern GuestErrorT guest_heartbeat_msg_send_challenge( void );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Message - Send Challenge Response
// =================================================
extern GuestErrorT guest_heartbeat_msg_send_challenge_response(
bool health, GuestHeartbeatActionT corrective_action, char log_msg[] );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Message - Send Action Notify
// ============================================
extern GuestErrorT guest_heartbeat_msg_send_action_notify(
int invocation_id, GuestHeartbeatEventT event,
GuestHeartbeatNotifyT notify, int timeout_ms );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Message - Send Action Response
// ==============================================
GuestErrorT guest_heartbeat_msg_send_action_response(
int invocation_id, GuestHeartbeatEventT event,
GuestHeartbeatNotifyT notify, GuestHeartbeatVoteResultT vote_result,
char log_msg[] );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Message - Initialize
// ====================================
extern GuestErrorT guest_heartbeat_msg_initialize(
char* comm_device, GuestHeartbeatMsgCallbacksT* callbacks );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Message - Finalize
// ==================================
extern GuestErrorT guest_heartbeat_msg_finalize( void );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_MESSAGE_H__ */

View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_MESSAGE_DEFINITIONS_H__
#define __GUEST_HEARTBEAT_MESSAGE_DEFINITIONS_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define GUEST_HEARTBEAT_MSG_VERSION_CURRENT 3
#define GUEST_HEARTBEAT_MSG_REVISION_CURRENT 1
#define GUEST_HEARTBEAT_MSG_HEALTHY "healthy"
#define GUEST_HEARTBEAT_MSG_UNHEALTHY "unhealthy"
// maximum size of a string value except instance name and log msg
#define GUEST_HEARTBEAT_MSG_MAX_VALUE_SIZE 32
// maximum size of instance name
#define GUEST_HEARTBEAT_MSG_MAX_NAME_SIZE 64
#define GUEST_HEARTBEAT_MSG_MAX_LOG_SIZE 224
#define GUEST_HEARTBEAT_MSG_MAX_MSG_SIZE 1056
#define GUEST_HEARTBEAT_MSG_MIN_MSG_SIZE 32
// *IMPORTANT NOTE* The keys defined here should match those defined in
// NFV-VIM in order to properly encode/decode REST-API messages.
// Keys for Repair Action
#define GUEST_HEARTBEAT_MSG_ACTION_UNKNOWN "unknown"
#define GUEST_HEARTBEAT_MSG_ACTION_NONE "none"
#define GUEST_HEARTBEAT_MSG_ACTION_REBOOT "reboot"
#define GUEST_HEARTBEAT_MSG_ACTION_STOP "stop"
#define GUEST_HEARTBEAT_MSG_ACTION_LOG "log"
// Keys for Event Type
#define GUEST_HEARTBEAT_MSG_EVENT_UNKNOWN "unknown"
#define GUEST_HEARTBEAT_MSG_EVENT_STOP "stop"
#define GUEST_HEARTBEAT_MSG_EVENT_REBOOT "reboot"
#define GUEST_HEARTBEAT_MSG_EVENT_SUSPEND "suspend"
#define GUEST_HEARTBEAT_MSG_EVENT_PAUSE "pause"
#define GUEST_HEARTBEAT_MSG_EVENT_UNPAUSE "unpause"
#define GUEST_HEARTBEAT_MSG_EVENT_RESUME "resume"
#define GUEST_HEARTBEAT_MSG_EVENT_RESIZE_BEGIN "resize_begin"
#define GUEST_HEARTBEAT_MSG_EVENT_RESIZE_END "resize_end"
#define GUEST_HEARTBEAT_MSG_EVENT_LIVE_MIGRATE_BEGIN "live_migrate_begin"
#define GUEST_HEARTBEAT_MSG_EVENT_LIVE_MIGRATE_END "live_migrate_end"
#define GUEST_HEARTBEAT_MSG_EVENT_COLD_MIGRATE_BEGIN "cold_migrate_begin"
#define GUEST_HEARTBEAT_MSG_EVENT_COLD_MIGRATE_END "cold_migrate_end"
// Keys for Notification Type
#define GUEST_HEARTBEAT_MSG_NOTIFY_UNKNOWN "unknown"
#define GUEST_HEARTBEAT_MSG_NOTIFY_REVOCABLE "revocable"
#define GUEST_HEARTBEAT_MSG_NOTIFY_IRREVOCABLE "irrevocable"
// Keys for Vote Result
#define GUEST_HEARTBEAT_MSG_VOTE_RESULT_UNKNOWN "unknown"
#define GUEST_HEARTBEAT_MSG_VOTE_RESULT_ACCEPT "accept"
#define GUEST_HEARTBEAT_MSG_VOTE_RESULT_REJECT "reject"
#define GUEST_HEARTBEAT_MSG_VOTE_RESULT_COMPLETE "complete"
#define GUEST_HEARTBEAT_MSG_VOTE_RESULT_TIMEOUT "timeout"
#define GUEST_HEARTBEAT_MSG_VOTE_RESULT_ERROR "error"
// client registers for heartbeat service
#define GUEST_HEARTBEAT_MSG_INIT "init"
// server accepts new client
#define GUEST_HEARTBEAT_MSG_INIT_ACK "init_ack"
// client intends to exit
#define GUEST_HEARTBEAT_MSG_EXIT "exit"
// server challenges client, are you healthy
#define GUEST_HEARTBEAT_MSG_CHALLENGE "challenge"
// client response to challenge
#define GUEST_HEARTBEAT_MSG_CHALLENGE_RESPONSE "challenge_response"
// server proposes/demands action
#define GUEST_HEARTBEAT_MSG_ACTION_NOTIFY "action_notify"
// client votes on action, or indicates action complete
#define GUEST_HEARTBEAT_MSG_ACTION_RESPONSE "action_response"
// server notify client of failure in processing client message
#define GUEST_HEARTBEAT_MSG_NACK "nack"
// Keys for messages between Host and Guest
#define GUEST_HEARTBEAT_MSG_VERSION "version"
#define GUEST_HEARTBEAT_MSG_REVISION "revision"
#define GUEST_HEARTBEAT_MSG_MSG_TYPE "msg_type"
#define GUEST_HEARTBEAT_MSG_SEQUENCE "sequence"
#define GUEST_HEARTBEAT_MSG_INVOCATION_ID "invocation_id"
#define GUEST_HEARTBEAT_MSG_NAME "name"
#define GUEST_HEARTBEAT_MSG_HEARTBEAT_INTERVAL_MS "heartbeat_interval_ms"
#define GUEST_HEARTBEAT_MSG_VOTE_SECS "vote_secs"
#define GUEST_HEARTBEAT_MSG_SHUTDOWN_NOTICE_SECS "shutdown_notice_secs"
#define GUEST_HEARTBEAT_MSG_SUSPEND_NOTICE_SECS "suspend_notice_secs"
#define GUEST_HEARTBEAT_MSG_RESUME_NOTICE_SECS "resume_notice_secs"
#define GUEST_HEARTBEAT_MSG_RESTART_SECS "restart_secs"
#define GUEST_HEARTBEAT_MSG_CORRECTIVE_ACTION "corrective_action"
#define GUEST_HEARTBEAT_MSG_LOG_MSG "log_msg"
#define GUEST_HEARTBEAT_MSG_HEARTBEAT_CHALLENGE "heartbeat_challenge"
#define GUEST_HEARTBEAT_MSG_HEARTBEAT_RESPONSE "heartbeat_response"
#define GUEST_HEARTBEAT_MSG_HEARTBEAT_HEALTH "heartbeat_health"
#define GUEST_HEARTBEAT_MSG_EVENT_TYPE "event_type"
#define GUEST_HEARTBEAT_MSG_NOTIFICATION_TYPE "notification_type"
#define GUEST_HEARTBEAT_MSG_TIMEOUT_MS "timeout_ms"
#define GUEST_HEARTBEAT_MSG_VOTE_RESULT "vote_result"
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_MESSAGE_DEFINITIONS_H__ */

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guest_heartbeat_types.h"
// ****************************************************************************
// Guest Heartbeat Types - Action String
// =====================================
const char* guest_heartbeat_action_str( GuestHeartbeatActionT action )
{
switch (action)
{
case GUEST_HEARTBEAT_ACTION_NONE: return "none";
case GUEST_HEARTBEAT_ACTION_REBOOT: return "reboot";
case GUEST_HEARTBEAT_ACTION_STOP: return "stop";
case GUEST_HEARTBEAT_ACTION_LOG: return "log";
default:
return "action-???";
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Types - Event String
// ====================================
const char* guest_heartbeat_event_str( GuestHeartbeatEventT event )
{
switch (event)
{
case GUEST_HEARTBEAT_EVENT_STOP: return "stop";
case GUEST_HEARTBEAT_EVENT_REBOOT: return "reboot";
case GUEST_HEARTBEAT_EVENT_SUSPEND: return "suspend";
case GUEST_HEARTBEAT_EVENT_PAUSE: return "pause";
case GUEST_HEARTBEAT_EVENT_UNPAUSE: return "unpause";
case GUEST_HEARTBEAT_EVENT_RESUME: return "resume";
case GUEST_HEARTBEAT_EVENT_RESIZE_BEGIN: return "resize-begin";
case GUEST_HEARTBEAT_EVENT_RESIZE_END: return "resize-end";
case GUEST_HEARTBEAT_EVENT_LIVE_MIGRATE_BEGIN: return "live-migrate-begin";
case GUEST_HEARTBEAT_EVENT_LIVE_MIGRATE_END: return "live-migrate-end";
case GUEST_HEARTBEAT_EVENT_COLD_MIGRATE_BEGIN: return "cold-migrate-begin";
case GUEST_HEARTBEAT_EVENT_COLD_MIGRATE_END: return "cold-migrate-end";
default:
return "event-???";
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Types - Notify String
// =====================================
const char* guest_heartbeat_notify_str( GuestHeartbeatNotifyT notify )
{
switch (notify)
{
case GUEST_HEARTBEAT_NOTIFY_REVOCABLE: return "revocable";
case GUEST_HEARTBEAT_NOTIFY_IRREVOCABLE: return "irrevocable";
default:
return "notify-???";
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Types - Vote Result String
// ==========================================
const char* guest_heartbeat_vote_result_str( GuestHeartbeatVoteResultT result )
{
switch (result)
{
case GUEST_HEARTBEAT_VOTE_RESULT_ACCEPT: return "accept";
case GUEST_HEARTBEAT_VOTE_RESULT_REJECT: return "reject";
case GUEST_HEARTBEAT_VOTE_RESULT_COMPLETE: return "complete";
case GUEST_HEARTBEAT_VOTE_RESULT_TIMEOUT: return "timeout";
case GUEST_HEARTBEAT_VOTE_RESULT_ERROR: return "error";
default:
return "vote-???";
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Types - Merge Action
// ====================================
GuestHeartbeatActionT guest_heartbeat_merge_action(
GuestHeartbeatActionT current_action, GuestHeartbeatActionT new_action )
{
switch (new_action)
{
case GUEST_HEARTBEAT_ACTION_STOP:
return new_action;
case GUEST_HEARTBEAT_ACTION_REBOOT:
if (GUEST_HEARTBEAT_ACTION_STOP != current_action)
return new_action;
return current_action;
case GUEST_HEARTBEAT_ACTION_LOG:
if ((GUEST_HEARTBEAT_ACTION_STOP != current_action) &&
(GUEST_HEARTBEAT_ACTION_REBOOT != current_action))
return new_action;
return current_action;
default:
return current_action;
}
}
// ****************************************************************************

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GUEST_HEARTBEAT_TYPES_H__
#define __GUEST_HEARTBEAT_TYPES_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
GUEST_HEARTBEAT_ACTION_UNKNOWN,
GUEST_HEARTBEAT_ACTION_NONE,
GUEST_HEARTBEAT_ACTION_REBOOT,
GUEST_HEARTBEAT_ACTION_STOP,
GUEST_HEARTBEAT_ACTION_LOG,
GUEST_HEARTBEAT_ACTION_MAX,
} GuestHeartbeatActionT;
typedef enum {
GUEST_HEARTBEAT_EVENT_UNKNOWN,
GUEST_HEARTBEAT_EVENT_STOP,
GUEST_HEARTBEAT_EVENT_REBOOT,
GUEST_HEARTBEAT_EVENT_SUSPEND,
GUEST_HEARTBEAT_EVENT_PAUSE,
GUEST_HEARTBEAT_EVENT_UNPAUSE,
GUEST_HEARTBEAT_EVENT_RESUME,
GUEST_HEARTBEAT_EVENT_RESIZE_BEGIN,
GUEST_HEARTBEAT_EVENT_RESIZE_END,
GUEST_HEARTBEAT_EVENT_LIVE_MIGRATE_BEGIN,
GUEST_HEARTBEAT_EVENT_LIVE_MIGRATE_END,
GUEST_HEARTBEAT_EVENT_COLD_MIGRATE_BEGIN,
GUEST_HEARTBEAT_EVENT_COLD_MIGRATE_END,
GUEST_HEARTBEAT_EVENT_MAX,
} GuestHeartbeatEventT;
typedef enum {
GUEST_HEARTBEAT_NOTIFY_UNKNOWN,
GUEST_HEARTBEAT_NOTIFY_REVOCABLE,
GUEST_HEARTBEAT_NOTIFY_IRREVOCABLE,
GUEST_HEARTBEAT_NOTIFY_MAX,
} GuestHeartbeatNotifyT;
typedef enum {
GUEST_HEARTBEAT_VOTE_RESULT_UNKNOWN,
GUEST_HEARTBEAT_VOTE_RESULT_ACCEPT,
GUEST_HEARTBEAT_VOTE_RESULT_REJECT,
GUEST_HEARTBEAT_VOTE_RESULT_COMPLETE,
GUEST_HEARTBEAT_VOTE_RESULT_TIMEOUT,
GUEST_HEARTBEAT_VOTE_RESULT_ERROR,
GUEST_HEARTBEAT_VOTE_RESULT_MAX,
} GuestHeartbeatVoteResultT;
// ****************************************************************************
// Guest Heartbeat Types - Action String
// =====================================
extern const char* guest_heartbeat_action_str( GuestHeartbeatActionT action );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Types - Event String
// ====================================
extern const char* guest_heartbeat_event_str( GuestHeartbeatEventT event );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Types - Notify String
// =====================================
extern const char* guest_heartbeat_notify_str( GuestHeartbeatNotifyT notify );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Types - Vote Result String
// ==========================================
extern const char* guest_heartbeat_vote_result_str( GuestHeartbeatVoteResultT result );
// ****************************************************************************
// ****************************************************************************
// Guest Heartbeat Types - Merge Action
// ====================================
extern GuestHeartbeatActionT guest_heartbeat_merge_action(
GuestHeartbeatActionT current_action, GuestHeartbeatActionT new_action );
// ****************************************************************************
#ifdef __cplusplus
}
#endif
#endif /* __GUEST_HEARTBEAT_TYPES_H__ */

View File

@ -0,0 +1,77 @@
#
# Copyright(c) 2013-2016, Wind River Systems, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Wind River Systems nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SHELL = /bin/sh
## Configuration Directory Variables
prefix := /usr/local
exec_prefix := $(prefix)
sysconfdir := $(prefix)/etc
includedir := $(prefix)/include
libdir := $(exec_prefix)/lib
bindir := $(exec_prefix)/bin
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
BUILD_DIR := $(CURRENT_DIR)/build
.SUFFIXES:
.SUFFIXES: .c .o
.PHONY: all build create_build_dir clean distclean
program_NAME := guest-client-test
program_C_INCLUDES := -I$(CURRENT_DIR) -I$(CURRENT_DIR)/../
program_C_INCLUDES += -I$(CURRENT_DIR)/../heartbeat
program_C_INCLUDES += -I$(CURRENT_DIR)/../../include
program_C_SRCS := $(wildcard *.c)
program_C_OBJS := ${program_C_SRCS:.c=.o}
program_LDLIBS := -lrt
CFLAGS = -g -O2 -Wall -Werror -Wformat -DSYSCONFDIR=$(sysconfdir)
all: build
%.o: %.c
$(CC) $(CFLAGS) $(program_C_INCLUDES) -c $^ -o $(BUILD_DIR)/$@ -ljson-c
$(program_NAME): $(program_C_OBJS)
@(cd ../; make --no-print-directory build sysconfdir=$(sysconfdir) BUILD_DIR=$(BUILD_DIR))
@-($(RM) $(BUILD_DIR)/guest_client.o $(BUILD_DIR)/guest-client)
$(CC) $(CFLAGS) $(BUILD_DIR)/*.o $(program_LDLIBS) -o $(BUILD_DIR)/$(program_NAME) -ljson-c
create_build_dir:
mkdir -p --mode 755 $(BUILD_DIR)
build: create_build_dir $(program_NAME)
clean:
@-($(RM) $(BUILD_DIR)/*)
distclean: clean

Some files were not shown because too many files have changed in this diff Show More