2018-08-21 23:08:30 +00:00
#!/bin/bash
2022-05-06 12:45:03 +00:00
export RED = '\x1b[0;31m'
export GREEN = '\x1b[38;5;22m'
export CYAN = '\x1b[36m'
export YELLOW = '\x1b[33m'
export NO_COLOR = '\x1b[0m'
if [ -z " ${ LOG_TITLE } " ] ; then
LOG_TITLE = ''
fi
if [ -z " ${ LOG_LEVEL } " ] ; then
LOG_LEVEL = "INFO"
fi
debug( ) {
if [ [ " ${ LOG_LEVEL } " = = "DEBUG" ] ] ; then
local log_title
if [ -n " ${ LOG_TITLE } " ] ; then
log_title = " ( ${ LOG_TITLE } ) "
else
log_title = ''
fi
echo -e " ${ GREEN } [DEBUG] ${ log_title } ${ NO_COLOR } $1 "
fi
}
info( ) {
if [ [ " ${ LOG_LEVEL } " = = "DEBUG" ] ] || \
[ [ " ${ LOG_LEVEL } " = = "INFO" ] ] ; then
local log_title
if [ -n " ${ LOG_TITLE } " ] ; then
log_title = " ( ${ LOG_TITLE } ) "
else
log_title = ''
fi
echo -e " ${ CYAN } [INFO] ${ log_title } ${ NO_COLOR } $1 "
fi
}
warn( ) {
if [ [ " ${ LOG_LEVEL } " = = "DEBUG" ] ] || \
[ [ " ${ LOG_LEVEL } " = = "INFO" ] ] || \
[ [ " ${ LOG_LEVEL } " = = "WARN" ] ] ; then
local log_title
if [ -n " ${ LOG_TITLE } " ] ; then
log_title = " ( ${ LOG_TITLE } ) "
else
log_title = ''
fi
echo -e " ${ YELLOW } [WARN] ${ log_title } ${ NO_COLOR } $1 "
fi
}
error( ) {
if [ [ " ${ LOG_LEVEL } " = = "DEBUG" ] ] || \
[ [ " ${ LOG_LEVEL } " = = "INFO" ] ] || \
[ [ " ${ LOG_LEVEL } " = = "WARN" ] ] || \
[ [ " ${ LOG_LEVEL } " = = "ERROR" ] ] ; then
local log_title
if [ -n " ${ LOG_TITLE } " ] ; then
log_title = " ( ${ LOG_TITLE } ) "
else
log_title = ''
fi
echo -e " ${ RED } [ERROR] ${ log_title } ${ NO_COLOR } $1 "
fi
}
detect_node_os( )
{
local pod = " $1 "
2022-07-12 11:55:32 +00:00
OS = ` kubectl exec -i $pod -- nsenter --mount= /proc/1/ns/mnt -- bash -c 'grep -E "^ID_LIKE=" /etc/os-release | cut -d= -f2' `
2022-05-06 12:45:03 +00:00
if [ [ -z " ${ OS } " ] ] ; then
2022-07-12 11:55:32 +00:00
OS = ` kubectl exec -i $pod -- nsenter --mount= /proc/1/ns/mnt -- bash -c 'grep -E "^ID=" /etc/os-release | cut -d= -f2' `
2022-05-06 12:45:03 +00:00
fi
echo " $OS "
}
set_packages_and_check_cmd( )
{
case $OS in
*"debian" * | *"ubuntu" * )
CHECK_CMD = 'dpkg -l | grep -w'
PACKAGES = ( nfs-common open-iscsi)
; ;
*"centos" * | *"fedora" * | *"rocky" * | *"ol" * )
CHECK_CMD = 'rpm -q'
PACKAGES = ( nfs-utils iscsi-initiator-utils)
; ;
*"suse" * )
CHECK_CMD = 'rpm -q'
PACKAGES = ( nfs-client open-iscsi)
; ;
2022-05-07 16:35:19 +00:00
*"arch" * )
CHECK_CMD = 'pacman -Q'
PACKAGES = ( nfs-utils open-iscsi)
; ;
2022-07-29 04:50:59 +00:00
*"gentoo" * )
CHECK_CMD = 'qlist -I'
PACKAGES = ( net-fs/nfs-utils sys-block/open-iscsi)
; ;
2022-05-06 12:45:03 +00:00
*)
CHECK_CMD = ''
PACKAGES = ( )
warn " Stop the environment check because ' $OS ' is not supported in the environment check script. "
exit 1
; ;
esac
}
check_dependencies( ) {
2018-08-21 23:08:30 +00:00
local targets = ( $@ )
2022-05-06 12:45:03 +00:00
2018-08-21 23:08:30 +00:00
local allFound = true
for ( ( i = 0; i<${# targets [@] } ; i++) ) ; do
local target = ${ targets [ $i ] }
if [ " $( which $target ) " = = "" ] ; then
allFound = false
2022-05-06 12:45:03 +00:00
error " Not found: $target "
2018-08-21 23:08:30 +00:00
fi
done
if [ " $allFound " = = "false" ] ; then
2022-05-06 12:45:03 +00:00
error "Please install missing dependencies."
2018-08-21 23:08:30 +00:00
exit 2
2022-05-06 12:45:03 +00:00
else
info "Required dependencies are installed."
2018-08-21 23:08:30 +00:00
fi
}
create_ds( ) {
cat <<EOF > $TE MP_DIR/environment_check.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app: longhorn-environment-check
name: longhorn-environment-check
spec:
selector:
matchLabels:
app: longhorn-environment-check
template:
metadata:
labels:
app: longhorn-environment-check
spec:
2022-05-06 12:45:03 +00:00
hostPID: true
2018-08-21 23:08:30 +00:00
containers:
- name: longhorn-environment-check
2022-05-06 12:45:03 +00:00
image: alpine:3.12
2018-08-21 23:08:30 +00:00
args: [ "/bin/sh" , "-c" , "sleep 1000000000" ]
volumeMounts:
- name: mountpoint
2018-08-22 03:10:20 +00:00
mountPath: /tmp/longhorn-environment-check
2018-08-21 23:08:30 +00:00
mountPropagation: Bidirectional
securityContext:
privileged: true
volumes:
- name: mountpoint
hostPath:
2018-08-22 03:10:20 +00:00
path: /tmp/longhorn-environment-check
2018-08-21 23:08:30 +00:00
EOF
2022-05-06 12:45:03 +00:00
kubectl create -f $TEMP_DIR /environment_check.yaml > /dev/null
2018-08-21 23:08:30 +00:00
}
cleanup( ) {
2022-05-06 12:45:03 +00:00
info "Cleaning up longhorn-environment-check pods..."
kubectl delete -f $TEMP_DIR /environment_check.yaml > /dev/null
2018-08-21 23:08:30 +00:00
rm -rf $TEMP_DIR
2022-05-06 12:45:03 +00:00
info "Cleanup completed."
2018-08-22 03:10:20 +00:00
}
2018-08-21 23:08:30 +00:00
wait_ds_ready( ) {
while true; do
local ds = $( kubectl get ds/longhorn-environment-check -o json)
local numberReady = $( echo $ds | jq .status.numberReady)
local desiredNumberScheduled = $( echo $ds | jq .status.desiredNumberScheduled)
if [ " $desiredNumberScheduled " = = " $numberReady " ] && [ " $desiredNumberScheduled " != "0" ] ; then
2022-05-06 12:45:03 +00:00
info " All longhorn-environment-check pods are ready ( $numberReady / $desiredNumberScheduled ). "
2018-08-21 23:08:30 +00:00
return
fi
2022-05-06 12:45:03 +00:00
info " Waiting for longhorn-environment-check pods to become ready ( $numberReady / $desiredNumberScheduled )... "
2018-08-21 23:08:30 +00:00
sleep 3
done
}
2022-05-06 12:45:03 +00:00
check_mount_propagation( ) {
2018-08-21 23:08:30 +00:00
local allSupported = true
local pods = $( kubectl -l app = longhorn-environment-check get po -o json)
2018-08-23 21:22:08 +00:00
2021-06-03 16:07:26 +00:00
local ds = $( kubectl get ds/longhorn-environment-check -o json)
local desiredNumberScheduled = $( echo $ds | jq .status.desiredNumberScheduled)
for ( ( i = 0; i<desiredNumberScheduled; i++) ) ; do
2018-08-21 23:08:30 +00:00
local pod = $( echo $pods | jq .items[ $i ] )
local nodeName = $( echo $pod | jq -r .spec.nodeName)
local mountPropagation = $( echo $pod | jq -r '.spec.containers[0].volumeMounts[] | select(.name=="mountpoint") | .mountPropagation' )
if [ " $mountPropagation " != "Bidirectional" ] ; then
allSupported = false
2022-05-06 12:45:03 +00:00
error " node $nodeName : MountPropagation is disabled "
2018-08-21 23:08:30 +00:00
fi
done
if [ " $allSupported " != "true" ] ; then
2022-05-06 12:45:03 +00:00
error "MountPropagation is disabled on at least one node. As a result, CSI driver and Base image cannot be supported."
2018-08-21 23:08:30 +00:00
exit 1
else
2022-05-06 12:45:03 +00:00
info "MountPropagation is enabled."
2018-08-21 23:08:30 +00:00
fi
}
2022-05-06 12:45:03 +00:00
check_package_installed( ) {
local pods = $( kubectl get pods -o name | grep longhorn-environment-check)
local allFound = true
for pod in ${ pods } ; do
OS = ` detect_node_os $pod `
if [ x" $OS " = = x"" ] ; then
error " Unable to detect OS on node $node . "
exit 2
fi
set_packages_and_check_cmd " $OS "
for ( ( i = 0; i<${# PACKAGES [@] } ; i++) ) ; do
local package = ${ PACKAGES [ $i ] }
2022-07-12 11:55:32 +00:00
kubectl exec -i $pod -- nsenter --mount= /proc/1/ns/mnt -- timeout 30 bash -c " $CHECK_CMD $package " > /dev/null 2>& 1
2022-05-06 12:45:03 +00:00
if [ $? != 0 ] ; then
allFound = false
node = ` kubectl get ${ pod } --no-headers -o= custom-columns= :.spec.nodeName`
error " $package is not found in $node . "
fi
done
done
if [ " $allFound " = = "false" ] ; then
error "Please install missing packages."
exit 2
else
info "Required packages are installed."
fi
}
check_multipathd( ) {
local pods = $( kubectl get pods -o name | grep longhorn-environment-check)
local allNotFound = true
for pod in ${ pods } ; do
kubectl exec -t $pod -- nsenter --mount= /proc/1/ns/mnt -- bash -c "systemctl status --no-pager multipathd.service" > /dev/null 2>& 1
if [ $? = 0 ] ; then
allNotFound = false
node = ` kubectl get ${ pod } --no-headers -o= custom-columns= :.spec.nodeName`
warn " multipathd is running on $node . "
fi
done
if [ " $allNotFound " = = "false" ] ; then
warn "multipathd would probably result in the Longhorn volume mount failure. Please refer to https://longhorn.io/kb/troubleshooting-volume-with-multipath for more information."
fi
}
check_iscsid( ) {
local pods = $( kubectl get pods -o name | grep longhorn-environment-check)
local allFound = true
for pod in ${ pods } ; do
kubectl exec -t $pod -- nsenter --mount= /proc/1/ns/mnt -- bash -c "systemctl status --no-pager iscsid.service" > /dev/null 2>& 1
if [ $? != 0 ] ; then
allFound = false
node = ` kubectl get ${ pod } --no-headers -o= custom-columns= :.spec.nodeName`
error " iscsid is not running on $node . "
fi
done
if [ " $allFound " = = "false" ] ; then
exit 2
fi
}
DEPENDENCIES = ( kubectl jq mktemp)
check_dependencies ${ DEPENDENCIES [@] }
2018-08-21 23:08:30 +00:00
TEMP_DIR = $( mktemp -d)
2022-05-06 12:45:03 +00:00
2018-08-21 23:08:30 +00:00
trap cleanup EXIT
create_ds
wait_ds_ready
2022-05-06 12:45:03 +00:00
check_package_installed
check_iscsid
check_multipathd
check_mount_propagation
2018-08-21 23:08:30 +00:00
exit 0
2022-05-06 12:45:03 +00:00