| #!/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 "$@" |