Add mariadb-cli, kubectl and openstack commands to collect
This adds containerized related commands to collect: - containerized wrapper script mariadb-cli to access MariaDB mysql - various kubectl commands to understand resource usage - various containerized openstack commands to understand resource usage mariadb-cli is used to dump contents of all mariadb databases. Change-Id: I70a08e38adbba247152509a22a8b9beac9128ff9 Closes-Bug: 1889678 Closes-Bug: 1894103 Signed-off-by: Jim Gauld <james.gauld@windriver.com>
This commit is contained in:
parent
533d4fff06
commit
dd902cf386
|
@ -32,9 +32,11 @@ install -m 755 collect_utils %{buildroot}/usr/local/sbin/collect_utils
|
|||
install -m 755 collect_parms %{buildroot}/usr/local/sbin/collect_parms
|
||||
install -m 755 collect_mask_passwords %{buildroot}/usr/local/sbin/collect_mask_passwords
|
||||
install -m 755 expect_done %{buildroot}/usr/local/sbin/expect_done
|
||||
install -m 755 mariadb-cli.sh %{buildroot}/usr/local/sbin/mariadb-cli
|
||||
|
||||
install -m 755 collect_sysinv.sh %{buildroot}%{_sysconfdir}/collect.d/collect_sysinv
|
||||
install -m 755 collect_psqldb.sh %{buildroot}%{_sysconfdir}/collect.d/collect_psqldb
|
||||
install -m 755 collect_mariadb.sh %{buildroot}%{_sysconfdir}/collect.d/collect_mariadb
|
||||
install -m 755 collect_openstack.sh %{buildroot}%{_sysconfdir}/collect.d/collect_openstack
|
||||
install -m 755 collect_networking.sh %{buildroot}%{_sysconfdir}/collect.d/collect_networking
|
||||
install -m 755 collect_ceph.sh %{buildroot}%{_sysconfdir}/collect.d/collect_ceph
|
||||
|
|
|
@ -13,6 +13,14 @@ source /usr/local/sbin/collect_utils
|
|||
|
||||
SERVICE="containerization"
|
||||
LOGFILE="${extradir}/${SERVICE}.info"
|
||||
LOGFILE_EVENT="${extradir}/${SERVICE}_events.info"
|
||||
LOGFILE_API="${extradir}/${SERVICE}_api.info"
|
||||
LOGFILE_HOST="${extradir}/${SERVICE}_host.info"
|
||||
LOGFILE_IMG="${extradir}/${SERVICE}_images.info"
|
||||
LOGFILE_KUBE="${extradir}/${SERVICE}_kube.info"
|
||||
LOGFILE_PODS="${extradir}/${SERVICE}_pods.info"
|
||||
LOGFILE_HELM="${extradir}/${SERVICE}_helm.info"
|
||||
|
||||
HELM_DIR="${extradir}/helm"
|
||||
ETCD_DB_FILE="${extradir}/etcd_database.dump"
|
||||
KUBE_CONFIG_FILE="/etc/kubernetes/admin.conf"
|
||||
|
@ -26,57 +34,131 @@ mkdir -p ${HELM_DIR}
|
|||
source_openrc_if_needed
|
||||
|
||||
CMD="docker image ls -a"
|
||||
delimiter ${LOGFILE} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE}
|
||||
delimiter ${LOGFILE_IMG} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_IMG}
|
||||
|
||||
CMD="crictl images"
|
||||
delimiter ${LOGFILE} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE}
|
||||
delimiter ${LOGFILE_IMG} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_IMG}
|
||||
|
||||
CMD="docker container ps -a"
|
||||
delimiter ${LOGFILE} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE}
|
||||
delimiter ${LOGFILE_IMG} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_IMG}
|
||||
|
||||
CMD="crictl ps -a"
|
||||
delimiter ${LOGFILE} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE}
|
||||
delimiter ${LOGFILE_IMG} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_IMG}
|
||||
|
||||
CMD="cat /var/lib/kubelet/cpu_manager_state | python -mjson.tool"
|
||||
delimiter ${LOGFILE_HOST} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_HOST}
|
||||
|
||||
###############################################################################
|
||||
# Active Controller
|
||||
###############################################################################
|
||||
if [ "$nodetype" = "controller" -a "${ACTIVE}" = true ] ; then
|
||||
|
||||
declare -a KUBE_CMDS=(
|
||||
"kubectl ${KUBE_CONFIG} version"
|
||||
"kubectl ${KUBE_CONFIG} api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl ${KUBE_CONFIG} get --show-kind --ignore-not-found --all-namespaces"
|
||||
"kubectl ${KUBE_CONFIG} api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl ${KUBE_CONFIG} get --show-kind --ignore-not-found --all-namespaces -o yaml"
|
||||
"kubectl ${KUBE_CONFIG} get pvc --all-namespaces"
|
||||
"kubectl ${KUBE_CONFIG} get pvc --all-namespaces -o yaml"
|
||||
"kubectl ${KUBE_CONFIG} get pv --all-namespaces"
|
||||
"kubectl ${KUBE_CONFIG} get pv --all-namespaces -o yaml"
|
||||
"kubectl ${KUBE_CONFIG} get events --all-namespaces --sort-by='.metadata.creationTimestamp' -o go-template='{{range .items}}{{printf \"%s %s\t%s\t%s\t%s\t%s\n\" .firstTimestamp .involvedObject.name .involvedObject.kind .message .reason .type}}{{end}}'"
|
||||
)
|
||||
# Environment for kubectl and helm
|
||||
export KUBECONFIG=${KUBE_CONFIG_FILE}
|
||||
|
||||
for CMD in "${KUBE_CMDS[@]}" ; do
|
||||
delimiter ${LOGFILE} "${CMD}"
|
||||
eval ${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE}
|
||||
declare -a CMDS=()
|
||||
CMDS+=("kubectl version")
|
||||
CMDS+=("kubectl get nodes -o wide")
|
||||
CMDS+=("kubectl get nodes --show-labels")
|
||||
CMDS+=("kubectl get nodes -o json")
|
||||
CMDS+=("kubectl describe nodes")
|
||||
CMDS+=("kubectl services")
|
||||
CMDS+=("kubectl get configmaps --all-namespaces")
|
||||
CMDS+=("kubectl get daemonsets --all-namespaces")
|
||||
CMDS+=("kubectl get pods --all-namespaces -o wide")
|
||||
CMDS+=("kubectl get pvc --all-namespaces")
|
||||
CMDS+=("kubectl get pvc --all-namespaces -o yaml")
|
||||
CMDS+=("kubectl get pv --all-namespaces")
|
||||
CMDS+=("kubectl get pv --all-namespaces -o yaml")
|
||||
CMDS+=("kubectl get sc --all-namespaces")
|
||||
CMDS+=("kubectl get serviceaccounts --all-namespaces")
|
||||
CMDS+=("kubectl get deployments.apps --all-namespaces")
|
||||
CMDS+=("kubectl get rolebindings.rbac.authorization.k8s.io --all-namespaces")
|
||||
CMDS+=("kubectl get roles.rbac.authorization.k8s.io --all-namespaces")
|
||||
CMDS+=("kubectl get clusterrolebindings.rbac.authorization.k8s.io")
|
||||
CMDS+=("kubectl get clusterroles.rbac.authorization.k8s.io")
|
||||
for CMD in "${CMDS[@]}" ; do
|
||||
delimiter ${LOGFILE_KUBE} "${CMD}"
|
||||
eval ${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_KUBE}
|
||||
echo >>${LOGFILE_KUBE}
|
||||
done
|
||||
|
||||
CMD="helm ${KUBE_CONFIG} version"
|
||||
delimiter ${LOGFILE} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE}
|
||||
# api-resources; verbose, place in separate file
|
||||
CMDS=()
|
||||
CMDS+=("kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get --show-kind --ignore-not-found --all-namespaces")
|
||||
CMDS+=("kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get --show-kind --ignore-not-found --all-namespaces -o yaml")
|
||||
for CMD in "${CMDS[@]}" ; do
|
||||
delimiter ${LOGFILE_API} "${CMD}"
|
||||
eval ${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_API}
|
||||
echo >>${LOGFILE_API}
|
||||
done
|
||||
|
||||
CMD="helm ${KUBE_CONFIG} list -a"
|
||||
delimiter ${LOGFILE} "${CMD}"
|
||||
APPLIST=$(${CMD} 2>>${COLLECT_ERROR_LOG} | tee -a ${LOGFILE})
|
||||
APPLIST=$(echo "${APPLIST}" | awk '{if (NR!=1) {print}}')
|
||||
while read -r app; do
|
||||
APPNAME=$(echo ${app} | awk '{print $1}')
|
||||
APPREVISION=$(echo ${app} | awk '{print $2}')
|
||||
helm ${KUBE_CONFIG} status ${APPNAME} > ${HELM_DIR}/${APPNAME}.status
|
||||
helm ${KUBE_CONFIG} get values ${APPNAME} --revision ${APPREVISION} \
|
||||
> ${HELM_DIR}/${APPNAME}.v${APPREVISION}
|
||||
done <<< "${APPLIST}"
|
||||
# describe pods; verbose, place in separate file
|
||||
CMDS=()
|
||||
CMDS+=("kubectl describe pods --all-namespaces")
|
||||
for CMD in "${CMDS[@]}" ; do
|
||||
delimiter ${LOGFILE_PODS} "${CMD}"
|
||||
eval ${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_PODS}
|
||||
echo >>${LOGFILE_API}
|
||||
done
|
||||
|
||||
# events; verbose, place in separate file
|
||||
CMDS=()
|
||||
CMDS+=("kubectl get events --all-namespaces --sort-by='.metadata.creationTimestamp' -o go-template='{{range .items}}{{printf \"%s %s\t%s\t%s\t%s\t%s\n\" .firstTimestamp .involvedObject.name .involvedObject.kind .message .reason .type}}{{end}}'")
|
||||
for CMD in "${CMDS[@]}" ; do
|
||||
delimiter ${LOGFILE_EVENT} "${CMD}"
|
||||
eval ${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_EVENT}
|
||||
echo >>${LOGFILE_EVENT}
|
||||
done
|
||||
|
||||
# Helm related
|
||||
CMD="helm version"
|
||||
delimiter ${LOGFILE_HELM} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_HELM}
|
||||
echo >>${LOGFILE_HELM}
|
||||
|
||||
HELM_VERSION=$(helm version --client --short)
|
||||
if [[ $HELM_VERSION =~ v2 ]]; then
|
||||
CMD="helm list -a"
|
||||
delimiter ${LOGFILE_HELM} "${CMD}"
|
||||
APPLIST=$(${CMD} 2>>${COLLECT_ERROR_LOG} | tee -a ${LOGFILE_HELM})
|
||||
APPLIST=$(echo "${APPLIST}" | awk '{if (NR!=1) {print}}')
|
||||
while read -r app; do
|
||||
APPNAME=$(echo ${app} | awk '{print $1}')
|
||||
APPREVISION=$(echo ${app} | awk '{print $2}')
|
||||
helm status ${APPNAME} > ${HELM_DIR}/${APPNAME}.status
|
||||
helm get values ${APPNAME} --revision ${APPREVISION} \
|
||||
> ${HELM_DIR}/${APPNAME}.v${APPREVISION}
|
||||
done <<< "${APPLIST}"
|
||||
elif [[ $HELM_VERSION =~ v3 ]]; then
|
||||
CMD="helm list --all --all-namespaces"
|
||||
delimiter ${LOGFILE_HELM} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_HELM}
|
||||
|
||||
CMD="helm repo list"
|
||||
delimiter ${LOGFILE_HELM} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_HELM}
|
||||
fi
|
||||
|
||||
HELM2CLI=$(which helmv2-cli)
|
||||
if [ $? -eq 0 ]; then
|
||||
CMD="helmv2-cli -- helm list"
|
||||
delimiter ${LOGFILE_HELM} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_HELM}
|
||||
|
||||
CMD="helmv2-cli -- helm search"
|
||||
delimiter ${LOGFILE_HELM} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_HELM}
|
||||
|
||||
CMD="helmv2-cli -- helm repo list"
|
||||
delimiter ${LOGFILE_HELM} "${CMD}"
|
||||
${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE_HELM}
|
||||
fi
|
||||
|
||||
CMD="cp -r /opt/platform/helm_charts ${HELM_DIR}/"
|
||||
delimiter ${LOGFILE} "${CMD}"
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
#! /bin/bash
|
||||
#
|
||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Gather containerized MariaDB information from active controller.
|
||||
|
||||
# Loads Up Utilities and Commands Variables
|
||||
source /usr/local/sbin/collect_parms
|
||||
source /usr/local/sbin/collect_utils
|
||||
|
||||
SERVICE="mariadb"
|
||||
DB_DIR="${extradir}/${SERVICE}"
|
||||
LOGFILE="${extradir}/${SERVICE}.info"
|
||||
echo "${hostname}: MariaDB Info .....: ${LOGFILE}"
|
||||
|
||||
function is_service_active {
|
||||
active=$(sm-query service postgres | grep "enabled-active")
|
||||
if [ -z "${active}" ] ; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "${nodetype}" = "controller" ] ; then
|
||||
is_service_active
|
||||
if [ "$?" = "0" ] ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# MariaDB databases
|
||||
delimiter ${LOGFILE} "MariaDB databases:"
|
||||
mariadb-cli --command 'show databases' >> ${LOGFILE}
|
||||
|
||||
# MariaDB database sizes
|
||||
delimiter ${LOGFILE} "MariaDB database sizes:"
|
||||
mariadb-cli --command '
|
||||
SELECT table_schema AS "database",
|
||||
ROUND(SUM(DATA_LENGTH + INDEX_LENGTH)/1024/1024, 3) AS "Size (MiB)",
|
||||
SUM(TABLE_ROWS) AS "rowCount"
|
||||
FROM information_schema.TABLES
|
||||
GROUP BY table_schema' >> ${LOGFILE}
|
||||
|
||||
delimiter ${LOGFILE} "MariaDB database table sizes:"
|
||||
mariadb-cli --command '
|
||||
SELECT
|
||||
table_schema AS "database", TABLE_NAME AS "table",
|
||||
ROUND((DATA_LENGTH + INDEX_LENGTH)/1024/1024, 6) AS "Size (MiB)",
|
||||
TABLE_ROWS AS "rowCount"
|
||||
FROM information_schema.TABLES
|
||||
ORDER BY table_schema, TABLE_NAME' >> ${LOGFILE}
|
||||
|
||||
# MariaDB dump all databases
|
||||
delimiter ${LOGFILE} "Dumping MariaDB databases: ${DB_DIR}"
|
||||
mkdir -p ${DB_DIR}
|
||||
(cd ${DB_DIR}; mariadb-cli --dump --exclude keystone,ceilometer)
|
||||
fi
|
||||
|
||||
exit 0
|
|
@ -10,38 +10,99 @@
|
|||
source /usr/local/sbin/collect_parms
|
||||
source /usr/local/sbin/collect_utils
|
||||
|
||||
# Environment for kubectl
|
||||
export KUBECONFIG=/etc/kubernetes/admin.conf
|
||||
|
||||
SERVICE="openstack"
|
||||
LOGFILE="${extradir}/${SERVICE}.info"
|
||||
echo "${hostname}: Openstack Info ....: ${LOGFILE}"
|
||||
|
||||
function is_service_active {
|
||||
active=`sm-query service rabbit-fs | grep "enabled-active"`
|
||||
if [ -z "$active" ] ; then
|
||||
active=$(sm-query service rabbit-fs | grep "enabled-active")
|
||||
if [ -z "${active}" ] ; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
SERVICE="openstack"
|
||||
LOGFILE="${extradir}/${SERVICE}.info"
|
||||
echo "${hostname}: Openstack Info ....: ${LOGFILE}"
|
||||
function is_openstack_node {
|
||||
local PASS=0
|
||||
local FAIL=1
|
||||
# NOTE: hostname changes during first configuration
|
||||
local this_node=$(cat /proc/sys/kernel/hostname)
|
||||
|
||||
###############################################################################
|
||||
# Only Controller
|
||||
###############################################################################
|
||||
if [ "$nodetype" = "controller" ] ; then
|
||||
|
||||
is_service_active
|
||||
if [ "$?" = "0" ] ; then
|
||||
exit 0
|
||||
labels=$(kubectl get node ${this_node} \
|
||||
--no-headers --show-labels 2>/dev/null | awk '{print $NF}')
|
||||
if [[ $labels =~ openstack-control-plane=enabled ]]; then
|
||||
return ${PASS}
|
||||
else
|
||||
return ${FAIL}
|
||||
fi
|
||||
}
|
||||
|
||||
delimiter ${LOGFILE} "openstack project list"
|
||||
openstack project list >> ${LOGFILE} 2>>${COLLECT_ERROR_LOG}
|
||||
function openstack_credentials {
|
||||
# Setup openstack admin tenant credentials using environment variables
|
||||
unset OS_SERVICE_TOKEN
|
||||
export OS_ENDPOINT_TYPE=internalURL
|
||||
export CINDER_ENDPOINT_TYPE=internalURL
|
||||
export OS_USERNAME=admin
|
||||
export OS_PASSWORD=$(TERM=linux /opt/platform/.keyring/*/.CREDENTIAL 2>/dev/null)
|
||||
export OS_AUTH_TYPE=password
|
||||
export OS_AUTH_URL=http://keystone.openstack.svc.cluster.local/v3
|
||||
export OS_PROJECT_NAME=admin
|
||||
export OS_USER_DOMAIN_NAME=Default
|
||||
export OS_PROJECT_DOMAIN_NAME=Default
|
||||
export OS_IDENTITY_API_VERSION=3
|
||||
export OS_REGION_NAME=RegionOne
|
||||
export OS_INTERFACE=internal
|
||||
}
|
||||
|
||||
delimiter ${LOGFILE} "openstack user list"
|
||||
openstack user list >> ${LOGFILE} 2>>${COLLECT_ERROR_LOG}
|
||||
function openstack_commands {
|
||||
declare -a CMDS=()
|
||||
CMDS+=("openstack project list --long")
|
||||
CMDS+=("openstack user list --long")
|
||||
CMDS+=("openstack service list --long")
|
||||
CMDS+=("openstack router list --long")
|
||||
CMDS+=("openstack network list --long")
|
||||
CMDS+=("openstack subnet list --long")
|
||||
CMDS+=("openstack image list --long")
|
||||
CMDS+=("openstack volume list --all-projects --long")
|
||||
CMDS+=("openstack availability zone list --long")
|
||||
CMDS+=("openstack server group list --all-projects --long")
|
||||
CMDS+=('openstack server list --all-projects --long -c ID -c Name -c Status -c "Task State" -c "Power State" -c Networks -c "Image Name" -c "Image ID" -c "Flavor Name" -c "Flavor ID" -c "Availability Zone" -c Host -c Properties')
|
||||
CMDS+=("openstack stack list --long --all-projects")
|
||||
CMDS+=("openstack security group list --all-projects")
|
||||
CMDS+=("openstack security group rule list --all-projects --long")
|
||||
CMDS+=("openstack keypair list")
|
||||
CMDS+=("openstack configuration show")
|
||||
CMDS+=("openstack quota list --compute")
|
||||
CMDS+=("openstack quota list --volume")
|
||||
CMDS+=("openstack quota list --network")
|
||||
CMDS+=("openstack host list")
|
||||
CMDS+=("openstack hypervisor list --long")
|
||||
CMDS+=("openstack hypervisor stats show")
|
||||
HOSTS=( $(openstack hypervisor list -f value -c "Hypervisor Hostname" 2>/dev/null) )
|
||||
for host in "${HOSTS[@]}" ; do
|
||||
CMDS+=("openstack hypervisor show -f yaml ${host}")
|
||||
done
|
||||
|
||||
# nova commands
|
||||
CMDS+=("nova service-list")
|
||||
|
||||
for CMD in "${CMDS[@]}" ; do
|
||||
delimiter ${LOGFILE} "${CMD}"
|
||||
eval ${CMD} 2>>${COLLECT_ERROR_LOG} >>${LOGFILE}
|
||||
echo >>${LOGFILE}
|
||||
done
|
||||
}
|
||||
|
||||
function rabbitmq_usage_stats {
|
||||
# RabbitMQ usage stats
|
||||
MQ_STATUS="rabbitmqctl status"
|
||||
delimiter ${LOGFILE} "${MQ_STATUS} | grep -e '{memory' -A30"
|
||||
${MQ_STATUS} 2>/dev/null | grep -e '{memory' -A30 >> ${LOGFILE}
|
||||
echo >>${LOGFILE}
|
||||
|
||||
delimiter ${LOGFILE} "RabbitMQ Queue Info"
|
||||
num_queues=$(rabbitmqctl list_queues | wc -l); ((num_queues-=2))
|
||||
|
@ -54,6 +115,31 @@ if [ "$nodetype" = "controller" ] ; then
|
|||
messages=${arr[0]}; consumers=${arr[1]}; memory=${arr[2]}
|
||||
printf "%6s %8s %9s %11s %8s %8s %9s %10s\n" "queues" "bindings" "exchanges" "connections" "channels" "messages" "consumers" "memory" >> ${LOGFILE} 2>>${COLLECT_ERROR_LOG}
|
||||
printf "%6d %8d %9d %11d %8d %8d %9d %10d\n" $num_queues $num_bindings $num_exchanges $num_connections $num_channels $messages $consumers $memory >> ${LOGFILE} 2>>${COLLECT_ERROR_LOG}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Only Controller
|
||||
###############################################################################
|
||||
if [ "$nodetype" = "controller" ] ; then
|
||||
|
||||
is_service_active
|
||||
if [ "$?" = "0" ] ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# host rabbitmq usage
|
||||
rabbitmq_usage_stats
|
||||
|
||||
# Check for openstack label on this node
|
||||
if ! is_openstack_node; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Run as subshell so we don't contaminate environment
|
||||
(openstack_credentials; openstack_commands)
|
||||
|
||||
# TODO(jgauld): Should also get containerized rabbitmq usage,
|
||||
# need wrapper script rabbitmq-cli
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# This script is wrapper to containerized mariadb-server mysql client.
|
||||
# This provides access to MariaDB databases.
|
||||
#
|
||||
# There are three modes of operation:
|
||||
# - no command specified gives an interactive mysql shell
|
||||
# - command specified executes a single mysql command
|
||||
# - dump option to dump database contents to sql text file
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
# Define minimal path
|
||||
PATH=/bin:/usr/bin:/usr/local/bin
|
||||
|
||||
# Environment for kubectl
|
||||
export KUBECONFIG=/etc/kubernetes/admin.conf
|
||||
|
||||
# Process input options
|
||||
SCRIPT=$(basename $0)
|
||||
OPTS=$(getopt -o dh --long debug,help,command:,database:,exclude:,dump -n ${SCRIPT} -- "$@")
|
||||
if [ $? != 0 ]; then
|
||||
echo "Failed parsing options." >&2
|
||||
exit 1
|
||||
fi
|
||||
eval set -- "$OPTS"
|
||||
|
||||
DEBUG=false
|
||||
HELP=false
|
||||
DUMP=false
|
||||
COMMAND=""
|
||||
DATABASE=""
|
||||
EXCLUDE=""
|
||||
while true
|
||||
do
|
||||
case "$1" in
|
||||
-d | --debug ) DEBUG=true; shift ;;
|
||||
-h | --help ) HELP=true; shift ;;
|
||||
--command )
|
||||
COMMAND="$2"
|
||||
shift 2
|
||||
;;
|
||||
--database )
|
||||
DATABASE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--exclude )
|
||||
EXCLUDE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--dump )
|
||||
DUMP=true
|
||||
shift
|
||||
;;
|
||||
-- )
|
||||
shift
|
||||
break
|
||||
;;
|
||||
* )
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Treat remaining arguments as commands + options
|
||||
shift $((OPTIND-1))
|
||||
OTHERARGS="$@"
|
||||
|
||||
if [ ${HELP} == 'true' ]; then
|
||||
echo "Usage: ${SCRIPT} [-d|--debug] [-h|--help] [--database <db>] [--exclude <db,...>] [--command <cmd>] [--dump]"
|
||||
echo "Options:"
|
||||
echo " -d | --debug : display debug information"
|
||||
echo " -h | --help : this help"
|
||||
echo " --database <db> : connect to database db"
|
||||
echo " --exclude <db1,...> : list of databases to exclude"
|
||||
echo " --command <cmd> : execute mysql command cmd"
|
||||
echo " --dump : dump database(s) to sql file in current directory"
|
||||
echo
|
||||
echo "Command option examples:"
|
||||
echo
|
||||
echo "Interactive mysql shell:"
|
||||
echo " mariadb-cli"
|
||||
echo " mariadb-cli --database nova"
|
||||
echo " mariadb-cli --command 'show_databases'"
|
||||
echo " mariadb-cli --database nova --command 'select * from compute_nodes'"
|
||||
echo
|
||||
echo "Dump MariaDB databases to sql file:"
|
||||
echo " mariadb-cli --dump"
|
||||
echo " mariadb-cli --dump --database nova"
|
||||
echo " mariadb-cli --dump --exclude keystone"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
# Logger setup
|
||||
LOG_FACILITY=user
|
||||
LOG_PRIORITY=info
|
||||
function LOG {
|
||||
logger -t "${0##*/}[$$]" -p ${LOG_FACILITY}.${LOG_PRIORITY} "$@"
|
||||
echo "${0##*/}[$$]" "$@"
|
||||
}
|
||||
function ERROR {
|
||||
MSG="ERROR"
|
||||
LOG "${MSG} $@"
|
||||
}
|
||||
|
||||
function is_openstack_node {
|
||||
local PASS=0
|
||||
local FAIL=1
|
||||
# NOTE: hostname changes during first configuration
|
||||
local this_node=$(cat /proc/sys/kernel/hostname)
|
||||
|
||||
labels=$(kubectl get node ${this_node} \
|
||||
--no-headers --show-labels 2>/dev/null | awk '{print $NF}')
|
||||
if [[ $labels =~ openstack-control-plane=enabled ]]; then
|
||||
return ${PASS}
|
||||
else
|
||||
return ${FAIL}
|
||||
fi
|
||||
}
|
||||
|
||||
# Selected options
|
||||
if [ ${DEBUG} == 'true' ]; then
|
||||
LOG "Options: DUMP=${DUMP} OTHERARGS: ${OTHERARGS}"
|
||||
if [ ! -z "${DATABASE}" ]; then
|
||||
LOG "Options: DATABASE:${DATABASE}"
|
||||
fi
|
||||
if [ ! -z "${EXCLUDE}" ]; then
|
||||
LOG "Options: EXCLUDE:${EXCLUDE}"
|
||||
fi
|
||||
if [ ! -z "${COMMAND}" ]; then
|
||||
LOG "Options: COMMAND:${COMMAND}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for openstack label on this node
|
||||
if ! is_openstack_node; then
|
||||
ERROR "This node not configured for openstack."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine running mariadb pods
|
||||
MARIADB_PODS=( $(kubectl get pods -n openstack \
|
||||
--selector=application=mariadb,component=server \
|
||||
--field-selector status.phase=Running \
|
||||
--output=jsonpath={.items..metadata.name}) )
|
||||
if [ ${DEBUG} == 'true' ]; then
|
||||
LOG "Found mariadb-server pods: ${MARIADB_PODS[@]}"
|
||||
fi
|
||||
|
||||
# Get first available mariadb pod with container we can exec
|
||||
DBPOD=""
|
||||
for POD in "${MARIADB_PODS[@]}"
|
||||
do
|
||||
kubectl exec -it -n openstack ${POD} -c mariadb -- pwd 1>/dev/null 2>/dev/null
|
||||
RC=$?
|
||||
if [ ${RC} -eq 0 ]; then
|
||||
DBPOD=${POD}
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "${DBPOD}" ]; then
|
||||
ERROR "Could not find mariadb-server pod."
|
||||
exit 1
|
||||
fi
|
||||
if [ ${DEBUG} == 'true' ]; then
|
||||
LOG "Found mariadb-server pod: ${DBPOD}"
|
||||
fi
|
||||
|
||||
EVAL='eval env 1>/dev/null'
|
||||
DBOPTS='--password=$MYSQL_DBADMIN_PASSWORD --user=$MYSQL_DBADMIN_USERNAME'
|
||||
|
||||
if [ ${DUMP} == 'true' ]; then
|
||||
# Dump database contents to sql text file
|
||||
DB_EXT=sql
|
||||
|
||||
DATABASES=()
|
||||
if [ ! -z "${DATABASE}" ]; then
|
||||
DATABASES+=( $DATABASE )
|
||||
else
|
||||
# Get list of databases
|
||||
MYSQL_CMD="${EVAL}; mysql ${DBOPTS} -e 'show databases' -sN --disable-pager"
|
||||
if [ ${DEBUG} == 'true' ]; then
|
||||
LOG "MYSQL_CMD: ${MYSQL_CMD}"
|
||||
fi
|
||||
|
||||
# Suppress error: line from stdout, eg.,
|
||||
# error: Found option without preceding group in config file: /etc/mysql/conf.d/20-override.cnf at line: 1
|
||||
# Exclude databases: mysql, information_schema, performance_schema
|
||||
# Remove linefeed control character.
|
||||
DATABASES=( $(kubectl exec -it -n openstack ${DBPOD} -c mariadb -- bash -c "${MYSQL_CMD}" | \
|
||||
grep -v -e error: -e mysql -e information_schema -e performance_schema | tr -d '\r') )
|
||||
fi
|
||||
|
||||
for dbname in "${DATABASES[@]}"
|
||||
do
|
||||
re=\\b"${dbname}"\\b
|
||||
if [[ "${EXCLUDE}" =~ ${re} ]]; then
|
||||
LOG "excluding: ${dbname}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# NOTE: --skip-opt will show an INSERT for each record
|
||||
DUMP_CMD="${EVAL}; mysqldump ${DBOPTS} --skip-opt --skip-comments --skip-set-charset ${dbname}"
|
||||
dbfile=${dbname}.${DB_EXT}
|
||||
LOG "Dump database: $dbname to file: ${dbfile}"
|
||||
if [ ${DEBUG} == 'true' ]; then
|
||||
LOG "DUMP_CMD: ${DUMP_CMD}"
|
||||
fi
|
||||
kubectl exec -it -n openstack ${DBPOD} -c mariadb -- bash -c "${DUMP_CMD}" > ${dbfile}
|
||||
done
|
||||
|
||||
else
|
||||
# Interactive mariadb mysql client
|
||||
LOG "Interactive MariaDB mysql shell"
|
||||
MYSQL_CMD="${EVAL}; mysql ${DBOPTS} ${DATABASE}"
|
||||
if [ ! -z "${COMMAND}" ]; then
|
||||
MYSQL_CMD="${MYSQL_CMD} -e '${COMMAND}'"
|
||||
fi
|
||||
|
||||
if [ ${DEBUG} == 'true' ]; then
|
||||
LOG "MYSQL_CMD: ${MYSQL_CMD}"
|
||||
fi
|
||||
kubectl exec -it -n openstack ${DBPOD} -c mariadb -- bash -c "${MYSQL_CMD}"
|
||||
fi
|
||||
|
||||
exit 0
|
Loading…
Reference in New Issue