Merge "Add ceph entrypoint scripts"

This commit is contained in:
Jenkins 2017-07-14 16:32:03 +00:00 committed by Gerrit Code Review
commit 3be0325339
21 changed files with 1162 additions and 0 deletions

View File

@ -0,0 +1,223 @@
#!/bin/bash
set -ex
# log arguments with timestamp
function log {
if [ -z "$*" ]; then
return 1
fi
TIMESTAMP=$(date '+%F %T')
echo "${TIMESTAMP} $0: $*"
return 0
}
# ceph config file exists or die
function check_config {
if [[ ! -e /etc/ceph/${CLUSTER}.conf ]]; then
log "ERROR- /etc/ceph/${CLUSTER}.conf must exist; get it from your existing mon"
exit 1
fi
}
# ceph admin key exists or die
function check_admin_key {
if [[ ! -e $ADMIN_KEYRING ]]; then
log "ERROR- $ADMIN_KEYRING must exist; get it from your existing mon"
exit 1
fi
}
# Given two strings, return the length of the shared prefix
function prefix_length {
local maxlen=${#1}
for ((i=maxlen-1;i>=0;i--)); do
if [[ "${1:0:i}" == "${2:0:i}" ]]; then
echo $i
return
fi
done
}
# Test if a command line tool is available
function is_available {
command -v $@ &>/dev/null
}
# create the mandatory directories
function create_mandatory_directories {
# Let's create the bootstrap directories
for keyring in $OSD_BOOTSTRAP_KEYRING $MDS_BOOTSTRAP_KEYRING $RGW_BOOTSTRAP_KEYRING; do
mkdir -p $(dirname $keyring)
done
# Let's create the ceph directories
for directory in mon osd mds radosgw tmp mgr; do
mkdir -p /var/lib/ceph/$directory
done
# Make the monitor directory
mkdir -p "$MON_DATA_DIR"
# Create socket directory
mkdir -p /var/run/ceph
# Creating rados directories
mkdir -p /var/lib/ceph/radosgw/${RGW_NAME}
# Create the MDS directory
mkdir -p /var/lib/ceph/mds/${CLUSTER}-${MDS_NAME}
# Create the MGR directory
mkdir -p /var/lib/ceph/mgr/${CLUSTER}-$MGR_NAME
# Adjust the owner of all those directories
chown -R ceph. /var/run/ceph/ /var/lib/ceph/*
}
# Calculate proper device names, given a device and partition number
function dev_part {
local osd_device=${1}
local osd_partition=${2}
if [[ -L ${osd_device} ]]; then
# This device is a symlink. Work out it's actual device
local actual_device=$(readlink -f ${osd_device})
local bn=$(basename ${osd_device})
if [[ "${actual_device:0-1:1}" == [0-9] ]]; then
local desired_partition="${actual_device}p${osd_partition}"
else
local desired_partition="${actual_device}${osd_partition}"
fi
# Now search for a symlink in the directory of $osd_device
# that has the correct desired partition, and the longest
# shared prefix with the original symlink
local symdir=$(dirname ${osd_device})
local link=""
local pfxlen=0
for option in $(ls $symdir); do
if [[ $(readlink -f $symdir/$option) == $desired_partition ]]; then
local optprefixlen=$(prefix_length $option $bn)
if [[ $optprefixlen > $pfxlen ]]; then
link=$symdir/$option
pfxlen=$optprefixlen
fi
fi
done
if [[ $pfxlen -eq 0 ]]; then
>&2 log "Could not locate appropriate symlink for partition ${osd_partition} of ${osd_device}"
exit 1
fi
echo "$link"
elif [[ "${osd_device:0-1:1}" == [0-9] ]]; then
echo "${osd_device}p${osd_partition}"
else
echo "${osd_device}${osd_partition}"
fi
}
function osd_trying_to_determine_scenario {
if [ -z "${OSD_DEVICE}" ]; then
log "Bootstrapped OSD(s) found; using OSD directory"
source osd_directory.sh
osd_directory
elif $(parted --script ${OSD_DEVICE} print | egrep -sq '^ 1.*ceph data'); then
log "Bootstrapped OSD found; activating ${OSD_DEVICE}"
source osd_disk_activate.sh
osd_activate
else
log "Device detected, assuming ceph-disk scenario is desired"
log "Preparing and activating ${OSD_DEVICE}"
osd_disk
fi
}
function get_osd_dev {
for i in ${OSD_DISKS}
do
osd_id=$(echo ${i}|sed 's/\(.*\):\(.*\)/\1/')
osd_dev="/dev/$(echo ${i}|sed 's/\(.*\):\(.*\)/\2/')"
if [ ${osd_id} = ${1} ]; then
echo -n "${osd_dev}"
fi
done
}
function unsupported_scenario {
echo "ERROR: '${CEPH_DAEMON}' scenario or key/value store '${KV_TYPE}' is not supported by this distribution."
echo "ERROR: for the list of supported scenarios, please refer to your vendor."
exit 1
}
function is_integer {
# This function is about saying if the passed argument is an integer
# Supports also negative integers
# We use $@ here to consider everything given as parameter and not only the
# first one : that's mainly for splited strings like "10 10"
[[ $@ =~ ^-?[0-9]+$ ]]
}
# Transform any set of strings to lowercase
function to_lowercase {
echo "${@,,}"
}
# Transform any set of strings to uppercase
function to_uppercase {
echo "${@^^}"
}
# Replace any variable separated with comma with space
# e.g: DEBUG=foo,bar will become:
# echo ${DEBUG//,/ }
# foo bar
function comma_to_space {
echo "${@//,/ }"
}
# Get based distro by discovering the package manager
function get_package_manager {
if is_available rpm; then
OS_VENDOR=redhat
elif is_available dpkg; then
OS_VENDOR=ubuntu
fi
}
# Determine if current distribution is an Ubuntu-based distribution
function is_ubuntu {
get_package_manager
[[ "$OS_VENDOR" == "ubuntu" ]]
}
# Determine if current distribution is a RedHat-based distribution
function is_redhat {
get_package_manager
[[ "$OS_VENDOR" == "redhat" ]]
}
# Wait for a file to exist, regardless of the type
function wait_for_file {
timeout 10 bash -c "while [ ! -e ${1} ]; do echo 'Waiting for ${1} to show up' && sleep 1 ; done"
}
function valid_scenarios {
log "Valid values for CEPH_DAEMON are $(to_uppercase $ALL_SCENARIOS)."
log "Valid values for the daemon parameter are $ALL_SCENARIOS"
}
function invalid_ceph_daemon {
if [ -z "$CEPH_DAEMON" ]; then
log "ERROR- One of CEPH_DAEMON or a daemon parameter must be defined as the name of the daemon you want to deploy."
valid_scenarios
exit 1
else
log "ERROR- unrecognized scenario."
valid_scenarios
fi
}
function get_osd_path {
echo "$OSD_PATH_BASE-$1/"
}

View File

@ -0,0 +1,136 @@
#!/bin/bash
set -ex
export LC_ALL=C
source variables_entrypoint.sh
source common_functions.sh
source debug.sh
###########################
# CONFIGURATION GENERATOR #
###########################
# Load in the bootstrapping routines
# based on the data store
case "$KV_TYPE" in
etcd)
# TAG: kv_type_etcd
source /config.kv.etcd.sh
;;
k8s|kubernetes)
# TAG: kv_type_k8s
source /config.k8s.sh
;;
*)
source /config.static.sh
;;
esac
###############
# CEPH_DAEMON #
###############
# Normalize DAEMON to lowercase
CEPH_DAEMON=$(to_lowercase ${CEPH_DAEMON})
create_mandatory_directories
# If we are given a valid first argument, set the
# CEPH_DAEMON variable from it
case "$CEPH_DAEMON" in
populate_kvstore)
# TAG: populate_kvstore
source populate_kv.sh
populate_kv
;;
mon)
# TAG: mon
source start_mon.sh
start_mon
;;
osd)
# TAG: osd
source start_osd.sh
start_osd
;;
osd_directory)
# TAG: osd_directory
source start_osd.sh
OSD_TYPE="directory"
start_osd
;;
osd_directory_single)
# TAG: osd_directory_single
source start_osd.sh
OSD_TYPE="directory_single"
start_osd
;;
osd_ceph_disk)
# TAG: osd_ceph_disk
source start_osd.sh
OSD_TYPE="disk"
start_osd
;;
osd_ceph_disk_prepare)
# TAG: osd_ceph_disk_prepare
source start_osd.sh
OSD_TYPE="prepare"
start_osd
;;
osd_ceph_disk_activate)
# TAG: osd_ceph_disk_activate
source start_osd.sh
OSD_TYPE="activate"
start_osd
;;
osd_ceph_activate_journal)
# TAG: osd_ceph_activate_journal
source start_osd.sh
OSD_TYPE="activate_journal"
start_osd
;;
mds)
# TAG: mds
source start_mds.sh
start_mds
;;
rgw)
# TAG: rgw
source start_rgw.sh
start_rgw
;;
rgw_user)
# TAG: rgw_user
source start_rgw.sh
create_rgw_user
;;
restapi)
# TAG: restapi
source start_restapi.sh
start_restapi
;;
nfs)
# TAG: nfs
echo "Temporarily disabled due to broken package dependencies with nfs-ganesha"
echo "For more info see: https://github.com/ceph/ceph-docker/pull/564"
exit 1
source start_nfs.sh
start_nfs
;;
zap_device)
# TAG: zap_device
source zap_device.sh
zap_device
;;
mon_health)
# TAG: mon_health
source watch_mon_health.sh
watch_mon_health
;;
*)
invalid_ceph_daemon
;;
esac
exit 0

View File

@ -0,0 +1,20 @@
#!/bin/bash
set -ex
function osd_activate_journal {
if [[ -z "${OSD_JOURNAL}" ]];then
log "ERROR- You must provide a device to build your OSD journal ie: /dev/sdb2"
exit 1
fi
# watch the udev event queue, and exit if all current events are handled
udevadm settle --timeout=600
# wait till partition exists
wait_for ${OSD_JOURNAL}
chown ceph. ${OSD_JOURNAL}
ceph-disk -v --setuser ceph --setgroup disk activate-journal ${OSD_JOURNAL}
start_osd
}

View File

@ -0,0 +1,31 @@
# Start the latest OSD
# In case of forego, we don't run ceph-osd, start_forego will do it later
function start_osd() {
mode=$1 #forego or empty
OSD_ID=$(cat /var/lib/ceph/osd/$(ls -ltr /var/lib/ceph/osd/ | tail -n1 | awk -v pattern="$CLUSTER" '$0 ~ pattern {print $9}')/whoami)
OSD_PATH=$(get_osd_path $OSD_ID)
OSD_KEYRING="$OSD_PATH/keyring"
OSD_WEIGHT=$(df -P -k $OSD_PATH | tail -1 | awk '{ d= $2/1073741824 ; r = sprintf("%.2f", d); print r }')
ceph ${CLI_OPTS} --name=osd.${OSD_ID} --keyring=$OSD_KEYRING osd crush create-or-move -- ${OSD_ID} ${OSD_WEIGHT} ${CRUSH_LOCATION}
# ceph-disk activiate has exec'ed /usr/bin/ceph-osd ${CLI_OPTS} -f -i ${OSD_ID}
# wait till docker stop or ceph-osd is killed
OSD_PID=$(ps -ef |grep ceph-osd |grep osd.${OSD_ID} |awk '{print $2}')
if [ -n "${OSD_PID}" ]; then
log "OSD (PID ${OSD_PID}) is running, waiting till it exits"
while [ -e /proc/${OSD_PID} ]; do sleep 1;done
fi
if [[ "$mode" == "forego" ]]; then
echo "${CLUSTER}-${OSD_ID}: /usr/bin/ceph-osd ${CLI_OPTS} -f -i ${OSD_ID} --setuser ceph --setgroup disk" | tee -a /etc/forego/${CLUSTER}/Procfile
else
log "SUCCESS"
exec /usr/bin/ceph-osd ${CLI_OPTS} -f -i ${OSD_ID} --setuser ceph --setgroup disk
fi
}
# Starting forego
function start_forego() {
exec /usr/local/bin/forego start -f /etc/forego/${CLUSTER}/Procfile
}

View File

@ -0,0 +1,77 @@
#!/bin/bash
set -ex
function osd_directory {
if [[ ! -d /var/lib/ceph/osd ]]; then
log "ERROR- could not find the osd directory, did you bind mount the OSD data directory?"
log "ERROR- use -v <host_osd_data_dir>:/var/lib/ceph/osd"
exit 1
fi
if [ -z "${HOSTNAME}" ]; then
log "HOSTNAME not set; This will prevent to add an OSD into the CRUSH map"
exit 1
fi
# check if anything is present, if not, create an osd and its directory
if [[ -n "$(find /var/lib/ceph/osd -prune -empty)" ]]; then
log "Creating osd with ceph --cluster ${CLUSTER} osd create"
OSD_ID=$(ceph --cluster ${CLUSTER} osd create)
if is_integer "$OSD_ID"; then
log "OSD created with ID: ${OSD_ID}"
else
log "OSD creation failed: ${OSD_ID}"
exit 1
fi
OSD_PATH=$(get_osd_path $OSD_ID)
# create the folder and own it
mkdir -p $OSD_PATH
chown ceph. $OSD_PATH
log "created folder $OSD_PATH"
fi
# create the directory and an empty Procfile
mkdir -p /etc/forego/${CLUSTER}
echo "" > /etc/forego/${CLUSTER}/Procfile
for OSD_ID in $(ls /var/lib/ceph/osd | sed 's/.*-//'); do
OSD_PATH=$(get_osd_path $OSD_ID)
OSD_KEYRING="$OSD_PATH/keyring"
if [ -n "${JOURNAL_DIR}" ]; then
OSD_J="${JOURNAL_DIR}/journal.${OSD_ID}"
chown -R ceph. ${JOURNAL_DIR}
else
if [ -n "${JOURNAL}" ]; then
OSD_J=${JOURNAL}
chown -R ceph. $(dirname ${JOURNAL_DIR})
else
OSD_J=${OSD_PATH}/journal
fi
fi
# check to see if our osd has been initialized
if [ ! -e ${OSD_PATH}/keyring ]; then
chown ceph. $OSD_PATH
# create osd key and file structure
ceph-osd ${CLI_OPTS} -i $OSD_ID --mkfs --mkkey --mkjournal --osd-journal ${OSD_J} --setuser ceph --setgroup ceph
if [ ! -e $OSD_BOOTSTRAP_KEYRING ]; then
log "ERROR- $OSD_BOOTSTRAP_KEYRING must exist. You can extract it from your current monitor by running 'ceph auth get client.bootstrap-osd -o $OSD_BOOTSTRAP_KEYRING '"
exit 1
fi
timeout 10 ceph ${CLI_OPTS} --name client.bootstrap-osd --keyring $OSD_BOOTSTRAP_KEYRING health || exit 1
# add the osd key
ceph ${CLI_OPTS} --name client.bootstrap-osd --keyring $OSD_BOOTSTRAP_KEYRING auth add osd.${OSD_ID} -i ${OSD_KEYRING} osd 'allow *' mon 'allow profile osd' || log $1
log "done adding key"
chown ceph. ${OSD_KEYRING}
chmod 0600 ${OSD_KEYRING}
# add the osd to the crush map
OSD_WEIGHT=$(df -P -k $OSD_PATH | tail -1 | awk '{ d= $2/1073741824 ; r = sprintf("%.2f", d); print r }')
ceph ${CLI_OPTS} --name=osd.${OSD_ID} --keyring=${OSD_KEYRING} osd crush create-or-move -- ${OSD_ID} ${OSD_WEIGHT} ${CRUSH_LOCATION}
fi
echo "${CLUSTER}-${OSD_ID}: /usr/bin/ceph-osd ${CLI_OPTS} -f -i ${OSD_ID} --osd-journal ${OSD_J} -k $OSD_KEYRING" | tee -a /etc/forego/${CLUSTER}/Procfile
done
log "SUCCESS"
start_forego
}

View File

@ -0,0 +1,33 @@
#!/bin/bash
set -ex
function osd_directory_single {
if [[ ! -d /var/lib/ceph/osd ]]; then
log "ERROR- could not find the osd directory, did you bind mount the OSD data directory?"
log "ERROR- use -v <host_osd_data_dir>:/var/lib/ceph/osd"
exit 1
fi
# pick one osd and make sure no lock is held
for OSD_ID in $(ls /var/lib/ceph/osd | sed 's/.*-//'); do
OSD_PATH=$(get_osd_path $OSD_ID)
OSD_KEYRING="$OSD_PATH/keyring"
if [[ -n "$(find $OSD_PATH -prune -empty)" ]]; then
log "Looks like OSD: ${OSD_ID} has not been bootstrapped yet, doing nothing, moving on to the next discoverable OSD"
else
# check if the osd has a lock, if yes moving on, if not we run it
# many thanks to Julien Danjou for the python piece
if python -c "import sys, fcntl, struct; l = fcntl.fcntl(open('${OSD_PATH}/fsid', 'a'), fcntl.F_GETLK, struct.pack('hhllhh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)); l_type, l_whence, l_start, l_len, l_pid, l_sysid = struct.unpack('hhllhh', l); sys.exit(0 if l_type == fcntl.F_UNLCK else 1)"; then
log "Looks like OSD: ${OSD_ID} is not started, starting it..."
log "SUCCESS"
exec ceph-osd $DAEMON_OPTS -i ${OSD_ID} -k $OSD_KEYRING
break
fi
fi
done
log "Looks like all the OSDs are already running, doing nothing"
log "Exiting the container"
log "SUCCESS"
exit 0
}

View File

@ -0,0 +1,51 @@
#!/bin/bash
set -ex
function osd_activate {
if [[ -z "${OSD_DEVICE}" ]];then
log "ERROR- You must provide a device to build your OSD ie: /dev/sdb"
exit 1
fi
CEPH_DISK_OPTIONS=""
DATA_UUID=$(blkid -o value -s PARTUUID ${OSD_DEVICE}1)
LOCKBOX_UUID=$(blkid -o value -s PARTUUID ${OSD_DEVICE}3 || true)
JOURNAL_PART=$(dev_part ${OSD_DEVICE} 2)
ACTUAL_OSD_DEVICE=$(readlink -f ${OSD_DEVICE}) # resolve /dev/disk/by-* names
# watch the udev event queue, and exit if all current events are handled
udevadm settle --timeout=600
# wait till partition exists then activate it
if [[ -n "${OSD_JOURNAL}" ]]; then
wait_for_file ${OSD_DEVICE}
chown ceph. ${OSD_JOURNAL}
else
wait_for_file $(dev_part ${OSD_DEVICE} 1)
chown ceph. $JOURNAL_PART
fi
DATA_PART=$(dev_part ${OSD_DEVICE} 1)
MOUNTED_PART=${DATA_PART}
if [[ ${OSD_DMCRYPT} -eq 1 ]]; then
echo "Mounting LOCKBOX directory"
# NOTE(leseb): adding || true so when this bug will be fixed the entrypoint will not fail
# Ceph bug tracker: http://tracker.ceph.com/issues/18945
mkdir -p /var/lib/ceph/osd-lockbox/${DATA_UUID}
mount /dev/disk/by-partuuid/${LOCKBOX_UUID} /var/lib/ceph/osd-lockbox/${DATA_UUID} || true
CEPH_DISK_OPTIONS="$CEPH_DISK_OPTIONS --dmcrypt"
MOUNTED_PART="/dev/mapper/${DATA_UUID}"
fi
ceph-disk -v --setuser ceph --setgroup disk activate ${CEPH_DISK_OPTIONS} --no-start-daemon ${DATA_PART}
OSD_ID=$(grep "${MOUNTED_PART}" /proc/mounts | awk '{print $2}' | grep -oh '[0-9]*')
OSD_PATH=$(get_osd_path $OSD_ID)
OSD_KEYRING="$OSD_PATH/keyring"
OSD_WEIGHT=$(df -P -k $OSD_PATH | tail -1 | awk '{ d= $2/1073741824 ; r = sprintf("%.2f", d); print r }')
ceph ${CLI_OPTS} --name=osd.${OSD_ID} --keyring=$OSD_KEYRING osd crush create-or-move -- ${OSD_ID} ${OSD_WEIGHT} ${CRUSH_LOCATION}
log "SUCCESS"
exec /usr/bin/ceph-osd ${CLI_OPTS} -f -i ${OSD_ID} --setuser ceph --setgroup disk
}

View File

@ -0,0 +1,74 @@
#!/bin/bash
set -ex
function osd_disk_prepare {
if [[ -z "${OSD_DEVICE}" ]];then
log "ERROR- You must provide a device to build your OSD ie: /dev/sdb"
exit 1
fi
if [[ ! -e "${OSD_DEVICE}" ]]; then
log "ERROR- The device pointed by OSD_DEVICE ($OSD_DEVICE) doesn't exist !"
exit 1
fi
if [ ! -e $OSD_BOOTSTRAP_KEYRING ]; then
log "ERROR- $OSD_BOOTSTRAP_KEYRING must exist. You can extract it from your current monitor by running 'ceph auth get client.bootstrap-osd -o $OSD_BOOTSTRAP_KEYRING'"
exit 1
fi
timeout 10 ceph ${CLI_OPTS} --name client.bootstrap-osd --keyring $OSD_BOOTSTRAP_KEYRING health || exit 1
# check device status first
if ! parted --script ${OSD_DEVICE} print > /dev/null 2>&1; then
if [[ ${OSD_FORCE_ZAP} -eq 1 ]]; then
log "It looks like ${OSD_DEVICE} isn't consistent, however OSD_FORCE_ZAP is enabled so we are zapping the device anyway"
ceph-disk -v zap ${OSD_DEVICE}
else
log "Regarding parted, device ${OSD_DEVICE} is inconsistent/broken/weird."
log "It would be too dangerous to destroy it without any notification."
log "Please set OSD_FORCE_ZAP to '1' if you really want to zap this disk."
exit 1
fi
fi
# then search for some ceph metadata on the disk
if [[ "$(parted --script ${OSD_DEVICE} print | egrep '^ 1.*ceph data')" ]]; then
if [[ ${OSD_FORCE_ZAP} -eq 1 ]]; then
log "It looks like ${OSD_DEVICE} is an OSD, however OSD_FORCE_ZAP is enabled so we are zapping the device anyway"
ceph-disk -v zap ${OSD_DEVICE}
else
log "INFO- It looks like ${OSD_DEVICE} is an OSD, set OSD_FORCE_ZAP=1 to use this device anyway and zap its content"
log "You can also use the zap_device scenario on the appropriate device to zap it"
log "Moving on, trying to activate the OSD now."
return
fi
fi
if [[ ${OSD_BLUESTORE} -eq 1 ]]; then
ceph-disk -v prepare ${CLI_OPTS} --bluestore ${OSD_DEVICE}
elif [[ ${OSD_DMCRYPT} -eq 1 ]]; then
get_admin_key
check_admin_key
# the admin key must be present on the node
# in order to store the encrypted key in the monitor's k/v store
ceph-disk -v prepare ${CLI_OPTS} --journal-uuid ${OSD_JOURNAL_UUID} --lockbox-uuid ${OSD_LOCKBOX_UUID} --dmcrypt ${OSD_DEVICE} ${OSD_JOURNAL}
echo "Unmounting LOCKBOX directory"
# NOTE(leseb): adding || true so when this bug will be fixed the entrypoint will not fail
# Ceph bug tracker: http://tracker.ceph.com/issues/18944
DATA_UUID=$(blkid -o value -s PARTUUID ${OSD_DEVICE}1)
umount /var/lib/ceph/osd-lockbox/${DATA_UUID} || true
else
ceph-disk -v prepare ${CLI_OPTS} --journal-uuid ${OSD_JOURNAL_UUID} ${OSD_DEVICE} ${OSD_JOURNAL}
fi
# watch the udev event queue, and exit if all current events are handled
udevadm settle --timeout=600
if [[ -n "${OSD_JOURNAL}" ]]; then
wait_for_file ${OSD_JOURNAL}
chown ceph. ${OSD_JOURNAL}
else
wait_for_file $(dev_part ${OSD_DEVICE} 2)
chown ceph. $(dev_part ${OSD_DEVICE} 2)
fi
}

View File

@ -0,0 +1,66 @@
#!/bin/bash
set -ex
function osd_disks {
if [[ ! -d /var/lib/ceph/osd ]]; then
log "ERROR- could not find the osd directory, did you bind mount the OSD data directory?"
log "ERROR- use -v <host_osd_data_dir>:/var/lib/ceph/osd"
exit 1
fi
if [[ -z ${OSD_DISKS} ]]; then
log "ERROR- could not find the osd devices, did you configure OSD disks?"
log "ERROR- use -e OSD_DISKS=\"0:sdd 1:sde 2:sdf\""
exit 1
fi
# Create the directory and an empty Procfile
mkdir -p /etc/forego/${CLUSTER}
echo "" > /etc/forego/${CLUSTER}/Procfile
# check if anything is there, if not create an osd with directory
if [[ -z "$(find /var/lib/ceph/osd -prune -empty)" ]]; then
log "Mount existing and prepared OSD disks for ceph-cluster ${CLUSTER}"
for OSD_ID in $(ls /var/lib/ceph/osd | sed 's/.*-//'); do
OSD_PATH=$(get_osd_path $OSD_ID)
OSD_KEYRING="$OSD_PATH/keyring"
OSD_DEV=$(get_osd_dev ${OSD_ID})
if [[ -z ${OSD_DEV} ]]; then
log "No device mapping for ${CLUSTER}-${OSD_ID} for ceph-cluster ${CLUSTER}"
exit 1
fi
mount ${MOUNT_OPTS} $(dev_part ${OSD_DEV} 1) $OSD_PATH
xOSD_ID=$(cat $OSD_PATH/whoami)
if [[ "${OSD_ID}" != "${xOSD_ID}" ]]; then
log "Device ${OSD_DEV} is corrupt for $OSD_PATH"
exit 1
fi
echo "${CLUSTER}-${OSD_ID}: /usr/bin/ceph-osd ${CLI_OPTS} -f -i ${OSD_ID} --setuser ceph --setgroup disk" | tee -a /etc/forego/${CLUSTER}/Procfile
done
exec /usr/local/bin/forego start -f /etc/forego/${CLUSTER}/Procfile
fi
#
# As per the exec in the first statement, we only reach here if there is some OSDs
#
for OSD_DISK in ${OSD_DISKS}; do
OSD_DEV="/dev/$(echo ${OSD_DISK}|sed 's/\(.*\):\(.*\)/\2/')"
if [[ "$(parted --script ${OSD_DEV} print | egrep '^ 1.*ceph data')" ]]; then
if [[ ${OSD_FORCE_ZAP} -eq 1 ]]; then
ceph-disk -v zap ${OSD_DEV}
else
log "ERROR- It looks like the device ($OSD_DEV) is an OSD, set OSD_FORCE_ZAP=1 to use this device anyway and zap its content"
exit 1
fi
fi
ceph-disk -v prepare ${CLI_OPTS} ${OSD_DEV} ${OSD_JOURNAL}
# prepare the OSDs configuration and start them later
start_osd forego
done
log "SUCCESS"
# Actually, starting them as per forego configuration
start_forego
}

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
ceph mon remove $(hostname -s)

View File

@ -0,0 +1,58 @@
#!/bin/bash
set -ex
function start_mds {
get_config
check_config
# Check to see if we are a new MDS
if [ ! -e $MDS_KEYRING ]; then
if [ -e $ADMIN_KEYRING ]; then
KEYRING_OPT="--name client.admin --keyring $ADMIN_KEYRING"
elif [ -e $MDS_BOOTSTRAP_KEYRING ]; then
KEYRING_OPT="--name client.bootstrap-mds --keyring $MDS_BOOTSTRAP_KEYRING"
else
log "ERROR- Failed to bootstrap MDS: could not find admin or bootstrap-mds keyring. You can extract it from your current monitor by running 'ceph auth get client.bootstrap-mds -o $MDS_BOOTSTRAP_KEYRING"
exit 1
fi
timeout 10 ceph ${CLI_OPTS} $KEYRING_OPT health || exit 1
# Generate the MDS key
ceph ${CLI_OPTS} $KEYRING_OPT auth get-or-create mds.$MDS_NAME osd 'allow rwx' mds 'allow' mon 'allow profile mds' -o $MDS_KEYRING
chown ceph. $MDS_KEYRING
chmod 600 $MDS_KEYRING
fi
# NOTE (leseb): having the admin keyring is really a security issue
# If we need to bootstrap a MDS we should probably create the following on the monitors
# I understand that this handy to do this here
# but having the admin key inside every container is a concern
# Create the Ceph filesystem, if necessary
if [ $CEPHFS_CREATE -eq 1 ]; then
get_admin_key
check_admin_key
if [[ "$(ceph ${CLI_OPTS} fs ls | grep -c name:.${CEPHFS_NAME},)" -eq 0 ]]; then
# Make sure the specified data pool exists
if ! ceph ${CLI_OPTS} osd pool stats ${CEPHFS_DATA_POOL} > /dev/null 2>&1; then
ceph ${CLI_OPTS} osd pool create ${CEPHFS_DATA_POOL} ${CEPHFS_DATA_POOL_PG}
fi
# Make sure the specified metadata pool exists
if ! ceph ${CLI_OPTS} osd pool stats ${CEPHFS_METADATA_POOL} > /dev/null 2>&1; then
ceph ${CLI_OPTS} osd pool create ${CEPHFS_METADATA_POOL} ${CEPHFS_METADATA_POOL_PG}
fi
ceph ${CLI_OPTS} fs new ${CEPHFS_NAME} ${CEPHFS_METADATA_POOL} ${CEPHFS_DATA_POOL}
fi
fi
log "SUCCESS"
# NOTE: prefixing this with exec causes it to die (commit suicide)
/usr/bin/ceph-mds $DAEMON_OPTS -i ${MDS_NAME}
}

View File

@ -0,0 +1,141 @@
#!/bin/bash
set -ex
IPV4_REGEXP='[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
IPV4_NETWORK_REGEXP="$IPV4_REGEXP/[0-9]\{1,2\}"
function flat_to_ipv6 {
# Get a flat input like fe800000000000000042acfffe110003 and output fe80::0042:acff:fe11:0003
# This input usually comes from the ipv6_route or if_inet6 files from /proc
# First, split the string in set of 4 bytes with ":" as separator
value=$(echo "$@" | sed -e 's/.\{4\}/&:/g' -e '$s/\:$//')
# Let's remove the useless 0000 and "::"
value=${value//0000/:};
while $(echo $value | grep -q ":::"); do
value=${value//::/:};
done
echo $value
}
function get_ip {
NIC=$1
# IPv4 is the default unless we specify it
IP_VERSION=${2:-4}
# We should avoid reporting any IPv6 "scope local" interface that would make the ceph bind() call to fail
if is_available ip; then
ip -$IP_VERSION -o a s $NIC | grep "scope global" | awk '{ sub ("/..", "", $4); print $4 }' || true
else
case "$IP_VERSION" in
6)
# We don't want local scope, so let's remove field 4 if not 00
ip=$(flat_to_ipv6 $(grep $NIC /proc/net/if_inet6 | awk '$4==00 {print $1}'))
# IPv6 IPs should be surrounded by brackets to let ceph-monmap being happy
echo "[$ip]"
;;
*)
grep -o "$IPV4_REGEXP" /proc/net/fib_trie | grep -vEw "^127|255$|0$" | head -1
;;
esac
fi
}
function get_network {
NIC=$1
# IPv4 is the default unless we specify it
IP_VERSION=${2:-4}
case "$IP_VERSION" in
6)
if is_available ip; then
ip -$IP_VERSION route show dev $NIC | grep proto | awk '{ print $1 }' | grep -v default | grep -vi ^fe80 || true
else
# We don't want the link local routes
line=$(grep $NIC /proc/1/task/1/net/ipv6_route | awk '$2==40' | grep -v ^fe80 || true)
base=$(echo $line | awk '{ print $1 }')
base=$(flat_to_ipv6 $base)
mask=$(echo $line | awk '{ print $2 }')
echo "$base/$((16#$mask))"
fi
;;
*)
if is_available ip; then
ip -$IP_VERSION route show dev $NIC | grep proto | awk '{ print $1 }' | grep -v default | grep "/" || true
else
grep -o "$IPV4_NETWORK_REGEXP" /proc/net/fib_trie | grep -vE "^127|^0" | head -1
fi
;;
esac
}
function start_mon {
if [[ ${NETWORK_AUTO_DETECT} -eq 0 ]]; then
if [[ -z "$CEPH_PUBLIC_NETWORK" ]]; then
log "ERROR- CEPH_PUBLIC_NETWORK must be defined as the name of the network for the OSDs"
exit 1
fi
if [[ -z "$MON_IP" ]]; then
log "ERROR- MON_IP must be defined as the IP address of the monitor"
exit 1
fi
else
NIC_MORE_TRAFFIC=$(grep -vE "lo:|face|Inter" /proc/net/dev | sort -n -k 2 | tail -1 | awk '{ sub (":", "", $1); print $1 }')
IP_VERSION=4
if [ ${NETWORK_AUTO_DETECT} -gt 1 ]; then
MON_IP=$(get_ip ${NIC_MORE_TRAFFIC} ${NETWORK_AUTO_DETECT})
CEPH_PUBLIC_NETWORK=$(get_network ${NIC_MORE_TRAFFIC} ${NETWORK_AUTO_DETECT})
IP_VERSION=${NETWORK_AUTO_DETECT}
else # Means -eq 1
MON_IP="[$(get_ip ${NIC_MORE_TRAFFIC} 6)]"
CEPH_PUBLIC_NETWORK=$(get_network ${NIC_MORE_TRAFFIC} 6)
IP_VERSION=6
if [ -z "$MON_IP" ]; then
MON_IP=$(get_ip ${NIC_MORE_TRAFFIC})
CEPH_PUBLIC_NETWORK=$(get_network ${NIC_MORE_TRAFFIC})
IP_VERSION=4
fi
fi
fi
if [[ -z "$MON_IP" || -z "$CEPH_PUBLIC_NETWORK" ]]; then
log "ERROR- it looks like we have not been able to discover the network settings"
exit 1
fi
get_mon_config $IP_VERSION
# If we don't have a monitor keyring, this is a new monitor
if [ ! -e "$MON_DATA_DIR/keyring" ]; then
if [ ! -e $MON_KEYRING ]; then
log "ERROR- $MON_KEYRING must exist. You can extract it from your current monitor by running 'ceph auth get mon. -o $MON_KEYRING' or use a KV Store"
exit 1
fi
if [ ! -e $MONMAP ]; then
log "ERROR- $MONMAP must exist. You can extract it from your current monitor by running 'ceph mon getmap -o $MONMAP' or use a KV Store"
exit 1
fi
# Testing if it's not the first monitor, if one key doesn't exist we assume none of them exist
for keyring in $OSD_BOOTSTRAP_KEYRING $MDS_BOOTSTRAP_KEYRING $RGW_BOOTSTRAP_KEYRING $ADMIN_KEYRING; do
ceph-authtool $MON_KEYRING --import-keyring $keyring
done
# Prepare the monitor daemon's directory with the map and keyring
ceph-mon --setuser ceph --setgroup ceph --cluster ${CLUSTER} --mkfs -i ${MON_NAME} --inject-monmap $MONMAP --keyring $MON_KEYRING --mon-data "$MON_DATA_DIR"
else
log "Trying to get the most recent monmap..."
# Ignore when we timeout, in most cases that means the cluster has no quorum or
# no mons are up and running yet
timeout 5 ceph ${CLI_OPTS} mon getmap -o $MONMAP || true
ceph-mon --setuser ceph --setgroup ceph --cluster ${CLUSTER} -i ${MON_NAME} --inject-monmap $MONMAP --keyring $MON_KEYRING --mon-data "$MON_DATA_DIR"
timeout 7 ceph ${CLI_OPTS} mon add "${MON_NAME}" "${MON_IP}:6789" || true
fi
log "SUCCESS"
# start MON
exec /usr/bin/ceph-mon $DAEMON_OPTS -i ${MON_NAME} --mon-data "$MON_DATA_DIR" --public-addr "${MON_IP}:6789"
}

View File

@ -0,0 +1,61 @@
#!/bin/bash
set -ex
if is_redhat; then
source /etc/sysconfig/ceph
elif is_ubuntu; then
source /etc/default/ceph
fi
function start_osd {
get_config
check_config
if [ ${CEPH_GET_ADMIN_KEY} -eq 1 ]; then
get_admin_key
check_admin_key
fi
case "$OSD_TYPE" in
directory)
source osd_directory.sh
source osd_common.sh
osd_directory
;;
directory_single)
source osd_directory_single.sh
osd_directory_single
;;
disk)
osd_disk
;;
prepare)
source osd_disk_prepare.sh
osd_disk_prepare
;;
activate)
source osd_disk_activate.sh
osd_activate
;;
devices)
source osd_disks.sh
source osd_common.sh
osd_disks
;;
activate_journal)
source osd_activate_journal.sh
source osd_common.sh
osd_activate_journal
;;
*)
osd_trying_to_determine_scenario
;;
esac
}
function osd_disk {
source osd_disk_prepare.sh
source osd_disk_activate.sh
osd_disk_prepare
osd_activate
}

View File

@ -0,0 +1,55 @@
#!/bin/bash
set -ex
function start_rgw {
get_config
check_config
if [ ${CEPH_GET_ADMIN_KEY} -eq 1 ]; then
get_admin_key
check_admin_key
fi
# Check to see if our RGW has been initialized
if [ ! -e $RGW_KEYRING ]; then
if [ ! -e $RGW_BOOTSTRAP_KEYRING ]; then
log "ERROR- $RGW_BOOTSTRAP_KEYRING must exist. You can extract it from your current monitor by running 'ceph auth get client.bootstrap-rgw -o $RGW_BOOTSTRAP_KEYRING'"
exit 1
fi
timeout 10 ceph ${CLI_OPTS} --name client.bootstrap-rgw --keyring $RGW_BOOTSTRAP_KEYRING health || exit 1
# Generate the RGW key
ceph ${CLI_OPTS} --name client.bootstrap-rgw --keyring $RGW_BOOTSTRAP_KEYRING auth get-or-create client.rgw.${RGW_NAME} osd 'allow rwx' mon 'allow rw' -o $RGW_KEYRING
chown ceph. $RGW_KEYRING
chmod 0600 $RGW_KEYRING
fi
log "SUCCESS"
RGW_FRONTENDS="civetweb port=$RGW_CIVETWEB_PORT"
if [ "$RGW_REMOTE_CGI" -eq 1 ]; then
RGW_FRONTENDS="fastcgi socket_port=$RGW_REMOTE_CGI_PORT socket_host=$RGW_REMOTE_CGI_HOST"
fi
exec /usr/bin/radosgw $DAEMON_OPTS -n client.rgw.${RGW_NAME} -k $RGW_KEYRING --rgw-socket-path="" --rgw-zonegroup="$RGW_ZONEGROUP" --rgw-zone="$RGW_ZONE" --rgw-frontends="$RGW_FRONTENDS"
}
function create_rgw_user {
# Check to see if our RGW has been initialized
if [ ! -e /var/lib/ceph/radosgw/keyring ]; then
log "ERROR- /var/lib/ceph/radosgw/keyring must exist. Please get it from your Rados Gateway"
exit 1
fi
mv /var/lib/ceph/radosgw/keyring $RGW_KEYRING
USER_KEY=""
if [ -n "${RGW_USER_SECRET_KEY}" ]; then
USER_KEY="--access-key=${RGW_USER_USER_KEY} --secret=${RGW_USER_SECRET_KEY}"
fi
exec radosgw-admin user create --uid=${RGW_USER} ${USER_KEY} --display-name="RGW ${RGW_USER} User" -c /etc/ceph/${CLUSTER}.conf
}

View File

@ -0,0 +1,13 @@
#!/bin/bash
set -ex
function watch_mon_health {
while [ true ]
do
log "checking for zombie mons"
/check_zombie_mons.py || true
log "sleep 30 sec"
sleep 30
done
}

View File

@ -33,3 +33,33 @@ data:
ceph-namespace-client-key.sh: |+
{{ tuple "bin/_ceph-namespace-client-key.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
{{- end }}
common_functions.sh: |+
{{ tuple "bin/_common_functions.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
entrypoint.sh: |+
{{ tuple "bin/_entrypoint.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
osd_activate_journal.sh: |+
{{ tuple "bin/_osd_activate_journal.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
osd_common.sh: |+
{{ tuple "bin/_osd_common.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
osd_directory.sh: |+
{{ tuple "bin/_osd_directory.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
osd_directory_single.sh: |+
{{ tuple "bin/_osd_directory_single.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
osd_disk_activate.sh: |+
{{ tuple "bin/_osd_disk_activate.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
osd_disk_prepare.sh: |+
{{ tuple "bin/_osd_disk_prepare.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
osd_disks.sh: |+
{{ tuple "bin/_osd_disks.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
remove-mon.sh: |+
{{ tuple "bin/_remove-mon.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
start_mon.sh: |+
{{ tuple "bin/_start_mon.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
start_osd.sh: |+
{{ tuple "bin/_start_osd.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
start_mds.sh: |+
{{ tuple "bin/_start_mds.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
start_rgw.sh: |+
{{ tuple "bin/_start_rgw.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
watch_mon_health.sh: |+
{{ tuple "bin/_watch_mon_health.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}

View File

@ -78,6 +78,22 @@ spec:
- name: ceph
mountPath: /var/lib/ceph
readOnly: false
- name: ceph-bin
mountPath: /entrypoint.sh
subPath: entrypoint.sh
readOnly: true
- name: ceph-bin
mountPath: /start_osd.sh
subPath: start_osd.sh
readOnly: true
- name: ceph-bin
mountPath: /osd_directory.sh
subPath: osd_directory.sh
readOnly: true
- name: ceph-bin
mountPath: /common_functions.sh
subPath: common_functions.sh
readOnly: true
- name: ceph-etc
mountPath: /etc/ceph/ceph.conf
subPath: ceph.conf
@ -111,6 +127,10 @@ spec:
- name: ceph
hostPath:
path: {{ .Values.ceph.storage.var_directory }}
- name: ceph-bin
configMap:
name: ceph-bin
defaultMode: 0555
- name: ceph-etc
configMap:
name: ceph-etc

View File

@ -64,6 +64,18 @@ spec:
command:
- /entrypoint.sh
volumeMounts:
- name: ceph-bin
mountPath: /entrypoint.sh
subPath: entrypoint.sh
readOnly: true
- name: ceph-bin
mountPath: /start_mds.sh
subPath: start_mds.sh
readOnly: true
- name: ceph-bin
mountPath: /common_functions.sh
subPath: common_functions.sh
readOnly: true
- name: ceph-etc
mountPath: /etc/ceph/ceph.conf
subPath: ceph.conf
@ -102,6 +114,10 @@ spec:
configMap:
name: ceph-etc
defaultMode: 0444
- name: ceph-bin
configMap:
name: ceph-bin
defaultMode: 0555
- name: ceph-client-admin-keyring
secret:
secretName: {{ .Values.secrets.keyrings.admin }}

View File

@ -64,6 +64,18 @@ spec:
command:
- /entrypoint.sh
volumeMounts:
- name: ceph-bin
mountPath: /entrypoint.sh
subPath: entrypoint.sh
readOnly: true
- name: ceph-bin
mountPath: /watch_mon_health.sh
subPath: watch_mon_health.sh
readOnly: true
- name: ceph-bin
mountPath: /common_functions.sh
subPath: common_functions.sh
readOnly: true
- name: ceph-etc
mountPath: /etc/ceph/ceph.conf
subPath: ceph.conf
@ -93,6 +105,10 @@ spec:
configMap:
name: ceph-etc
defaultMode: 0444
- name: ceph-bin
configMap:
name: ceph-bin
defaultMode: 0555
- name: ceph-client-admin-keyring
secret:
secretName: {{ .Values.secrets.keyrings.admin }}

View File

@ -65,6 +65,18 @@ spec:
command:
- /entrypoint.sh
volumeMounts:
- name: ceph-bin
mountPath: /entrypoint.sh
subPath: entrypoint.sh
readOnly: true
- name: ceph-bin
mountPath: /start_rgw.sh
subPath: start_rgw.sh
readOnly: true
- name: ceph-bin
mountPath: /common_functions.sh
subPath: common_functions.sh
readOnly: true
- name: ceph-etc
mountPath: /etc/ceph/ceph.conf
subPath: ceph.conf
@ -101,6 +113,10 @@ spec:
port: {{ .Values.network.port.rgw_target }}
timeoutSeconds: 5
volumes:
- name: ceph-bin
configMap:
name: ceph-bin
defaultMode: 0555
- name: ceph-etc
configMap:
name: ceph-etc

View File

@ -96,6 +96,22 @@ spec:
command:
- "/remove-mon.sh"
volumeMounts:
- name: ceph-bin
mountPath: /entrypoint.sh
subPath: entrypoint.sh
readOnly: true
- name: ceph-bin
mountPath: /start_mon.sh
subPath: start_mon.sh
readOnly: true
- name: ceph-bin
mountPath: /remove-mon.sh
subPath: remove-mon.sh
readOnly: true
- name: ceph-bin
mountPath: /common_functions.sh
subPath: common_functions.sh
readOnly: true
- name: ceph-etc
mountPath: /etc/ceph/ceph.conf
subPath: ceph.conf
@ -130,6 +146,10 @@ spec:
port: 6789
timeoutSeconds: 5
volumes:
- name: ceph-bin
configMap:
name: ceph-bin
defaultMode: 0555
- name: ceph-etc
configMap:
name: ceph-etc