Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Packaging #148

Open
wants to merge 9 commits into
base: linux-diagnostics-with-packaging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".

if ! shellcheck -S error NfsDiagnostics/nfsclientlogs.sh SMBDiagnostics/smbclientlogs.sh
then
echo "Shellcheck failed"
exit 1
fi
54 changes: 54 additions & 0 deletions .github/workflows/packaging-action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Package NFS and CIFS diagnostic scripts
run-name: Package NFS and CIFS diagnostic scripts
on: [push]

jobs:
package:
runs-on: ubuntu-latest

steps:
# - name: Download version artifact
# continue-on-error: true
# uses: actions/download-artifact@v3
# with:
# name: version
# path: packaging


- name: Set up environment
run: |
sudo apt install -y shellcheck
sudo apt install -y rpm
sudo apt install -y build-essential
sudo apt install -y debhelper

- name: Checkout Repository
uses: actions/checkout@v3

- name: ShellCheck-Validation
run: |
if ! shellcheck -S error NfsDiagnostics/nfsclientlogs.sh SMBDiagnostics/smbclientlogs.sh; then echo "ShellCheck Failed"; exit 1; fi

- name: Build Packages
run: |
cd packaging
make

- name: Upload Debian Package
uses: actions/upload-artifact@v3
with:
name: debian-package
path: packaging/*.deb

- name: Upload RPM Package
uses: actions/upload-artifact@v3
with:
name: rpm-package
path: packaging/*.rpm

# - name: Update Future Version
# uses: actions/upload-artifact@v3
# with:
# name: version
# path: packaging/VERSION.txt

16 changes: 12 additions & 4 deletions NfsDiagnostics/nfsclientlogs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
PIDFILE="/tmp/nfsclientlog.pid"
DIRNAME="./output"
NFS_PORT=2049
TRACE_NFSBPF_ABS_PATH="$(cd "$(dirname "trace-nfsbpf")" && pwd)/$(basename "trace-nfsbpf")"
#TRACE_NFSBPF_ABS_PATH="$(cd "$(dirname "trace-nfsbpf")" && pwd)/$(basename "trace-nfsbpf")"
TRACE_NFSBPF_ABS_PATH="/opt/xstore/lib/NfsDiagnostics/trace-nfsbpf"
PYTHON_PROG='python'
STDLOG_FILE='/dev/null'


# to enable backward compatibility.
_trace_nfsfsbpf_alt_path="$(cd "$(dirname "trace-nfsbpf")" && pwd)/$(basename "trace-nfsbpf")"
if [[ -f "${_trace_nfsbpf_alt_path}" ]];
then
TRACE_NFSBPF_ABS_PATH="${_trace_nfsbpf_alt_path}"
fi

main() {
if [[ "$*" =~ "v3b" ]]
then
Expand All @@ -23,7 +31,7 @@ main() {
then
stop 0<&- > "${STDLOG_FILE}" 2>&1
else
echo "Usage: ./nfsclientlogs.sh <v3b | v4> <> <start | stop> <CaptureNetwork> <OnAnomaly>"
echo "Usage: diag-main.sh nfs <v3b | v4> <start | stop> <CaptureNetwork> <OnAnomaly>"
exit 1
fi

Expand All @@ -45,7 +53,7 @@ start() {

init() {
check_utils
rm -r "$DIRNAME"
rm -rf "$DIRNAME"
mkdir -p "$DIRNAME"

dmesg -Tc > /dev/null
Expand Down Expand Up @@ -91,7 +99,7 @@ capture_network() {
}

trace_nfsbpf() {
nohup "${PYTHON_PROG}" "${TRACE_NFSBPF_ABS_PATH}" "${DIRNAME}" 0<&- 2>&1 &
nohup /usr/bin/env "${PYTHON_PROG}" "${TRACE_NFSBPF_ABS_PATH}" "${DIRNAME}" 0<&- 2>&1 &
}

stop() {
Expand Down
22 changes: 12 additions & 10 deletions NfsDiagnostics/trace-nfsbpf
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/usr/bin/python
Copy link
Collaborator

@ksub42 ksub42 Jul 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, Python3 is not available by default on at least some of the distros that we support (RHEL 7?). It might be a better idea to invoke Python as /usr/bin/env python. IIRC the scripts work the same across Python 2 & 3.

#!/usr/bin/env python
from bcc import BPF
from bcc.utils import printb
from time import sleep
import os
from sys import argv
from datetime import datetime
# define BPF program
bpf_text= """
#include <linux/sched.h>
Expand Down Expand Up @@ -90,10 +91,10 @@ b.attach_tracepoint(tp="nfs:nfs_commit_error", fn_name="trace_page_error")
b.attach_tracepoint(tp="nfs:nfs_pgio_error", fn_name="trace_pgio_error")
b.attach_tracepoint(tp="nfs:nfs_writeback_page_exit", fn_name="trace_inode_event")
b.attach_tracepoint(tp="nfs:nfs_writeback_inode_exit", fn_name="trace_inode_event")
print("Running Anomaly")
class stop_and_collapse(Exception):
pass

print(f"[{str(datetime.now())}] Running Anomaly Mode")
while 1:
try:
sleep(1);
Expand All @@ -109,17 +110,18 @@ while 1:
break;

output_dir = argv[1]
print("Exiting Anomaly")
fd=open("/tmp/nfsclientlog.pid", "r");
# trace_pid=fd.readline();
tcpdump_pid=fd.readline();
print(tcpdump_pid)
command = "kill -INT %s" % (tcpdump_pid)
os.system(command);
# command = "kill -INT %s" % (trace_pid)
print(f"[{str(datetime.now())}] Exiting Anomaly Mode")
if(os.path.exists("/tmp/nfsclientlog.pid")):
fd=open("/tmp/nfsclientlog.pid", "r");
tcpdump_pid=fd.readline();
command = "kill -INT %s" % (tcpdump_pid)
os.system(command);

command = "trace-cmd stop"
os.system(command);
sleep(3)

os.system(f"trace-cmd extract")
os.system(f"trace-cmd report 2>&1 > {output_dir}/nfs_trace")
os.system("trace-cmd reset")
os.system(f"sudo dmesg -c > {output_dir}/nfs_dmesg")
Expand Down
10 changes: 10 additions & 0 deletions README_hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Git Hooks
- The hooks need to be enabled manually by the contributor.
- To enable hooks, change the default hook directory by `git config core.hooksPath .githooks` or manually copy hooks from `.githooks` to `.git/hooks`
- New validations can be added to `.githooks/pre-commit`.


# GitHub Actions
- Github actions are stored in .github/workflow
- To modify automatic packaging process (for cifs and nfs diagnostic scripts), make changes to `.github/workflow/packaging-action.yaml`
- New validations can be added here.
16 changes: 12 additions & 4 deletions SMBDiagnostics/smbclientlogs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
PIDFILE="/tmp/smbclientlog.pid"
DIRNAME="./output"
CIFS_PORT=445
TRACE_CIFSBPF_ABS_PATH="$(cd "$(dirname "trace-cifsbpf")" && pwd)/$(basename "trace-cifsbpf")"
# TRACE_CIFSBPF_ABS_PATH="$(cd "$(dirname "trace-cifsbpf")" && pwd)/$(basename "trace-cifsbpf")"
TRACE_CIFSBPF_ABS_PATH="/opt/xstore/lib/SMBDiagnostics/trace-cifsbpf"
PYTHON_PROG='python'
STDLOG_FILE='/dev/null'


# to enable backward compatibility.
_trace_cifsbpf_alt_path="$(cd "$(dirname "trace-cifsbpf")" && pwd)/$(basename "trace-cifsbpf")"
if [[ -f "${_trace_cifsbpf_alt_path}" ]];
then
TRACE_CIFSBPF_ABS_PATH="${_trace_cifsbpf_alt_path}"
fi

main() {
if [[ "$*" =~ "start" ]]
then
Expand All @@ -16,7 +24,7 @@ main() {
then
stop 0<&- > "${STDLOG_FILE}" 2>&1
else
echo "Usage: ./smbclientlogs.sh <start | stop> <CaptureNetwork>"
echo "Usage: diag-main.sh cifs <start | stop> <CaptureNetwork> <OnAnomaly>"
exit 1
fi

Expand All @@ -43,7 +51,7 @@ start() {

init() {
check_utils
rm -r "$DIRNAME"
rm -rf "$DIRNAME"
mkdir -p "$DIRNAME"

dmesg -Tc > /dev/null
Expand Down Expand Up @@ -117,7 +125,7 @@ capture_network() {
}

trace_cifsbpf() {
nohup "${PYTHON_PROG}" "${TRACE_CIFSBPF_ABS_PATH}" "${DIRNAME}" 0<&- 2>&1 &
nohup /usr/bin/env "${PYTHON_PROG}" "${TRACE_CIFSBPF_ABS_PATH}" "${DIRNAME}" 0<&- 2>&1 &
}

stop() {
Expand Down
20 changes: 11 additions & 9 deletions SMBDiagnostics/trace-cifsbpf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/python
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same /usr/bin/env python comment as in trace-nfsbpf.

#!/usr/bin/env python
from bcc import BPF
from bcc.utils import printb
from time import sleep
Expand Down Expand Up @@ -133,19 +133,21 @@ while 1:

output_dir = argv[1]
print(f"[{str(datetime.now())}] Exiting Anomaly Mode")
fd=open("/tmp/smbclientlog.pid", "r");
# trace_pid=fd.readline();
tcpdump_pid=fd.readline();
print(tcpdump_pid)
command = "kill -INT %s" % (tcpdump_pid)
os.system(command);
# command = "kill -INT %s" % (trace_pid)

if(os.path.exists("/tmp/smbclientlog.pid")):
fd=open("/tmp/smbclientlog.pid", "r");
tcpdump_pid=fd.readline();
command = "kill -INT %s" % (tcpdump_pid)
os.system(command);

command = "trace-cmd stop"
os.system(command);
sleep(3)

os.system(f"trace-cmd extract")
os.system(f"trace-cmd report 2>&1 > {output_dir}/cifs_trace")
os.system("trace-cmd reset")
os.system(f"sudo dmesg -c > {output_dir}/nfs_dmesg")
os.system(f"sudo dmesg -c > {output_dir}/cifs_dmesg")
os.system(f"mv cifs_diag.txt {output_dir}")
os.system(f"mv os_details.txt {output_dir}")
command = f"zip -r $(basename {output_dir}).zip {output_dir}"
Expand Down
19 changes: 19 additions & 0 deletions diag-main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/bash

# PACKAGE_TREE="$(dirname $(dirname $(readlink -f $0)))"
PACKAGE_TREE="/opt/xstore"
run() {
if [[ $1 == "nfs" ]] || [[ $1 == "cifs" ]];
then
if [[ $1 == "nfs" ]]
then script_path="${PACKAGE_TREE}/lib/NfsDiagnostics/nfsclientlogs.sh"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: I'm a little divided about pushing nfsclientlogs (and the smb equivalent) into lib. I figure that since they're executable, they should be under bin. Then again, I also see that having them in lib makes sense. I'm not going to make this a blocker, but I guess it is something we could ask for an opinion about with other folks.

else script_path="${PACKAGE_TREE}/lib/SMBDiagnostics/smbclientlogs.sh"
fi
$script_path "$@"

else
echo "Usage: diag-main.sh <cifs | nfs> <start | stop> [Version] [CaptureNetwork] [OnAnomaly]" >&2
fi
}

run "$@"
14 changes: 14 additions & 0 deletions health-check-daemon-POC/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Steps to simulate fault and test the daemon:
1. Install the linux-crashdump using `./crash_dump.sh install`. This step requires a reboot.
2. Start the daemon by running 'sudo ./main.sh'.
3. Simulate fault by inserting module from `./buggy-module/moduleA.ko`.
4. Wait for daemon to print "Crash Dump Enabled".
5. Once crash dump is enabled, insert the other copy of buggy module `./buggy-module/moduleB.ko`
6. This should trigger a kernel panic and the system should enter into a reboot.
7. Crashdumps will be generated inside `/var/crash` directory.
8. Disable crashdumps manually running `sudo ./crash_dump.sh disable`.

# Note:
- crashdumps can be enabled without a restart.
- disabling crashdumps require a restart.
- moduleB is a copy of moduleA. We need two copies because when the buggy module is inserted, it cannot be removed from kernel by running `rmmod MODULE_NAME`. So instead of inserting, removing and reinserting the same module, we instead use a copy of the same module.
7 changes: 7 additions & 0 deletions health-check-daemon-POC/buggy-module/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
obj-m += module.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
57 changes: 57 additions & 0 deletions health-check-daemon-POC/buggy-module/module.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>

MODULE_AUTHOR("Aman");
MODULE_DESCRIPTION("This module when inserted causes null pointer dereference fault");
MODULE_LICENSE("GPL");

typedef struct ABC {
int a;
int b;
} ABC;

ABC* ptr;

void print(ABC* abc) {
printk(KERN_INFO "abc(a: %d, b: %d)\n", abc->a, abc->b);
}

void cause_gpf(void) {
printk(KERN_WARNING "Hello World <Insert Evil Laughter>\n\n");
ptr = kmalloc(sizeof(ABC), GFP_KERNEL);
ptr->a = 118;
ptr->b = 212;

printk(KERN_INFO "Before Free:");
print(ptr);
kfree(ptr);
}

void cause_nullderef(void) {
ptr = kmalloc(sizeof(ABC), GFP_KERNEL);
ptr -> a = 118;
ptr -> b = 212;
printk(KERN_INFO "Before Free");
print(ptr);
kfree(ptr);
ptr = NULL;
print(ptr);
}

static int __init custom_init(void) {
cause_nullderef();
return 1;
}

static void __exit custom_exit(void) {
printk(KERN_INFO "After Free:");
print(ptr);
printk(KERN_INFO "Goodbye |:>)\n\n");
}

module_init(custom_init);
module_exit(custom_exit);


Binary file added health-check-daemon-POC/buggy-module/moduleA.ko
Binary file not shown.
Binary file added health-check-daemon-POC/buggy-module/moduleB.ko
Binary file not shown.
Loading