blob: f384cd2d5ceb6a93095e6cd6db24c29b4b4dcee7 [file] [log] [blame]
#!/bin/sh
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e -u
STATE_DIR=/run/cros-machine-id-regen
DEFAULT_MACHINE_ID_FILE=/var/lib/dbus/machine-id
bail_if_not_root() {
if [ "$(id -u)" != 0 ]; then
echo "$0: this script must be run as root." >&2
exit 1
fi
}
ensure_state_dir() {
mkdir -p "${STATE_DIR}"
chmod 700 "${STATE_DIR}"
}
is_avahi_running() {
initctl status avahi | grep -q "^avahi start"
return $?
}
log() {
logger -t cros-machine-id-regen "$@"
}
emit_metrics() {
local reason="$1"
local seconds_since_last_update="$2"
local reason_enum_value=0
local reason_pretty="Unknown"
case "${reason}" in
network)
reason_enum_value=1
reason_pretty="Network"
;;
periodic)
reason_enum_value=2
reason_pretty="Periodic"
;;
esac
metrics_client -s ChromeOS.MachineIdRegen.Reason "${reason_enum_value}"
if [ "${seconds_since_last_update}" != 0 ]; then
metrics_client ChromeOS.MachineIdRegen.AgeSeconds \
"${seconds_since_last_update}" 0 86400 50
metrics_client ChromeOS.MachineIdRegen.AgeSeconds_${reason_pretty} \
"${seconds_since_last_update}" 0 86400 50
fi
}
regen() {
local machine_id_file="$1"
local reason="$2"
local minimum_age_seconds="$3"
# Read machine uptime and round to nearest integer.
local uptime_seconds
uptime_seconds=$(printf %.0f $(cut -d' ' -f1 /proc/uptime))
# Figure out path to timestamp file.
timestamp_path=${STATE_DIR}/timestamp$(echo "${machine_id_file}" | tr / _)
# Read last update and calculate how long since last time.
local last_update=0
if [ -e "${timestamp_path}" ]; then
last_update=$(cat "${timestamp_path}")
fi
local seconds_since_last_update=""
if [ "${last_update}" != 0 ]; then
seconds_since_last_update=$((uptime_seconds - last_update))
fi
# Skip updating if we did so recently.
if [ -n "${seconds_since_last_update}" ] && \
[ "${minimum_age_seconds}" != 0 ] && \
[ "${seconds_since_last_update}" -lt "${minimum_age_seconds}" ]; then
log "Not regenerating since we did so ${seconds_since_last_update} seconds ago."
return 0
fi
# Regenerate the machine identifier.
rm -f "${machine_id_file}".new
dbus-uuidgen --ensure="${machine_id_file}".new
mv "${machine_id_file}".new "${machine_id_file}"
# Update state.
echo "${uptime_seconds}" > "${timestamp_path}"
# If running, tell avahi to use the new machine-id.
if is_avahi_running; then
dbus-send --system --dest=org.freedesktop.Avahi --print-reply \
--reply-timeout=10000 \
/ org.freedesktop.Avahi.Server.SetHostName \
string:"$(cat "${machine_id_file}")" > /dev/null
fi
# Synchronously run Upstart jobs wanting to run when rotating the id.
initctl emit cros-machine-id-regenerated
# Log and emit metrics.
log "Regenerated ${machine_id_file} (reason: ${reason})."
emit_metrics "${reason}" "${seconds_since_last_update}"
}
show_help() {
cat<<EOF
usage: $0 -r REASON [-t MINIMUM_AGE_SECONDS] [-p PATH_TO_FILE]
Regenerates the ${DEFAULT_MACHINE_ID_FILE} file.
Arguments:
-r The reason for regenerating, e.g. 'network' or 'periodic'.
-t Don't regenerate if last regenerated this many seconds ago.
-p Path to machine-id file to use instead of ${DEFAULT_MACHINE_ID_FILE}.
EOF
}
main() {
# Parse command-line options.
local reason=""
local minimum_age_seconds=0
local machine_id_file="${DEFAULT_MACHINE_ID_FILE}"
while getopts "ht:r:p:" opt; do
case "${opt}" in
h)
show_help
exit 0
;;
t)
minimum_age_seconds="${OPTARG}"
;;
r)
reason="${OPTARG}"
;;
p)
machine_id_file="${OPTARG}"
;;
esac
done
# Bail if no reason is given.
if [ -z "${reason}" ]; then
show_help
exit 1
fi
# Regenerate the machine idenfitier and ensure multiple invocations
# are serialized.
bail_if_not_root
ensure_state_dir
(
flock --timeout 15 -n 9
regen "${machine_id_file}" "${reason}" "${minimum_age_seconds}"
) 9>"${STATE_DIR}"/lock
}
main "$@"