mirror of
https://github.com/clearlinux/telemetrics-client.git
synced 2026-09-01 11:15:51 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da8a8ef85c | ||
|
|
5cbd31cbf2 | ||
|
|
4119bdea33 | ||
|
|
2395f6bf3e | ||
|
|
bc7e2610ee | ||
|
|
a4774bde2e | ||
|
|
63574e7406 | ||
|
|
ce35876b55 | ||
|
|
055e55b2f3 | ||
|
|
84b4266bc2 | ||
|
|
e7d9d7b0ba | ||
|
|
b0effc8850 | ||
|
|
e9ce8bc1ae | ||
|
|
ea1480fb04 | ||
|
|
a6e81aa3bb | ||
|
|
fffe9755ad | ||
|
|
b465d35b24 | ||
|
|
e2aeda86eb | ||
|
|
6b4089075f | ||
|
|
83bb3df20a | ||
|
|
e855a19c88 | ||
|
|
7173e1fede | ||
|
|
a4bc8b55dd | ||
|
|
d81ac1e8f3 | ||
|
|
b0d448e9e7 | ||
|
|
88ee43f528 | ||
|
|
49a1d41a3a | ||
|
|
0e20d62c9e | ||
|
|
d314c1a88b | ||
|
|
b9ad4c2f14 | ||
|
|
9fd3c280ba | ||
|
|
75255fff50 | ||
|
|
b2adc08d4f | ||
|
|
e6357bb051 | ||
|
|
15b5df2f47 | ||
|
|
f516d85e59 | ||
|
|
ce2ad0c2b0 |
@@ -0,0 +1,29 @@
|
||||
name: C/C++ CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install dependencies
|
||||
run: sudo apt-get install libcurl4-gnutls-dev valgrind libelf-dev libdw-dev
|
||||
- name: install check
|
||||
run: wget https://github.com/libcheck/check/releases/download/0.12.0/check-0.12.0.tar.gz &&
|
||||
tar xf check-0.12.0.tar.gz &&
|
||||
pushd check-0.12.0 &&
|
||||
./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu &&
|
||||
make -j8 && sudo make install && popd
|
||||
- name: autogen
|
||||
run: sh autogen.sh
|
||||
- name: configure
|
||||
run: ./configure
|
||||
- name: make
|
||||
run: make -j8
|
||||
- name: check
|
||||
run: make check
|
||||
- name: make distcheck
|
||||
run: make distcheck
|
||||
@@ -42,7 +42,6 @@ hprobe
|
||||
bertprobe
|
||||
crashprobe
|
||||
journalprobe
|
||||
pythonprobe
|
||||
telem-record-gen
|
||||
klogscanner
|
||||
pstoreclean
|
||||
|
||||
@@ -15,7 +15,6 @@ DISTCHECK_CONFIGURE_FLAGS = \
|
||||
include $(top_srcdir)/build-aux/make/cflags.make
|
||||
include $(top_srcdir)/build-aux/make/ldflags.make
|
||||
include $(top_srcdir)/docs/local.mk
|
||||
include $(top_srcdir)/scripts/local.mk
|
||||
include $(top_srcdir)/src/local.mk
|
||||
include $(top_srcdir)/src/data/local.mk
|
||||
include $(top_srcdir)/src/nica/local.mk
|
||||
|
||||
@@ -67,38 +67,47 @@ Descriptions of config options are listed below in the Usage section.
|
||||
|
||||
Starting the client
|
||||
---------------------
|
||||
To use the telemetrics client a one time explicit ```opt-in``` is required (this is
|
||||
also true when the contents of the directory ```/etc/telemetrics/``` are removed).
|
||||
To opt-in to telemetrics-client use the command:
|
||||
|
||||
```{r, engine='bash', count_lines}
|
||||
telemctl opt-in
|
||||
```
|
||||
|
||||
**Note** this is a change from previous versions, before 2.3.0 installation of
|
||||
telemetrics client was enough to enable the client and if needed the client could
|
||||
be disabled with ```telemctl opt-out```. This command in previous versions created
|
||||
```/etc/telemetrics/opt-out``` file (after telemetrics-client version 2.3.0 this
|
||||
file can be safely removed).
|
||||
|
||||
If the client was compiled with systemd support the respective activation units
|
||||
should be already in place (after a ```make install``` invocation). In this case
|
||||
the client wil start automatically when data is made available to it. i.e. when
|
||||
executing an ```/usr/bin/hprobe``` command.
|
||||
|
||||
Method 1 (recommended):
|
||||
executing an ```/usr/bin/hprobe``` command. Otherwise use the following command:
|
||||
|
||||
```{r, engine='bash', count_lines}
|
||||
telemctl start
|
||||
```
|
||||
|
||||
Note: the above invocation technically readies the service for both socket and
|
||||
path activation, so you may not see an "active" status.
|
||||
|
||||
Method 2:
|
||||
path activation, so you may not see an "active" status. To check the status of
|
||||
telemetrics-client use:
|
||||
|
||||
```{r, engine='bash', count_lines}
|
||||
systemctl start telemprobd.service
|
||||
systemctl start telempostd.service
|
||||
telemctl is-active
|
||||
telemprobd : active
|
||||
telempostd : active
|
||||
```
|
||||
|
||||
Method 3:
|
||||
|
||||
```{r, engine='bash', count_lines}
|
||||
telemprobd &
|
||||
telempostd &
|
||||
```
|
||||
Starting individual service units ```telempostd.service``` or ```telemeprobd.service```
|
||||
is discouraged.
|
||||
|
||||
Configure the client to autostart at boot
|
||||
---------------------
|
||||
|
||||
As longs as the first time ```opt-in``` was performed, the following methods are valid:
|
||||
|
||||
|
||||
Method 1 (recommended):
|
||||
|
||||
Enable the socket-activated service and path unit:
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([telemetrics-client], [2.2.1], [https://clearlinux.org/])
|
||||
AC_INIT([telemetrics-client], [2.2.3], [https://clearlinux.org/])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AM_INIT_AUTOMAKE([1.14 -Wall -Werror -Wno-extra-portability foreign subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
+6
-5
@@ -34,7 +34,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.sp
|
||||
\fBtelemctl\fP
|
||||
.sp
|
||||
\fB/etc/telemetrics/opt\-out\fP
|
||||
\fB/etc/telemetrics/opt\-in\fP
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
Control actions for telemetry services. The command can be used to start,
|
||||
@@ -48,12 +48,13 @@ restart, or stop \fBtelemprobd\fP(1) and \fBtelempostd\fP(1), or to opt\-in or o
|
||||
Starts, stops or restarts all running telemetry services.
|
||||
.IP \(bu 2
|
||||
\fBopt\-in\fP:
|
||||
Opts in to telemetry, and starts telemetry services. The opt\-out file
|
||||
\fB/etc/telemetrics/opt\-out\fP is removed.
|
||||
Opts in to telemetry and the opt\-in file \fB/etc/telemetrics/opt\-in\fP
|
||||
is created. Note: this is a one time required operation before
|
||||
telemetry can be used the first time.
|
||||
.IP \(bu 2
|
||||
\fBopt\-out\fP:
|
||||
Opts out of telemetry, and stops telemetry services. The opt\-out file
|
||||
\fB/etc/telemetrics/opt\-out\fP is created.
|
||||
Opts out of telemetry, and stops telemetry services. The opt\-in file
|
||||
\fB/etc/telemetrics/opt\-in\fP is deleted.
|
||||
.IP \(bu 2
|
||||
\fBis\-active\fP:
|
||||
Checks if telemetry client daemons are active (telemprobd and telempostd).
|
||||
|
||||
@@ -15,7 +15,7 @@ SYNOPSIS
|
||||
|
||||
``telemctl``
|
||||
|
||||
``/etc/telemetrics/opt-out``
|
||||
``/etc/telemetrics/opt-in``
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
@@ -32,12 +32,13 @@ OPTIONS
|
||||
Starts, stops or restarts all running telemetry services.
|
||||
|
||||
* ``opt-in``:
|
||||
Opts in to telemetry, and starts telemetry services. The opt-out file
|
||||
``/etc/telemetrics/opt-out`` is removed.
|
||||
Opts in to telemetry and the opt-in file ``/etc/telemetrics/opt-in``
|
||||
is created. Note: this is a one time required operation before
|
||||
telemetry can be used the first time.
|
||||
|
||||
* ``opt-out``:
|
||||
Opts out of telemetry, and stops telemetry services. The opt-out file
|
||||
``/etc/telemetrics/opt-out`` is created.
|
||||
Opts out of telemetry, and stops telemetry services. The opt-in file
|
||||
``/etc/telemetrics/opt-in`` is deleted.
|
||||
|
||||
* ``is-active``:
|
||||
Checks if telemetry client daemons are active (telemprobd and telempostd).
|
||||
|
||||
@@ -45,6 +45,8 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
\fBvoid tm_free_record(struct telem_ref *t_ref)\fP
|
||||
.sp
|
||||
\fBint tm_set_config_file(const char *c_file)\fP
|
||||
.sp
|
||||
\fBint tm_is_opted_in(void)\fP
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
The functions in the telemetry library facilitate the delivery of
|
||||
@@ -64,11 +66,15 @@ The function \fBtm_send_record()\fP delivers the record to the local
|
||||
.sp
|
||||
The function \fBtm_set_config_file()\fP can be used to provide an alternate
|
||||
configuration path to the telemetry library.
|
||||
.sp
|
||||
\fBtm_is_opted_in\fP is a utility provided to check if the one time opt\-in
|
||||
has been performed.
|
||||
.SH RETURN VALUES
|
||||
.sp
|
||||
All these functions return \fB0\fP on success, or a non\-zero return value
|
||||
if an error occurred. The function \fBtm_free_record()\fP does not return
|
||||
any value.
|
||||
any value. \fBtm_is_opted_in\fP returns \fB1\fP when telemetry is opted\-in
|
||||
otherwise \fB0\fP\&.
|
||||
.SH SEE ALSO
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
|
||||
@@ -27,6 +27,8 @@ SYNOPSIS
|
||||
|
||||
``int tm_set_config_file(const char *c_file)``
|
||||
|
||||
``int tm_is_opted_in(void)``
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
@@ -49,13 +51,16 @@ The function ``tm_send_record()`` delivers the record to the local
|
||||
The function ``tm_set_config_file()`` can be used to provide an alternate
|
||||
configuration path to the telemetry library.
|
||||
|
||||
``tm_is_opted_in`` is a utility provided to check if the one time opt-in
|
||||
has been performed.
|
||||
|
||||
RETURN VALUES
|
||||
=============
|
||||
|
||||
All these functions return ``0`` on success, or a non-zero return value
|
||||
if an error occurred. The function ``tm_free_record()`` does not return
|
||||
any value.
|
||||
any value. ``tm_is_opted_in`` returns ``1`` when telemetry is opted-in
|
||||
otherwise ``0``.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
dist_bin_SCRIPTS = %D%/telemctl
|
||||
|
||||
# vim: filetype=automake tabstop=8 shiftwidth=8 noexpandtab
|
||||
@@ -1,150 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
declare -a SPECIAL_UNITS=(
|
||||
hprobe.timer
|
||||
telemprobd.socket
|
||||
telempostd.path
|
||||
klogscanner.service
|
||||
journal-probe-tail.service
|
||||
python-probe.path
|
||||
)
|
||||
|
||||
declare -a SERVICES=(
|
||||
hprobe.service
|
||||
pstore-probe.service
|
||||
telemprobd.service
|
||||
telempostd.service
|
||||
journal-probe.service
|
||||
)
|
||||
|
||||
SCRIPT="$0"
|
||||
TELEM_DIR=/etc/telemetrics
|
||||
OPT_OUT_FILE=${TELEM_DIR}/opt-out
|
||||
TELEM_WRK_DIRS_CONF=/usr/lib/tmpfiles.d/telemetrics-dirs.conf
|
||||
|
||||
create_work_dirs() {
|
||||
# Creates dirs if missing, adjust ownership if exists
|
||||
systemd-tmpfiles --create ${TELEM_WRK_DIRS_CONF}
|
||||
}
|
||||
|
||||
telem_remove_work_dirs() {
|
||||
# Remove dirs
|
||||
awk '/^d/{print $2}' ${TELEM_WRK_DIRS_CONF} | xargs rm -rf;
|
||||
}
|
||||
|
||||
exit_ok() {
|
||||
echo "$1" > /dev/stderr
|
||||
exit 0
|
||||
}
|
||||
|
||||
exit_err() {
|
||||
echo "$1" > /dev/stderr
|
||||
exit 1
|
||||
}
|
||||
|
||||
notice() {
|
||||
echo "$1" > /dev/stderr
|
||||
}
|
||||
|
||||
for_each_service() {
|
||||
local action=$1 && shift
|
||||
local -a array=($*)
|
||||
for service in "${array[@]}"; do
|
||||
systemctl $action $service
|
||||
[ $? -ne 0 ] && notice "Failed to $action ${service}. Continuing..."
|
||||
done
|
||||
}
|
||||
|
||||
telem_stop() {
|
||||
# the special units must be stopped first so that activation no longer happens
|
||||
for_each_service "stop" ${SPECIAL_UNITS[@]}
|
||||
for_each_service "stop" ${SERVICES[@]}
|
||||
}
|
||||
|
||||
telem_start() {
|
||||
[ -f $OPT_OUT_FILE ] && exit_err "Opt out is enabled. Cannot start services."
|
||||
# trigger systemd-tmpfiles work dirs creation
|
||||
create_work_dirs
|
||||
# the units in SERVICES are activated as needed, so no need to start them
|
||||
for_each_service "start" ${SPECIAL_UNITS[@]}
|
||||
}
|
||||
|
||||
telem_is_active() {
|
||||
# check only activation units
|
||||
echo "telemprobd :" $(systemctl is-active telemprobd.socket)
|
||||
echo "telempostd :" $(systemctl is-active telempostd.path)
|
||||
}
|
||||
|
||||
telem_opt_out() {
|
||||
[ -f $OPT_OUT_FILE ] && exit_ok "Already opted out. Nothing to do."
|
||||
mkdir -p $TELEM_DIR || exit_err "Failed to create ${TELEM_DIR}."
|
||||
touch $OPT_OUT_FILE || exit_err "Failed to create ${OPT_OUT_FILE}."
|
||||
telem_stop
|
||||
telem_remove_work_dirs
|
||||
}
|
||||
|
||||
telem_opt_in() {
|
||||
[ ! -f $OPT_OUT_FILE ] && exit_ok "Already opted in. Nothing to do."
|
||||
rm -f $OPT_OUT_FILE || exit_err "Failed to remove ${OPT_OUT_FILE}."
|
||||
telem_start
|
||||
}
|
||||
|
||||
telem_restart() {
|
||||
telem_stop
|
||||
telem_start
|
||||
}
|
||||
|
||||
telem_journal_cli() {
|
||||
telem_journal "$@"
|
||||
}
|
||||
|
||||
usage() {
|
||||
format=' %-10s %s\n'
|
||||
printf "\n"
|
||||
printf "%s - Control actions for telemetry services\n" "$SCRIPT"
|
||||
printf "\n"
|
||||
printf "$format" "stop" "Stops all running telemetry services"
|
||||
printf "$format" "start" "Starts all telemetry services"
|
||||
printf "$format" "restart" "Restarts all telemetry services"
|
||||
printf "$format" "is-active" "Checks if telemprobd and telempostd are active"
|
||||
printf "$format" "opt-in" "Opts in to telemetry, and starts telemetry services"
|
||||
printf "$format" "opt-out" "Opts out of telemetry, and stops telemetry services"
|
||||
printf "$format" "journal" "Prints telemtry journal contents. Use -h argument with"
|
||||
printf "$format" "" "command for more options"
|
||||
printf "\n"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if [ "$1" != "journal" ] && [ $# -ne 1 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ $EUID -ne 0 ]; then
|
||||
exit_err "Must be root to run this command. Exiting..."
|
||||
fi
|
||||
|
||||
SUBCOMMAND=$1
|
||||
|
||||
case $SUBCOMMAND in
|
||||
opt-out)
|
||||
telem_opt_out ;;
|
||||
opt-in)
|
||||
telem_opt_in ;;
|
||||
stop)
|
||||
telem_stop ;;
|
||||
start)
|
||||
telem_start ;;
|
||||
restart)
|
||||
telem_restart ;;
|
||||
is-active)
|
||||
telem_is_active ;;
|
||||
journal)
|
||||
telem_journal_cli "$@" ;;
|
||||
*)
|
||||
notice "Unknown command passed to $SCRIPT"
|
||||
usage ;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# vi: ts=8 sw=2 sts=2 et tw=80
|
||||
+1
-1
@@ -75,7 +75,7 @@ static const uint32_t RECORD_FORMAT_VERSION = 4;
|
||||
#define TM_SITE_VERSION_FILE "/etc/os-release"
|
||||
#define TM_DIST_VERSION_FILE "/usr/lib/os-release"
|
||||
|
||||
#define TM_OPT_OUT_FILE "/etc/telemetrics/opt-out"
|
||||
#define TM_OPT_IN_FILE "/etc/telemetrics/opt-in"
|
||||
|
||||
/* Currently max supported payload size is 8kb */
|
||||
#define MAX_PAYLOAD_LENGTH 8192
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Description=Telemetrics BERT Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
ConditionPathExists=/sys/firmware/acpi/tables/data/BERT
|
||||
|
||||
[Service]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Description=Telemetrics Heartbeat Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/hprobe -Hlu
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Daily Heartbeat for Telemetrics
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Description=Telemetrics Systemd Journal Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/journalprobe -t
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Description=Telemetrics Systemd Journal Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/journalprobe
|
||||
|
||||
@@ -19,8 +19,6 @@ EXTRA_DIST += \
|
||||
%D%/bert-probe.service.in \
|
||||
%D%/journal-probe.service.in \
|
||||
%D%/journal-probe-tail.service.in \
|
||||
%D%/python-probe.service.in \
|
||||
%D%/python-probe.path.in \
|
||||
%D%/pstore-probe.service.in \
|
||||
%D%/klogscanner.service.in \
|
||||
%D%/pstore-clean.service.in \
|
||||
@@ -58,8 +56,6 @@ systemdunit_DATA = \
|
||||
%D%/bert-probe.service \
|
||||
%D%/journal-probe.service \
|
||||
%D%/journal-probe-tail.service \
|
||||
%D%/python-probe.service \
|
||||
%D%/python-probe.path \
|
||||
%D%/pstore-probe.service \
|
||||
%D%/klogscanner.service \
|
||||
%D%/pstore-clean.service \
|
||||
@@ -96,12 +92,6 @@ systemdunit_DATA = \
|
||||
%D%/telempostd.service: %D%/telempostd.service.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
%D%/python-probe.service: %D%/python-probe.service.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
%D%/python-probe.path: %D%/python-probe.path.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
%D%/telemprobd.service: %D%/telemprobd.service.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
@@ -125,8 +115,6 @@ clean-local:
|
||||
%D%/telemprobd.socket \
|
||||
%D%/telempostd.service \
|
||||
%D%/telempostd.path \
|
||||
%D%/python-probe.service \
|
||||
%D%/python-probe.path \
|
||||
%D%/telemprobd-update-trigger.service \
|
||||
%D%/telemetrics.conf \
|
||||
%D%/telemetrics-dirs.conf \
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Description=Telemetrics Pstore Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/pstoreprobe
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
[Unit]
|
||||
Description=Python Probe Daemon Staging
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
|
||||
[Path]
|
||||
DirectoryNotEmpty=/var/lib/telemetry/python
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=Telemetrics Python Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
|
||||
[Service]
|
||||
User=telemetry
|
||||
ExecStart=@bindir@/pythonprobe
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -4,5 +4,3 @@ d @localstatedir@/log/telemetry 0750 telemetry telemetry -
|
||||
d @localstatedir@/log/telemetry/records 0750 telemetry telemetry -
|
||||
d @localstatedir@/cache/telemetry 0750 telemetry telemetry -
|
||||
d @localstatedir@/cache/telemetry/pstore 0750 telemetry telemetry -
|
||||
d /var/lib/telemetry/python 01777 telemetry telemetry -
|
||||
d /var/tmp/telemetry 01777 telemetry telemetry -
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Telemetry Post Daemon staging
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Path]
|
||||
DirectoryNotEmpty=@localstatedir@/spool/telemetry
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Telemetrics Post Daemon
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/telempostd
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Telemetrics Daemon
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/telemprobd
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Telemetrics Daemon
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Socket]
|
||||
ListenStream=@SOCKETDIR@/telem-0
|
||||
|
||||
+7
-10
@@ -43,7 +43,7 @@ bool _fgets(char *s, int n, FILE *stream)
|
||||
|
||||
bool read_record(char *fullpath, char *headers[], char **body, char **cfg_file)
|
||||
{
|
||||
int i, ret = 0;
|
||||
int i = 0;
|
||||
bool result = false;
|
||||
FILE *fp = NULL;
|
||||
long offset;
|
||||
@@ -52,23 +52,20 @@ bool read_record(char *fullpath, char *headers[], char **body, char **cfg_file)
|
||||
#else
|
||||
char line[PATH_MAX+1] = { 0 };
|
||||
#endif
|
||||
struct stat buf;
|
||||
long size;
|
||||
uint32_t cfg_prefix = 0;
|
||||
|
||||
ret = stat(fullpath, &buf);
|
||||
if (ret == -1) {
|
||||
telem_log(LOG_ERR, "Unable to stat record %s in staging\n", fullpath);
|
||||
return false;
|
||||
}
|
||||
size = buf.st_size;
|
||||
|
||||
fp = fopen(fullpath, "r");
|
||||
if (fp == NULL) {
|
||||
telem_log(LOG_ERR, "Unable to open file %s in staging\n", fullpath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the file size
|
||||
fseek(fp, 0 , SEEK_END);
|
||||
size = ftell(fp);
|
||||
fseek(fp, 0 , SEEK_SET);
|
||||
|
||||
// First line may contain configuration file path
|
||||
if (fread(&cfg_prefix, CFG_PREFIX_LENGTH, 1, fp) != 1) {
|
||||
telem_log(LOG_ERR, "Error while parsing staged record configuration info.\n");
|
||||
@@ -83,7 +80,7 @@ bool read_record(char *fullpath, char *headers[], char **body, char **cfg_file)
|
||||
|
||||
size_t pathlen = strlen(line);
|
||||
*cfg_file = malloc(pathlen + 1);
|
||||
if (cfg_file == NULL) {
|
||||
if (*cfg_file == NULL) {
|
||||
telem_log(LOG_ERR, "Could not allocate memory for config file path\n");
|
||||
goto read_error;
|
||||
}
|
||||
|
||||
+16
-11
@@ -99,11 +99,14 @@ static int deserialize_journal_entry(char *line, struct JournalEntry **entry)
|
||||
size_t offset = 0;
|
||||
struct JournalEntry *e = NULL;
|
||||
|
||||
if (line == NULL) {
|
||||
/* Assume an error... */
|
||||
*entry = NULL;
|
||||
|
||||
if (line == NULL || !strlen(line)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = malloc(sizeof(struct JournalEntry));
|
||||
e = calloc(1, sizeof(struct JournalEntry));
|
||||
if (!e) {
|
||||
return -1;
|
||||
}
|
||||
@@ -138,10 +141,6 @@ static int deserialize_journal_entry(char *line, struct JournalEntry **entry)
|
||||
e->boot_id = out;
|
||||
rc = 0;
|
||||
break;
|
||||
default:
|
||||
assert(i < 0 && i > 4);
|
||||
free(out);
|
||||
rc = 1;
|
||||
}
|
||||
} else {
|
||||
rc = -1;
|
||||
@@ -273,6 +272,8 @@ static int skip_n_lines(int n, FILE *fptr, int (*found_record)(char *))
|
||||
break;
|
||||
}
|
||||
if (found_record != NULL) {
|
||||
if (!strlen(line))
|
||||
continue;
|
||||
deserialize_journal_entry(line, &entry);
|
||||
if (entry) {
|
||||
found_record(entry->record_id);
|
||||
@@ -346,12 +347,14 @@ TelemJournal *open_journal(const char *journal_file)
|
||||
|
||||
if (read_boot_id(boot_id) != 0) {
|
||||
telem_perror("Error while reading boot_id");
|
||||
fclose(fptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
telem_journal = malloc(sizeof(struct TelemJournal));
|
||||
if (!telem_journal) {
|
||||
telem_log(LOG_CRIT, "CRIT: Unable to allocate memory\n");
|
||||
fclose(fptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -465,6 +468,8 @@ int print_journal(TelemJournal *telem_journal, char *classification,
|
||||
}
|
||||
|
||||
while (getline(&line, &len, journal_fileptr) != -1) {
|
||||
if (!strlen(line))
|
||||
continue;
|
||||
deserialize_journal_entry(line, &entry);
|
||||
if (entry) {
|
||||
/* filter entry out if one is provided */
|
||||
@@ -482,16 +487,16 @@ int print_journal(TelemJournal *telem_journal, char *classification,
|
||||
// Check prefixes when classification ends in /*, otherwise use strcomp
|
||||
if (is_class_prefix(classification)) {
|
||||
if (strncmp(entry->classification, classification, strlen(classification) - 1) != 0) {
|
||||
continue;
|
||||
goto skip_print;
|
||||
}
|
||||
} else if (strcmp(entry->classification, classification) != 0) {
|
||||
continue;
|
||||
goto skip_print;
|
||||
}
|
||||
}
|
||||
/* end filters section */
|
||||
ts = *localtime(&entry->timestamp);
|
||||
if (strftime(str_time, sizeof(str_time), "%a %Y-%m-%d %H:%M:%S %Z", &ts) == 0) {
|
||||
continue;
|
||||
goto skip_print;
|
||||
}
|
||||
/* print record metadata */
|
||||
fprintf(stdout, "%-30s %s %s %s %s\n", entry->classification, str_time, entry->record_id, entry->event_id, entry->boot_id);
|
||||
@@ -500,9 +505,9 @@ int print_journal(TelemJournal *telem_journal, char *classification,
|
||||
print_record(entry->record_id);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
skip_print:
|
||||
free_journal_entry(entry);
|
||||
free_journal_entry(entry);
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
fclose(journal_fileptr);
|
||||
|
||||
+14
-3
@@ -1,6 +1,17 @@
|
||||
bin_PROGRAMS = \
|
||||
%D%/telemprobd \
|
||||
%D%/telempostd
|
||||
%D%/telempostd \
|
||||
%D%/telemctl
|
||||
|
||||
%C%_telemctl_SOURCES = \
|
||||
%D%/telemctl.c
|
||||
|
||||
%C%_telemctl_CFLAGS = \
|
||||
$(AM_CFLAGS)
|
||||
|
||||
%C%_telemctl_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-pie
|
||||
|
||||
%C%_telemprobd_SOURCES = \
|
||||
%D%/probe.c \
|
||||
@@ -79,8 +90,8 @@ endif
|
||||
|
||||
# set library version info
|
||||
SHAREDLIB_CURRENT=4
|
||||
SHAREDLIB_REVISION=0
|
||||
SHAREDLIB_AGE=1
|
||||
SHAREDLIB_REVISION=1
|
||||
SHAREDLIB_AGE=0
|
||||
|
||||
noinst_LTLIBRARIES = %D%/libtelem-shared.la
|
||||
|
||||
|
||||
+36
-24
@@ -151,33 +151,38 @@ static char *string_strip(char *str, ssize_t len, ssize_t *out_len)
|
||||
/* eat \s */
|
||||
static char *string_unescape(char *str)
|
||||
{
|
||||
char *c, *c1, *c2, *c3;;
|
||||
char *c, *c1, *c2, *c3;;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c = calloc(strlen(str) + 1, 1);
|
||||
c1 = c;
|
||||
c = calloc(strlen(str) + 1, 1);
|
||||
if (c == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c2 = str;
|
||||
while (c2 && *c2 != 0) {
|
||||
c3 = c2 + 1;
|
||||
if (*c2 == '\\') {
|
||||
if (*c3 == 's') {
|
||||
*c = ' ';
|
||||
c++;
|
||||
c2 += 2;
|
||||
} else {
|
||||
c2++;
|
||||
}
|
||||
} else {
|
||||
*c = *c2;
|
||||
c++;
|
||||
c2++;
|
||||
}
|
||||
}
|
||||
c1 = c;
|
||||
|
||||
free(str);
|
||||
c2 = str;
|
||||
while (c2 && *c2 != 0) {
|
||||
c3 = c2 + 1;
|
||||
if (*c2 == '\\') {
|
||||
if (*c3 == 's') {
|
||||
*c = ' ';
|
||||
c++;
|
||||
c2 += 2;
|
||||
} else {
|
||||
c2++;
|
||||
}
|
||||
} else {
|
||||
*c = *c2;
|
||||
c++;
|
||||
c2++;
|
||||
}
|
||||
}
|
||||
|
||||
free(str);
|
||||
return c1;
|
||||
}
|
||||
|
||||
@@ -300,7 +305,14 @@ int nc_ini_file_parse_full(const char *path, NcHashmap **out_map, int *error_lin
|
||||
key = strdup(buf);
|
||||
key = string_chew_terminated(key);
|
||||
value = string_chew_terminated(value);
|
||||
value = string_unescape(value);
|
||||
if (value != NULL) {
|
||||
value = string_unescape(value);
|
||||
if (value == NULL) {
|
||||
err_ret = NC_INI_ERROR_INTERNAL;
|
||||
fprintf(stderr, "[inifile] Fatal! Out of memory\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (streq(key, "")) {
|
||||
err_ret = NC_INI_ERROR_EMPTY_KEY;
|
||||
|
||||
@@ -19,8 +19,6 @@ The default probes provided along the telemetry client code are:
|
||||
|
||||
* pstoreprobe: probe to collect messages left on pstore filesystem.
|
||||
|
||||
* pythonprobe: a probe that monitors Python generated traceback files.
|
||||
|
||||
* telem-record-gen: this is a "general-purpose probe" for sending custom
|
||||
records on-the-fly. This tool can be used stand alone or as a part of a
|
||||
script to implement a probe.
|
||||
|
||||
@@ -250,7 +250,7 @@ static int frame_cb(Dwfl_Frame *frame, void *userdata)
|
||||
" current frame: %s\n",
|
||||
dwfl_errmsg(-1));
|
||||
if (ret < 0) {
|
||||
return DWARF_CB_ABORT;
|
||||
errorstr = NULL;
|
||||
}
|
||||
return DWARF_CB_ABORT;
|
||||
}
|
||||
|
||||
@@ -4,24 +4,9 @@ bin_PROGRAMS += \
|
||||
%D%/telem-record-gen \
|
||||
%D%/klogscanner \
|
||||
%D%/pstoreprobe \
|
||||
%D%/pythonprobe \
|
||||
%D%/pstoreclean \
|
||||
%D%/bertprobe
|
||||
|
||||
%C%_pythonprobe_SOURCES = %D%/python-probe.c
|
||||
%C%_pythonprobe_CFLAGS = $(AM_CFLAGS)
|
||||
%C%_pythonprobe_LDADD = $(top_builddir)/src/libtelemetry.la
|
||||
%C%_pythonprobe_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-pie
|
||||
|
||||
if LOG_SYSTEMD
|
||||
if HAVE_SYSTEMD_JOURNAL
|
||||
%C%_pythonprobe_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
|
||||
%C%_pythonprobe_LDADD += $(SYSTEMD_JOURNAL_LIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
%C%_hprobe_SOURCES = %D%/hello.c
|
||||
%C%_hprobe_LDADD = $(top_builddir)/src/libtelemetry.la
|
||||
%C%_hprobe_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
@@ -150,6 +150,18 @@ struct oops_pattern oops_patterns_arr[] = {
|
||||
TM_MEDIUM,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"ACPI Error:",
|
||||
"org.clearlinux/kernel/warning",
|
||||
TM_MEDIUM,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Kernel panic - not syncing:",
|
||||
"org.clearlinux/kernel/panic",
|
||||
TM_CRITICAL,
|
||||
false,
|
||||
},
|
||||
};
|
||||
|
||||
static int oops_patterns_cnt = sizeof(oops_patterns_arr) / sizeof(struct oops_pattern);
|
||||
@@ -469,7 +481,7 @@ static void stack_frame_append(struct stack_frame **head, struct stack_frame **t
|
||||
while (*start && !isspace(*start)) {
|
||||
start++;
|
||||
}
|
||||
if (start && *start == '\0') {
|
||||
if (*start == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -504,7 +516,7 @@ static void stack_frame_append(struct stack_frame **head, struct stack_frame **t
|
||||
while (*start && !isspace(*start)) {
|
||||
start++;
|
||||
}
|
||||
if (start && *start == '\0') {
|
||||
if (*start == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -195,6 +196,13 @@ struct chunk_list {
|
||||
struct chunk_list *next;
|
||||
};
|
||||
|
||||
static void print_usage(char *prog)
|
||||
{
|
||||
printf("%s: Usage\n", prog);
|
||||
printf(" -f, --config_file This overides the other parameters\n");
|
||||
printf(" -h, --help Display this help message\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DIR *pstore_dir;
|
||||
@@ -205,6 +213,32 @@ int main(int argc, char **argv)
|
||||
int max_part;
|
||||
size_t totalsize = 0;
|
||||
char *crash_dump = NULL;
|
||||
int c;
|
||||
int opt_index = 0;
|
||||
|
||||
struct option opts[] = {
|
||||
{ "config_file", 1, NULL, 'f' },
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
while ((c = getopt_long(argc, argv, "f:h", opts, &opt_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
if (tm_set_config_file(optarg) != 0) {
|
||||
telem_log(LOG_ERR, "Configuration file"
|
||||
" path not valid\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
case '?':
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash table used to store chunks belonging to a oops counter
|
||||
@@ -230,7 +264,13 @@ int main(int argc, char **argv)
|
||||
// Look for only dmesg logs. Ignore other types of pstore dumps for now.
|
||||
if (sscanf(entry->d_name, "dmesg-efi-%" PRIu64, &id) == 1) {
|
||||
parse_id(id, &count, &part);
|
||||
telem_debug("DEBUG: Extracted count :%d, part : %d\n", count, part);
|
||||
telem_debug("dmesg-efi Extracted count :%d, part : %d\n",
|
||||
count, part);
|
||||
} else if (sscanf(entry->d_name, "dmesg-ramoops-%" PRIu64, &id) == 1) {
|
||||
count = (int)(id + 1);
|
||||
part = 1;
|
||||
telem_debug("dmesg-ramoops Extracted count :%d, part : %d\n",
|
||||
count, part);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "telemetry.h"
|
||||
|
||||
#define PYTHON_TELEMETRY_DIR "/var/lib/telemetry/python"
|
||||
|
||||
/* We expect something like: 1.python-exception.3.N2Qy24 */
|
||||
static bool validate_file_name(const char *filename, uint32_t *severity,
|
||||
char** class, uint32_t *version)
|
||||
{
|
||||
unsigned int ver, sev;
|
||||
char cls[PATH_MAX] = { 0 };
|
||||
char rnd[PATH_MAX] = { 0 };
|
||||
char *filename_base = basename(filename);
|
||||
char *str_class = NULL;
|
||||
|
||||
if (!filename_base) {
|
||||
telem_perror("basename failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sscanf(filename_base,"%u.%[^]0-9.].%u.%s", &ver, cls, &sev, rnd) == 4) {
|
||||
if (asprintf(&str_class, "org.clearlinux/python/%s", cls) < 29) {
|
||||
telem_log(LOG_ERR, "%s: invalid telemetry classification\n",
|
||||
str_class);
|
||||
return false;
|
||||
}
|
||||
*class = str_class;
|
||||
*version = ver;
|
||||
*severity = sev;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *read_file_into_buffer(const char *filename)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
char *contents = NULL;
|
||||
long sz;
|
||||
size_t size, bytes_read;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
telem_log(LOG_ERR, "Failed to open Python telemetry file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fseek(fp, 0, SEEK_END) == -1) {
|
||||
telem_log(LOG_ERR, "Failed to seek file %s: %s\n", filename,
|
||||
strerror(errno));
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
sz = ftell(fp);
|
||||
if (sz == -1L) {
|
||||
telem_perror("ftell failed");
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
if (sz == 0L) {
|
||||
telem_perror("File is empty\n");
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
if (fseek(fp, 0, SEEK_SET) < 0) {
|
||||
telem_log(LOG_ERR, "fseek failed for file %s:%s\n", filename,
|
||||
strerror(errno));
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
size = (size_t)sz;
|
||||
contents = calloc(sizeof(char), size);
|
||||
if (!contents) {
|
||||
telem_log(LOG_ERR, "Call to calloc failed\n");
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
bytes_read = fread(contents, sizeof(char), size, fp);
|
||||
|
||||
if (bytes_read < size) {
|
||||
telem_log(LOG_ERR, "Error while reading file %s:%s\n", filename,
|
||||
strerror(errno));
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return contents;
|
||||
|
||||
error_end:
|
||||
fclose(fp);
|
||||
if (contents) {
|
||||
free(contents);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void send_data(char *contents, uint32_t severity, char *class,
|
||||
uint32_t version)
|
||||
{
|
||||
struct telem_ref *handle = NULL;
|
||||
int ret;
|
||||
|
||||
if ((ret = tm_create_record(&handle, severity, class, version)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to create record: %s\n",
|
||||
strerror(-ret));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = tm_set_payload(handle, contents)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to set payload: %s\n",
|
||||
strerror(-ret));
|
||||
tm_free_record(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = tm_send_record(handle)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to send record: %s\n",
|
||||
strerror(-ret));
|
||||
}
|
||||
|
||||
tm_free_record(handle);
|
||||
}
|
||||
|
||||
/* Send a valid file to the backend. */
|
||||
static void deliver_payload(const char *filename)
|
||||
{
|
||||
uint32_t severity;
|
||||
uint32_t version;
|
||||
char *class = NULL;
|
||||
char *contents = NULL;
|
||||
|
||||
if (validate_file_name(filename, &severity, &class, &version)) {
|
||||
if ((contents = read_file_into_buffer(filename)) != NULL) {
|
||||
send_data(contents, severity, class, version);
|
||||
free(contents);
|
||||
}
|
||||
|
||||
free(class);
|
||||
}
|
||||
|
||||
/* Keep PYTHON_TELEMETRY_DIR empty. Delete the file. */
|
||||
if (unlink(filename) != 0) {
|
||||
telem_log(LOG_ERR, "Failed to unlink %s: %s\n", filename,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void drop_privs(void)
|
||||
{
|
||||
uid_t euid;
|
||||
|
||||
euid = geteuid();
|
||||
if (euid != 0) {
|
||||
telem_log(LOG_DEBUG, "Not root; skipping privilege drop\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct passwd *pw;
|
||||
|
||||
pw = getpwnam("telemetry");
|
||||
if (!pw) {
|
||||
telem_log(LOG_ERR, "telemetry user not found\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// The order is important here:
|
||||
// change supplemental groups, our gid, and then our uid
|
||||
if (initgroups(pw->pw_name, pw->pw_gid) != 0) {
|
||||
telem_perror("Failed to set supplemental group list");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (setgid(pw->pw_gid) != 0) {
|
||||
telem_perror("Failed to set GID");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (setuid(pw->pw_uid) != 0) {
|
||||
telem_perror("Failed to set UID");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
assert(getuid() == pw->pw_uid);
|
||||
assert(geteuid() == pw->pw_uid);
|
||||
assert(getgid() == pw->pw_gid);
|
||||
assert(getegid() == pw->pw_gid);
|
||||
}
|
||||
|
||||
static void print_usage(char *prog)
|
||||
{
|
||||
printf("%s: Usage\n", prog);
|
||||
printf(" -f, --config_file Specify a configuration file other than default\n");
|
||||
printf(" -h, --help Display this help message\n");
|
||||
printf(" -V, --version Print the program version\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
int c;
|
||||
int opt_index = 0;
|
||||
|
||||
struct option opts[] = {
|
||||
{ "config_file", 1, NULL, 'f' },
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
drop_privs();
|
||||
|
||||
while ((c = getopt_long(argc, argv, "f:hV", opts, &opt_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
if (tm_set_config_file(optarg) != 0) {
|
||||
telem_log(LOG_ERR, "Configuration file"
|
||||
" path not valid\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'V':
|
||||
printf(PACKAGE_VERSION "\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
case '?':
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (chdir(PYTHON_TELEMETRY_DIR)) {
|
||||
perror(PYTHON_TELEMETRY_DIR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Process all existing files */
|
||||
dir = opendir(PYTHON_TELEMETRY_DIR);
|
||||
if (!dir) {
|
||||
perror(PYTHON_TELEMETRY_DIR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
entry = readdir(dir);
|
||||
if (!entry) {
|
||||
break;
|
||||
}
|
||||
if (entry->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
deliver_payload(entry->d_name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@@ -110,12 +110,21 @@ static bool parse_options(int argc, char **argv)
|
||||
severity = (uint32_t)tmp;
|
||||
break;
|
||||
case 'c':
|
||||
if (opt_class != NULL) {
|
||||
free(opt_class);
|
||||
}
|
||||
opt_class = strdup(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
if (opt_payload != NULL) {
|
||||
free(opt_payload);
|
||||
}
|
||||
opt_payload = strdup(optarg);
|
||||
break;
|
||||
case 'P':
|
||||
if (opt_payload_file != NULL) {
|
||||
free(opt_payload_file);
|
||||
}
|
||||
opt_payload_file = strdup(optarg);
|
||||
break;
|
||||
case 'R':
|
||||
@@ -135,6 +144,9 @@ static bool parse_options(int argc, char **argv)
|
||||
payload_version = (uint32_t)tmp;
|
||||
break;
|
||||
case 'e':
|
||||
if (opt_event_id != NULL) {
|
||||
free(opt_event_id);
|
||||
}
|
||||
opt_event_id = strdup(optarg);
|
||||
if (opt_event_id == NULL) {
|
||||
goto fail;
|
||||
@@ -335,13 +347,13 @@ static int instanciate_record(struct telem_ref **t_ref, char *payload)
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if ((ret = opt_event_id && tm_set_event_id(*t_ref, opt_event_id)) < 0) {
|
||||
goto out1;
|
||||
if (opt_event_id) {
|
||||
if ((ret = tm_set_event_id(*t_ref, opt_event_id)) < 0) {
|
||||
goto out1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = tm_set_payload(*t_ref, payload)) < 0) {
|
||||
goto out1;
|
||||
}
|
||||
ret = tm_set_payload(*t_ref, payload);
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
@@ -356,6 +368,9 @@ static int send_record(char *payload)
|
||||
}
|
||||
|
||||
if ((ret = tm_send_record(t_ref)) < 0) {
|
||||
if (ret == -ECONNREFUSED) {
|
||||
fprintf(stderr, "Unable to send record. Make sure to opt-in to telemetry first 'telemctl opt-in'\n");
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -368,17 +383,17 @@ out:
|
||||
static int print_record(char *payload)
|
||||
{
|
||||
struct telem_ref *t_ref = NULL;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
int ret;
|
||||
|
||||
if ((ret = instanciate_record(&t_ref, payload)) == 0) {
|
||||
int i;
|
||||
for (i = 0; i < NUM_HEADERS; i++) {
|
||||
fprintf(stdout, "%s", t_ref->record->headers[i]);
|
||||
}
|
||||
fprintf(stdout, "%s\n", t_ref->record->payload);
|
||||
tm_free_record(t_ref);
|
||||
}
|
||||
|
||||
tm_free_record(t_ref);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+554
@@ -0,0 +1,554 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms and conditions of the GNU Lesser General Public License, as
|
||||
* published by the Free Software Foundation; either version 2.1 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <ftw.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define TELEM_DIR "/etc/telemetrics"
|
||||
#define TM_OPT_IN TELEM_DIR"/opt-in"
|
||||
|
||||
#define TELEM_WRK_DIRS_CONF "/usr/lib/tmpfiles.d/telemetrics-dirs.conf"
|
||||
|
||||
#define cmd_create_tmp_files "systemd-tmpfiles --create " TELEM_WRK_DIRS_CONF
|
||||
#define cmd_mk_telemdir "mkdir -p " TELEM_DIR
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
static char *SPECIAL_UNITS[] = {
|
||||
"hprobe.timer",
|
||||
"telemprobd.socket",
|
||||
"telempostd.path",
|
||||
"klogscanner.service",
|
||||
"journal-probe-tail.service",
|
||||
};
|
||||
|
||||
#define NUM_SPECIAL_UNITS ARRAY_SIZE(SPECIAL_UNITS)
|
||||
|
||||
static char *SERVICES[] = {
|
||||
"hprobe.service",
|
||||
"pstore-probe.service",
|
||||
"telemprobd.service",
|
||||
"telempostd.service",
|
||||
"journal-probe.service",
|
||||
};
|
||||
|
||||
#define NUM_SERVICES ARRAY_SIZE(SERVICES)
|
||||
|
||||
static int telemctl_start(void);
|
||||
static int telemctl_stop(void);
|
||||
static int telemctl_restart(void);
|
||||
static int telemctl_is_active(void);
|
||||
static int telemctl_opt_out(void);
|
||||
static int telemctl_opt_in(void);
|
||||
static int telemctl_journal(char *);
|
||||
|
||||
struct telemcmd {
|
||||
char *cmd;
|
||||
union {
|
||||
int (*f1)(void);
|
||||
int (*f2)(char *);
|
||||
} f;
|
||||
char *doc;
|
||||
};
|
||||
|
||||
static struct telemcmd commands[] = {
|
||||
{"stop", {.f1=telemctl_stop}, "Stops all running telemetry services" },
|
||||
{"start", {.f1=telemctl_start}, "Starts all telemetry services" },
|
||||
{"restart", {.f1=telemctl_restart}, "Restarts all telemetry services" },
|
||||
{"is-active", {.f1=telemctl_is_active},"Checks if telemprobd and telempostd are active" },
|
||||
{"opt-in", {.f1=telemctl_opt_in}, "Opts in to telemetry, and starts telemetry services" },
|
||||
{"opt-out", {.f1=telemctl_opt_out}, "Opts out of telemetry, and stops telemetry services" },
|
||||
{"journal", {.f2=telemctl_journal}, "Prints telemetry journal contents. Use -h argument with\n command for more options"}
|
||||
};
|
||||
|
||||
static int syscmd(char *cmd, char *buff, int bufflen)
|
||||
{
|
||||
int status;
|
||||
#ifdef DEBUG
|
||||
printf("[debug] [%s] %s\n", __func__, cmd);
|
||||
#endif
|
||||
FILE *fp = popen(cmd, "r");
|
||||
if (fp == NULL) {
|
||||
perror("popen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buff, bufflen, fp) != NULL) {
|
||||
;
|
||||
}
|
||||
|
||||
status = pclose(fp);
|
||||
if (status == -1) {
|
||||
perror("pclose");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
for_each_service() {
|
||||
local action=$1 && shift
|
||||
local -a array=($*)
|
||||
for service in "${array[@]}"; do
|
||||
systemctl $action $service
|
||||
[ $? -ne 0 ] && notice "Failed to $action ${service}. Continuing..."
|
||||
done
|
||||
}
|
||||
*/
|
||||
static int for_each_service(const char *command, char* services[], int numservices)
|
||||
{
|
||||
char buff[512];
|
||||
char cmd[256];
|
||||
int ret = 0, status;
|
||||
|
||||
for (int i = 0; i < numservices; i++) {
|
||||
snprintf(cmd, sizeof(cmd), "systemctl %s %s", command, services[i]);
|
||||
memset(buff, 0, sizeof(buff));
|
||||
status = syscmd(cmd, buff, sizeof(buff));
|
||||
if (status != 0 || buff[0] != 0) {
|
||||
fprintf(stderr, "%s", buff);
|
||||
fprintf(stderr, "Failed to %s %s. Continuing...", command, services[i]);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_start() {
|
||||
[ -f $OPT_OUT_FILE ] && exit_err "Opt out is enabled. Cannot start services."
|
||||
create_work_dirs
|
||||
for_each_service "start" ${SPECIAL_UNITS[@]}
|
||||
}
|
||||
|
||||
Modified to add explicit opt-in
|
||||
*/
|
||||
static int telemctl_start(void)
|
||||
{
|
||||
char buff[512];
|
||||
int status, ret;
|
||||
|
||||
if (access(TM_OPT_IN, F_OK) != 0) {
|
||||
fprintf(stderr, "Opt in to telemetry first.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Creates dirs if missing, adjust ownership if exists */
|
||||
memset(buff, 0, sizeof(buff));
|
||||
|
||||
/* Execute "systemd-tmpfiles --create ${TELEM_WRK_DIRS_CONF}" */
|
||||
status = syscmd(cmd_create_tmp_files, buff, sizeof(buff));
|
||||
fprintf(stderr, "%s", buff);
|
||||
|
||||
if (status == -1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = for_each_service("start", SPECIAL_UNITS, NUM_SPECIAL_UNITS);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_stop() {
|
||||
for_each_service "stop" ${SPECIAL_UNITS[@]}
|
||||
for_each_service "stop" ${SERVICES[@]}
|
||||
}
|
||||
*/
|
||||
static int telemctl_stop(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* the special units must be stopped first so that activation no longer happens */
|
||||
ret = for_each_service("stop", SPECIAL_UNITS, NUM_SPECIAL_UNITS);
|
||||
ret |= for_each_service("stop", SERVICES, NUM_SERVICES);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
*
|
||||
telem_restart() {
|
||||
telem_stop
|
||||
telem_start
|
||||
}
|
||||
*/
|
||||
static int telemctl_restart(void)
|
||||
{
|
||||
if (telemctl_stop() == 0) {
|
||||
return telemctl_start();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_is_active() {
|
||||
echo "telemprobd :" $(systemctl is-active telemprobd.socket)
|
||||
echo "telempostd :" $(systemctl is-active telempostd.path)
|
||||
}
|
||||
*/
|
||||
|
||||
static int telemctl_is_active(void)
|
||||
{
|
||||
char buff[256];
|
||||
|
||||
memset(buff, 0, sizeof(buff));
|
||||
if (syscmd("systemctl is-active telemprobd.socket", buff, sizeof(buff)) != -1) {
|
||||
printf("telemprobd : %s", buff);
|
||||
memset(buff, 0, sizeof(buff));
|
||||
if (syscmd("systemctl is-active telempostd.path",buff, sizeof(buff)) != -1) {
|
||||
printf("telempostd : %s", buff);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
|
||||
{
|
||||
int rv = remove(fpath);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "[debug] [%s] remove fpath:%s rv:%d\n", __func__, fpath, rv);
|
||||
#endif
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
/* rm -rf path
|
||||
*
|
||||
* We run as root, so be extra careful when deleting folders.
|
||||
* We only delete folders owned by telemetry:telemetry.
|
||||
* As for the files, they can be owned by root.
|
||||
*/
|
||||
static int rm_rf(char *path)
|
||||
{
|
||||
struct stat info;
|
||||
if (stat(path, &info) == 0) {
|
||||
struct passwd *pw = getpwuid(info.st_uid);
|
||||
if (pw == NULL) {
|
||||
perror("getpwuid");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pw->pw_name, "telemetry") != 0) {
|
||||
fprintf(stderr, "Not removing \"%s\": Incorrect folder owner \"%s\"\n",
|
||||
path, pw->pw_name);
|
||||
return -1;
|
||||
}
|
||||
struct group *gr = getgrgid(info.st_gid);
|
||||
if (gr == NULL) {
|
||||
perror("getgrgid");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(gr->gr_name, "telemetry") != 0) {
|
||||
fprintf(stderr, "Not removing \"%s\": Incorrect folder group \"%s\"\n",
|
||||
path, gr->gr_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS);
|
||||
} else {
|
||||
// Some folders are subfolders of folders already recursivley deleted.
|
||||
// So they may not exist anymore.
|
||||
if (errno != ENOENT) {
|
||||
fprintf(stderr, "file: %s :", path);
|
||||
perror("stat");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_remove_work_dirs() {
|
||||
# Remove dirs
|
||||
awk '/^d/{print $2}' ${TELEM_WRK_DIRS_CONF} | xargs rm -rf;
|
||||
}
|
||||
|
||||
Notes:
|
||||
Parse /usr/lib/tmpfiles.d/telemetrics-dirs.conf
|
||||
This file was used to create the folders needed by telemetry.
|
||||
Now we want to delete them. The file contents is as:
|
||||
|
||||
d /usr/local/var/lib/telemetry 0755 telemetry telemetry -
|
||||
d /usr/local/var/spool/telemetry 0750 telemetry telemetry -
|
||||
d /usr/local/var/log/telemetry 0750 telemetry telemetry -
|
||||
d /usr/local/var/log/telemetry/records 0750 telemetry telemetry -
|
||||
d /usr/local/var/cache/telemetry 0750 telemetry telemetry -
|
||||
d /usr/local/var/cache/telemetry/pstore 0750 telemetry telemetry -
|
||||
*/
|
||||
static int telemctl_remove_work_dirs(void)
|
||||
{
|
||||
FILE *fp = fopen(TELEM_WRK_DIRS_CONF, "r");
|
||||
if (fp == NULL){
|
||||
fprintf(stderr, "Could not open file %s", TELEM_WRK_DIRS_CONF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
char folder[PATH_MAX+1];
|
||||
char line[PATH_MAX+30];
|
||||
|
||||
if (fgets(line, sizeof(line), fp) == NULL) {
|
||||
if (ferror(fp)) {
|
||||
fprintf(stderr, "Error reading file %s\n", TELEM_WRK_DIRS_CONF);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
// EOF
|
||||
break;
|
||||
}
|
||||
|
||||
int ret = sscanf(line, "d %s %*s telemetry telemetry - \n", folder);
|
||||
if (ret == 1) {
|
||||
/* Delete the folder. We may get an error trying to delete
|
||||
* folders already deleted. We ignore them, so don't bother
|
||||
* checking rmrtf return value */
|
||||
rm_rf(folder);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mk_telem_dir(void)
|
||||
{
|
||||
char buff[512];
|
||||
int status;
|
||||
struct stat sb;
|
||||
|
||||
if (stat(TELEM_DIR, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
#ifdef DEBUG
|
||||
printf("[debug] [%s] Folder %s exists\n", __func__, TELEM_DIR);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(buff, 0, sizeof(buff));
|
||||
|
||||
/* Execute "mkdir -p TM_DIR" */
|
||||
status = syscmd(cmd_mk_telemdir, buff, sizeof(buff));
|
||||
fprintf(stderr, "%s", buff);
|
||||
|
||||
if (status == -1 || buff[0] != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_opt_out() {
|
||||
[ -f $OPT_OUT_FILE ] && exit_ok "Already opted out. Nothing to do."
|
||||
mkdir -p $TELEM_DIR || exit_err "Failed to create ${TELEM_DIR}."
|
||||
touch $OPT_OUT_FILE || exit_err "Failed to create ${OPT_OUT_FILE}."
|
||||
telem_stop
|
||||
telem_remove_work_dirs
|
||||
}
|
||||
*/
|
||||
static int telemctl_opt_out(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Remove TM_OPT_IN file */
|
||||
if (unlink(TM_OPT_IN) != 0) {
|
||||
if (errno == ENOENT) {
|
||||
fprintf(stderr, "Already opted out. Nothing to do.\n");
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr, "Failed to remove %s.\n", TM_OPT_IN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = telemctl_stop();
|
||||
ret |= telemctl_remove_work_dirs();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_opt_in() {
|
||||
[ ! -f $OPT_OUT_FILE ] && exit_ok "Already opted in. Nothing to do."
|
||||
rm -f $OPT_OUT_FILE || exit_err "Failed to remove ${OPT_OUT_FILE}."
|
||||
telem_start
|
||||
}
|
||||
|
||||
Modified to add explicit opt-in
|
||||
*/
|
||||
static int telemctl_opt_in(void)
|
||||
{
|
||||
|
||||
/* Ensure TELEM_DIR exists */
|
||||
if (mk_telem_dir() != 0) {
|
||||
fprintf(stderr, "Failed to create %s\n", TELEM_DIR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create a brand new file TM_OPT_IN, we maight fail because the file exists already.
|
||||
* In that case we are already opted in and we are done here. */
|
||||
int fd = open(TM_OPT_IN, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||
if (fd == -1) {
|
||||
if (errno == EEXIST) {
|
||||
fprintf(stderr, "Already opted in. Nothing to do.\n");
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "Failed to create %s.\n", TM_OPT_IN);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int journal_cmd(char *cmd)
|
||||
{
|
||||
int status;
|
||||
char buff[256];
|
||||
#ifdef DEBUG
|
||||
printf("[debug] [%s] %s\n", __func__, cmd);
|
||||
#endif
|
||||
FILE *fp = popen(cmd, "r");
|
||||
if (fp == NULL) {
|
||||
perror("popen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buff, sizeof(buff), fp) != NULL) {
|
||||
printf("%s", buff);
|
||||
}
|
||||
|
||||
status = pclose(fp);
|
||||
if (status == -1) {
|
||||
perror("pclose");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static char* concatargs(int argc, char** argv)
|
||||
{
|
||||
size_t len = strlen("telem_journal") + 1;
|
||||
for (int i = 2; i < argc; i++) {
|
||||
len += strlen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
char *buff = malloc(len*sizeof(char));
|
||||
|
||||
if (buff != NULL) {
|
||||
buff[0] = '\0';
|
||||
strcat(buff,"telem_journal ");
|
||||
|
||||
for (int i = 2; i < argc; i++) {
|
||||
strcat(buff, argv[i]);
|
||||
strcat(buff, " ");
|
||||
}
|
||||
}
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
static int telemctl_journal(char * x)
|
||||
{
|
||||
journal_cmd(x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_usage(char *str)
|
||||
{
|
||||
printf("%s - Control actions for telemetry services\n\n", str);
|
||||
|
||||
for (int i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) {
|
||||
printf(" %-9s %s\n", commands[i].cmd, commands[i].doc);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, ret = EXIT_SUCCESS;
|
||||
bool is_root;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
if (argc == 1) {
|
||||
print_usage(argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
is_root = getuid()?false:true;
|
||||
|
||||
for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) {
|
||||
if (strcmp(commands[i].cmd, argv[1]) == 0) {
|
||||
if (!is_root) {
|
||||
fprintf(stderr, "Must be root to run this command. Exiting...\n");
|
||||
exit(1);
|
||||
}
|
||||
/* Special treatment for "journal", it can have cmd line arguments */
|
||||
if (strcmp(argv[1],"journal") != 0) {
|
||||
if (argc != 2) {
|
||||
print_usage(argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
ret = commands[i].f.f1();
|
||||
} else {
|
||||
char *buff = concatargs(argc, argv);
|
||||
if (buff != NULL) {
|
||||
ret = commands[i].f.f2(buff);
|
||||
free(buff);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == sizeof(commands)/sizeof(commands[0])) {
|
||||
printf("Unknown command passed to %s\n\n", argv[0]);
|
||||
print_usage(argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
exit(ret);
|
||||
}
|
||||
+76
-53
@@ -36,6 +36,8 @@
|
||||
#include "log.h"
|
||||
#include "configuration.h"
|
||||
|
||||
static void process_record(TelemDaemon *daemon, client *cl);
|
||||
|
||||
void initialize_probe_daemon(TelemDaemon *daemon)
|
||||
{
|
||||
client_list_head head;
|
||||
@@ -80,7 +82,8 @@ bool is_client_list_empty(client_list_head *client_head)
|
||||
return (client_head->lh_first == NULL);
|
||||
}
|
||||
|
||||
void terminate_client(TelemDaemon *daemon, client *cl, nfds_t index)
|
||||
|
||||
static void terminate_client(TelemDaemon *daemon, client *cl, nfds_t index)
|
||||
{
|
||||
/* Remove fd from the pollfds array */
|
||||
del_pollfd(daemon, index);
|
||||
@@ -91,24 +94,40 @@ void terminate_client(TelemDaemon *daemon, client *cl, nfds_t index)
|
||||
remove_client(&(daemon->client_head), cl);
|
||||
}
|
||||
|
||||
bool handle_client(TelemDaemon *daemon, nfds_t ind, client *cl)
|
||||
/*
|
||||
See "tm_send_record" for record retails.
|
||||
|
||||
recv buffer layout:
|
||||
* <uint32_t record_size> : so recv knows how much to read
|
||||
* <custom cfg file field> : optional, variable size (string)
|
||||
* <uint32_t header_size>
|
||||
* <headers + Payload>
|
||||
* <null-byte>
|
||||
|
||||
The routine handle_client only cares about "record_size".
|
||||
However, we need to validate if the record_size is reasonable. We assume the
|
||||
worst case scenario would be a record with max cfg file field. There is no
|
||||
exact way to determine header_size, so we assume each line at most 80 chars.
|
||||
|
||||
*/
|
||||
|
||||
#define MAX_RECORD_SIZE (2*sizeof(uint32_t) + CFG_PREFIX_LENGTH + PATH_MAX + \
|
||||
MAX_PAYLOAD_LENGTH + NUM_HEADERS*80)
|
||||
bool handle_client(TelemDaemon *daemon, nfds_t index, client *cl)
|
||||
{
|
||||
/* For now read data from fd */
|
||||
ssize_t len;
|
||||
size_t record_size = 0;
|
||||
size_t buf_size;
|
||||
bool processed = false;
|
||||
uint32_t record_size;
|
||||
|
||||
if (!cl->buf) {
|
||||
cl->buf = malloc(RECORD_SIZE_LEN);
|
||||
cl->size = RECORD_SIZE_LEN;
|
||||
}
|
||||
if (!cl->buf) {
|
||||
telem_log(LOG_ERR, "Unable to allocate memory, exiting\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (cl->buf != NULL) {
|
||||
free(cl->buf);
|
||||
cl->buf = NULL;
|
||||
}
|
||||
|
||||
malloc_trim(0);
|
||||
len = recv(cl->fd, cl->buf, RECORD_SIZE_LEN, MSG_PEEK | MSG_DONTWAIT);
|
||||
len = recv(cl->fd, &record_size, RECORD_SIZE_LEN, MSG_PEEK | MSG_DONTWAIT);
|
||||
if (len < 0) {
|
||||
telem_log(LOG_ERR, "Failed to talk to client %d: %s\n", cl->fd,
|
||||
strerror(errno));
|
||||
@@ -120,6 +139,39 @@ bool handle_client(TelemDaemon *daemon, nfds_t ind, client *cl)
|
||||
goto end_client;
|
||||
}
|
||||
|
||||
/* Read the record size first */
|
||||
len = recv(cl->fd, &record_size, RECORD_SIZE_LEN, 0);
|
||||
if (len < 0) {
|
||||
telem_log(LOG_ERR, "Failed to receive data from client"
|
||||
" %d: %s\n", cl->fd, strerror(errno));
|
||||
goto end_client;
|
||||
} else if (len == 0) {
|
||||
telem_log(LOG_DEBUG, "End of transmission for client"
|
||||
" %d\n", cl->fd);
|
||||
goto end_client;
|
||||
}
|
||||
|
||||
/* Now that we know the record size, allocate a new buffer
|
||||
* for the record body. We don't need to record size itself in the body.
|
||||
*/
|
||||
|
||||
if (record_size <= RECORD_SIZE_LEN || record_size > MAX_RECORD_SIZE) {
|
||||
telem_log(LOG_ERR, "Record size %u greater tham maximum allowed %lu."
|
||||
"Recored ignored\n", record_size,
|
||||
MAX_RECORD_SIZE);
|
||||
goto end_client;
|
||||
}
|
||||
|
||||
buf_size = record_size - RECORD_SIZE_LEN;
|
||||
cl->buf = calloc(1, buf_size);
|
||||
if (!cl->buf) {
|
||||
telem_log(LOG_ERR, "Unable to allocate memory, exiting\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cl->size = buf_size;
|
||||
cl->offset = 0;
|
||||
|
||||
/* Read the actual record*/
|
||||
do {
|
||||
malloc_trim(0);
|
||||
len = recv(cl->fd, cl->buf + cl->offset, cl->size - cl->offset, 0);
|
||||
@@ -134,36 +186,11 @@ bool handle_client(TelemDaemon *daemon, nfds_t ind, client *cl)
|
||||
}
|
||||
|
||||
cl->offset += (size_t)len;
|
||||
if (cl->offset < RECORD_SIZE_LEN) {
|
||||
continue;
|
||||
}
|
||||
if (cl->size == RECORD_SIZE_LEN) {
|
||||
record_size = *(uint32_t *)(cl->buf);
|
||||
telem_log(LOG_DEBUG, "Total size of record: %zu\n", record_size);
|
||||
if (record_size == 0) { //record_size < RECORD_MIN_SIZE || record_size > RECORD_MAX_SIZE
|
||||
goto end_client;
|
||||
}
|
||||
// We just processed the record size field, so the remaining format
|
||||
// is (header size field + record body + terminating '\0' byte)
|
||||
cl->size = sizeof(uint32_t) + record_size + 1;
|
||||
cl->buf = realloc(cl->buf, cl->size);
|
||||
memset(cl->buf, 0, cl->size);
|
||||
cl->offset = 0;
|
||||
if (!cl->buf) {
|
||||
telem_log(LOG_ERR, "Unable to allocate memory, exiting\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (cl->offset != cl->size) {
|
||||
/* full record not received yet */
|
||||
continue;
|
||||
}
|
||||
if (cl->size != RECORD_SIZE_LEN) {
|
||||
/* entire record has been received */
|
||||
|
||||
if (cl->offset == cl->size) {
|
||||
process_record(daemon, cl);
|
||||
/* TODO: cleanup or terminate? */
|
||||
cl->offset = 0;
|
||||
cl->size = RECORD_SIZE_LEN;
|
||||
free(cl->buf);
|
||||
cl->buf = NULL;
|
||||
processed = true;
|
||||
telem_debug("DEBUG: Record processed for client %d\n", cl->fd);
|
||||
break;
|
||||
@@ -172,7 +199,7 @@ bool handle_client(TelemDaemon *daemon, nfds_t ind, client *cl)
|
||||
|
||||
end_client:
|
||||
telem_log(LOG_DEBUG, "Processed client %d: %s\n", cl->fd, processed ? "true" : "false");
|
||||
terminate_client(daemon, cl, ind);
|
||||
terminate_client(daemon, cl, index);
|
||||
return processed;
|
||||
}
|
||||
|
||||
@@ -222,14 +249,14 @@ char *read_machine_id_override()
|
||||
return machine_override;
|
||||
}
|
||||
|
||||
void machine_id_replace(char **machine_header, char *machine_id_override)
|
||||
static void machine_id_replace(char **machine_header, char *machine_id_override)
|
||||
{
|
||||
char machine_id[33] = { 0 };
|
||||
char *old_header;
|
||||
int ret;
|
||||
|
||||
if (machine_id_override) {
|
||||
strcpy(machine_id, machine_id_override);
|
||||
strncpy(machine_id, machine_id_override, sizeof(machine_id)-1);
|
||||
} else {
|
||||
if (!get_machine_id(machine_id)) {
|
||||
// TODO: decide if error handling is needed here
|
||||
@@ -255,23 +282,19 @@ static void stage_record(char *filepath, char *headers[], char *body, char *cfg_
|
||||
telem_debug("DEBUG: filepath:%s\n", filepath);
|
||||
telem_debug("DEBUG: body:%s\n", body);
|
||||
telem_debug("DEBUG: cfg:%s\n", cfg_file);
|
||||
// Use default path if not provided
|
||||
|
||||
if (filepath == NULL) {
|
||||
telem_log(LOG_ERR, "filepath value must be provided, aborting\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tmpfd = mkstemp(filepath);
|
||||
if (!tmpfd) {
|
||||
if (tmpfd < 0) {
|
||||
telem_perror("Error opening staging file");
|
||||
close(tmpfd);
|
||||
if (unlink(filepath)) {
|
||||
telem_perror("Error deleting staging file");
|
||||
}
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// open file
|
||||
// access the opened file as a stream
|
||||
tmpfile = fdopen(tmpfd, "a");
|
||||
if (!tmpfile) {
|
||||
telem_perror("Error opening temp stage file");
|
||||
@@ -292,7 +315,7 @@ static void stage_record(char *filepath, char *headers[], char *body, char *cfg_
|
||||
fprintf(tmpfile, "%s\n", headers[i]);
|
||||
}
|
||||
|
||||
//write body
|
||||
// write body
|
||||
fprintf(tmpfile, "%s\n", body);
|
||||
fflush(tmpfile);
|
||||
fclose(tmpfile);
|
||||
@@ -302,7 +325,7 @@ clean_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void process_record(TelemDaemon *daemon, client *cl)
|
||||
static void process_record(TelemDaemon *daemon, client *cl)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
@@ -430,7 +453,7 @@ bool get_machine_id(char *machine_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = fscanf(id_file, "%s", machine_id);
|
||||
ret = fscanf(id_file, "%32s", machine_id);
|
||||
if (ret != 1) {
|
||||
telem_perror("Could not read machine id from file");
|
||||
fclose(id_file);
|
||||
|
||||
@@ -125,27 +125,6 @@ void remove_client(client_list_head *client_head, client *cl);
|
||||
*/
|
||||
bool is_client_list_empty(client_list_head *client_head);
|
||||
|
||||
/**
|
||||
* Terminate a client connection
|
||||
*
|
||||
* @param daemon Pointer to the daemon
|
||||
* @param cl Pointer to the client in the client list
|
||||
* @param index The index of the client file descriptor in the poll fd
|
||||
* array
|
||||
*
|
||||
*/
|
||||
void terminate_client(TelemDaemon *daemon, client *cl, nfds_t index);
|
||||
|
||||
/**
|
||||
* Process record from a client
|
||||
*
|
||||
* @param daemon Pointer to the daemon
|
||||
* @param cl Pointer to the client in the client list
|
||||
*
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
void process_record(TelemDaemon *daemon, client *cl);
|
||||
|
||||
/**
|
||||
* Get random machine id stored in file
|
||||
*
|
||||
|
||||
+18
-28
@@ -913,14 +913,6 @@ int tm_create_record(struct telem_ref **t_ref, uint32_t severity,
|
||||
char *classification, uint32_t payload_version)
|
||||
{
|
||||
int ret = 0;
|
||||
int k = 0;
|
||||
struct stat unused;
|
||||
|
||||
k = stat(TM_OPT_OUT_FILE, &unused);
|
||||
if (k == 0) {
|
||||
// Bail early if opt-out is enabled
|
||||
return -ECONNREFUSED;
|
||||
}
|
||||
|
||||
*t_ref = (struct telem_ref *)malloc(sizeof(struct telem_ref));
|
||||
if (*t_ref == NULL) {
|
||||
@@ -984,14 +976,6 @@ int tm_set_payload(struct telem_ref *t_ref, char *payload)
|
||||
{
|
||||
size_t payload_len;
|
||||
int ret = 0;
|
||||
int k = 0;
|
||||
struct stat unused;
|
||||
|
||||
k = stat(TM_OPT_OUT_FILE, &unused);
|
||||
if (k == 0) {
|
||||
// Bail early if opt-out is enabled
|
||||
return -ECONNREFUSED;
|
||||
}
|
||||
|
||||
payload_len = strlen((char *)payload);
|
||||
|
||||
@@ -1053,7 +1037,7 @@ int tm_set_event_id(struct telem_ref *t_ref, char *event_id)
|
||||
int rc = -1;
|
||||
|
||||
if (!validate_event_id(event_id)) {
|
||||
if (t_ref && t_ref->record && t_ref->record->headers) {
|
||||
if (t_ref && t_ref->record) {
|
||||
// free default id before overriding
|
||||
free(t_ref->record->headers[TM_EVENT_ID]);
|
||||
// set new event_id
|
||||
@@ -1215,6 +1199,17 @@ out1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tm_is_opted_in(void)
|
||||
{
|
||||
struct stat unused;
|
||||
|
||||
if (stat(TM_OPT_IN_FILE, &unused) == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tm_send_record(struct telem_ref *t_ref)
|
||||
{
|
||||
int i;
|
||||
@@ -1224,14 +1219,11 @@ int tm_send_record(struct telem_ref *t_ref)
|
||||
char *data = NULL;
|
||||
size_t offset = 0;
|
||||
int ret = 0;
|
||||
int k = 0;
|
||||
struct stat unused;
|
||||
size_t cfg_file_name_size = 0;
|
||||
const char *cfg_file_name = NULL;
|
||||
|
||||
k = stat(TM_OPT_OUT_FILE, &unused);
|
||||
if (k == 0) {
|
||||
// Bail early if opt-out is enabled
|
||||
if (tm_is_opted_in() == 0) {
|
||||
// Bail early if opt-in is not existent
|
||||
return -ECONNREFUSED;
|
||||
}
|
||||
|
||||
@@ -1272,8 +1264,8 @@ int tm_send_record(struct telem_ref *t_ref)
|
||||
|
||||
/*
|
||||
* Allocating buffer for what we intend to send. Buffer layout is:
|
||||
* <uint32_t total_size> : so recv knows how much to read
|
||||
* <custom cfg file field> : optional
|
||||
* <uint32_t record_size> : so recv knows how much to read
|
||||
* <custom cfg file field> : optional
|
||||
* <uint32_t header_size>
|
||||
* <headers + Payload>
|
||||
* <null-byte>
|
||||
@@ -1281,16 +1273,14 @@ int tm_send_record(struct telem_ref *t_ref)
|
||||
*/
|
||||
record_size = (2 * sizeof(uint32_t)) + total_size + 1;
|
||||
|
||||
data = malloc(record_size);
|
||||
data = calloc(sizeof(char), record_size);
|
||||
if (!data) {
|
||||
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
|
||||
close(sfd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(data, 0, record_size);
|
||||
|
||||
memcpy(data, &total_size, sizeof(uint32_t));
|
||||
memcpy(data, &record_size, sizeof(uint32_t));
|
||||
offset += sizeof(uint32_t);
|
||||
|
||||
if (cfg_file_name != NULL) {
|
||||
|
||||
@@ -120,6 +120,13 @@ int tm_set_payload(struct telem_ref *t_ref, char *payload);
|
||||
*/
|
||||
int tm_send_record(struct telem_ref *t_ref);
|
||||
|
||||
/**
|
||||
* Checks if telemetry was opted in
|
||||
*
|
||||
* @return 1 when opt-in, or 0 when opt-out
|
||||
*/
|
||||
int tm_is_opted_in(void);
|
||||
|
||||
/**
|
||||
* Release the memory allocated to a telemetrics record.
|
||||
*
|
||||
|
||||
@@ -21,3 +21,8 @@ TM_4_0_0 {
|
||||
global:
|
||||
tm_set_event_id;
|
||||
} TM_3_0_0;
|
||||
|
||||
TM_4_1_0 {
|
||||
global:
|
||||
tm_is_opted_in;
|
||||
} TM_4_0_0;
|
||||
|
||||
@@ -363,8 +363,8 @@ save_err:
|
||||
|
||||
static void save_entry_to_journal(TelemPostDaemon *daemon, time_t t_stamp, char *headers[])
|
||||
{
|
||||
char *classification_value;
|
||||
char *event_id_value;
|
||||
char *classification_value = NULL;
|
||||
char *event_id_value = NULL;
|
||||
|
||||
if (get_header_value(headers[TM_CLASSIFICATION], &classification_value) &&
|
||||
get_header_value(headers[TM_EVENT_ID], &event_id_value)) {
|
||||
@@ -496,7 +496,7 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
|
||||
bool ret = false;
|
||||
char *headers[NUM_HEADERS];
|
||||
char *body = NULL;
|
||||
struct stat buf;
|
||||
struct stat buf = { 0 };
|
||||
time_t current_time = time(NULL);
|
||||
int64_t max_spool_size = 0;
|
||||
char *cfg_file = NULL;
|
||||
@@ -520,7 +520,7 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
|
||||
}
|
||||
|
||||
/** Update spool directory size **/
|
||||
(daemon->current_spool_size) += (buf.st_blocks * 512);
|
||||
daemon->current_spool_size += (buf.st_blocks * 512);
|
||||
|
||||
/** Check that record is not expired **/
|
||||
if (!S_ISREG(buf.st_mode) ||
|
||||
@@ -574,7 +574,7 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
|
||||
end_processing_file:
|
||||
/** Update spool size if record will be removed **/
|
||||
if (ret) {
|
||||
(daemon->current_spool_size) -= (buf.st_blocks * 512);
|
||||
daemon->current_spool_size -= (buf.st_blocks * 512);
|
||||
}
|
||||
telem_log(LOG_DEBUG, "spool_size: %ld\n", daemon->current_spool_size);
|
||||
free(body);
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ bool get_header_value(const char *header, char **value)
|
||||
*value = strdup(sep);
|
||||
}
|
||||
|
||||
return (bool)(value != NULL);
|
||||
return (bool)(*value != NULL);
|
||||
}
|
||||
|
||||
void *reallocate(void **addr, size_t *allocated, size_t requested)
|
||||
|
||||
@@ -41,7 +41,7 @@ void create_setup(void)
|
||||
* with the libcheck API...
|
||||
*/
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run these tests");
|
||||
"First time opt-in required to run test");
|
||||
}
|
||||
|
||||
START_TEST(record_create_non_null)
|
||||
@@ -98,12 +98,22 @@ void create_teardown(void)
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(is_opt_in)
|
||||
{
|
||||
int ret;
|
||||
ret = tm_is_opted_in();
|
||||
/* Smoke testing function */
|
||||
ck_assert_msg(ret == 0 || ret == 1,
|
||||
"Something wrong with opt-in check");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(record_create_invalid_class1)
|
||||
{
|
||||
int ret;
|
||||
ret = tm_create_record(&ref, 1, "t/t", 2000);
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
ck_assert(ret == -EINVAL);
|
||||
}
|
||||
END_TEST
|
||||
@@ -113,7 +123,7 @@ START_TEST(record_create_invalid_class2)
|
||||
int ret;
|
||||
ret = tm_create_record(&ref, 1, "t/t/t/t", 2000);
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
ck_assert(ret == -EINVAL);
|
||||
}
|
||||
END_TEST
|
||||
@@ -126,7 +136,7 @@ START_TEST(record_create_severity_underflow)
|
||||
// Severity of 0 is too low; raise it to 1, the minimum
|
||||
ret = tm_create_record(&ref, 0, "a/a/a", 2000);
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
|
||||
if (asprintf(&result, "%s: %u\n", TM_SEVERITY_STR, 1) < 0) {
|
||||
return;
|
||||
@@ -146,7 +156,7 @@ START_TEST(record_create_severity_overflow)
|
||||
// Severity of 5 is too high; lower it to 4, the maximum
|
||||
ret = tm_create_record(&ref, 5, "b/b/b", 2000);
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
|
||||
if (asprintf(&result, "%s: %u\n", TM_SEVERITY_STR, 4) < 0) {
|
||||
return;
|
||||
@@ -172,7 +182,7 @@ void event_id_setup(void)
|
||||
return;
|
||||
}
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
}
|
||||
|
||||
START_TEST(record_set_event_id)
|
||||
@@ -252,6 +262,10 @@ Suite *lib_suite(void)
|
||||
tcase_add_test(t, record_create_version);
|
||||
suite_add_tcase(s, t);
|
||||
|
||||
t = tcase_create("Opt-in");
|
||||
tcase_add_test(t, is_opt_in);
|
||||
suite_add_tcase(s, t);
|
||||
|
||||
t = tcase_create("invalid classification");
|
||||
tcase_add_test(t, record_create_invalid_class1);
|
||||
tcase_add_test(t, record_create_invalid_class2);
|
||||
|
||||
Reference in New Issue
Block a user