-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Reset factory #14105
Support Reset factory #14105
Changes from all commits
75aff97
4a90fca
dce4f6b
71d5ae4
275c013
3ae528b
9ba90d1
4f11c0e
251c47a
8be655f
837fd2b
365e9c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{%- set users_dict = { | ||
username: { | ||
"password": password, | ||
"expire": password_expire | ||
} | ||
} | ||
-%} | ||
{{ users_dict | tojson(indent=4) }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -607,12 +607,17 @@ sudo bash -c "echo enabled=false > $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" | |
# Generate initial SONiC configuration file | ||
j2 files/build_templates/init_cfg.json.j2 | sudo tee $FILESYSTEM_ROOT/etc/sonic/init_cfg.json | ||
|
||
# Copy config-setup script and service file | ||
# Copy config-setup script, conf file and service file | ||
j2 files/build_templates/config-setup.service.j2 | sudo tee $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/config-setup.service | ||
sudo cp $IMAGE_CONFIGS/config-setup/config-setup $FILESYSTEM_ROOT/usr/bin/config-setup | ||
sudo mkdir -p $FILESYSTEM_ROOT/etc/config-setup | ||
sudo cp $IMAGE_CONFIGS/config-setup/config-setup.conf $FILESYSTEM_ROOT/etc/config-setup/config-setup.conf | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’m not sure if I am understanding correctly. |
||
echo "config-setup.service" | sudo tee -a $GENERATED_SERVICE_FILE | ||
sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-setup.service | ||
|
||
# Copy reset-factory script and service | ||
sudo cp $IMAGE_CONFIGS/reset-factory/reset-factory $FILESYSTEM_ROOT/usr/bin/reset-factory | ||
|
||
# Add delayed tacacs application service | ||
sudo cp files/build_templates/tacacs-config.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/ | ||
echo "tacacs-config.timer" | sudo tee -a $GENERATED_SERVICE_FILE | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,7 @@ CONFIG_SETUP_VAR_DIR=/var/lib/config-setup | |
CONFIG_SETUP_PRE_MIGRATION_FLAG=${CONFIG_SETUP_VAR_DIR}/pending_pre_migration | ||
CONFIG_SETUP_POST_MIGRATION_FLAG=${CONFIG_SETUP_VAR_DIR}/pending_post_migration | ||
CONFIG_SETUP_INITIALIZATION_FLAG=${CONFIG_SETUP_VAR_DIR}/pending_initialization | ||
CONFIG_SETUP_CONF=/etc/config-setup/config-setup.conf | ||
|
||
TACACS_JSON_BACKUP=tacacs.json | ||
|
||
|
@@ -56,17 +57,31 @@ usage() | |
EOF | ||
} | ||
|
||
# Factory command usage and help | ||
usage_factory() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the comments. usage_factory() is used for "config-setup factory" help command. |
||
{ | ||
cat << EOF | ||
Usage: config-setup factory < keep-basic > | ||
|
||
Create factory default configuration and save it to | ||
to ${CONFIG_DB_JSON}. | ||
|
||
keep-basic - Preserves basic configurations only. | ||
EOF | ||
} | ||
|
||
# run given script | ||
run_hook() { | ||
local script="$1" | ||
local script_param="$2" | ||
local exit_status=0 | ||
|
||
if [ -f $script ]; then | ||
# Check hook for syntactical correctness before executing it | ||
/bin/bash -n $script | ||
/bin/bash -n $script $script_param | ||
exit_status=$? | ||
if [ "$exit_status" -eq 0 ]; then | ||
. $script | ||
. $script $script_param | ||
fi | ||
exit_status=$? | ||
fi | ||
|
@@ -82,6 +97,7 @@ run_hook() { | |
run_hookdir() { | ||
local dir="$1" | ||
local progress_file="$2" | ||
local script_param="$3" | ||
local exit_status=0 | ||
|
||
if [ -d "$dir" ]; then | ||
|
@@ -94,7 +110,7 @@ run_hookdir() { | |
fi | ||
|
||
for script in $SCRIPT_LIST; do | ||
run_hook $script | ||
run_hook $script $script_param | ||
exit_status=$((exit_status|$?)) | ||
script_name=$(basename $script) | ||
sed -i "/$script_name/d" $progress_file | ||
|
@@ -215,10 +231,33 @@ generate_config() | |
if [ "$1" = "ztp" ]; then | ||
/usr/lib/ztp/ztp-profile.sh create ${DEST_FILE} | ||
elif [ "$1" = "factory" ]; then | ||
FACTORY_TYPE=$3 | ||
rv=1 | ||
|
||
if [ "$FACTORY_TYPE" = "keep-basic" ]; then | ||
TMP_FILE="/tmp/tmp_keep_basic.$$.json" | ||
# Verify the DEST_FILE exists and KEEP_BASIC_TABLES was defined in CONFIG_SETUP_CONF | ||
if [ ! -f ${DEST_FILE} ] || [ -z "${KEEP_BASIC_TABLES}" ]; then | ||
# Create empty valid json file | ||
echo {} > ${TMP_FILE} | ||
else | ||
# Create filtered json file with keep-basic tables only | ||
jq 'with_entries(select([.key] | inside($tables)))' --argjson tables "$KEEP_BASIC_TABLES" ${DEST_FILE} > ${TMP_FILE} | ||
fi | ||
# Create factory default | ||
sonic-cfggen -H -k ${HW_KEY} --preset ${DEFAULT_PRESET} > ${DEST_FILE} | ||
rv=$? | ||
if [ $rv -ne 0 ]; then | ||
rm -f ${TMP_FILE} | ||
return $rv | ||
fi | ||
# Merge factory default config with filtered json | ||
jq --indent 4 -s '.[0] * .[1]' ${DEST_FILE} ${TMP_FILE} > tmp.$$.json && mv tmp.$$.json ${DEST_FILE} | ||
rm -f ${TMP_FILE} | ||
fi | ||
|
||
# Execute config initialization hooks | ||
run_hookdir ${FACTORY_DEFAULT_HOOKS} ${CONFIG_SETUP_INITIALIZATION_FLAG} | ||
run_hookdir ${FACTORY_DEFAULT_HOOKS} ${CONFIG_SETUP_INITIALIZATION_FLAG} ${FACTORY_TYPE} | ||
|
||
# Use preset defined in default_sku | ||
if [ ! -e ${DEST_FILE} ]; then | ||
|
@@ -402,6 +441,9 @@ boot_config() | |
# read SONiC immutable variables | ||
[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment | ||
|
||
# read config-setup.conf | ||
[ -f $CONFIG_SETUP_CONF ] && . $CONFIG_SETUP_CONF | ||
|
||
### Execution starts here ### | ||
PLATFORM=${PLATFORM:-`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`} | ||
# Parse the device specific asic conf file, if it exists | ||
|
@@ -426,7 +468,13 @@ fi | |
|
||
# Process factory default configuration creation request | ||
if [ "$CMD" = "factory" ]; then | ||
generate_config factory ${CONFIG_DB_JSON} | ||
FACTORY_TYPE=$2 | ||
if [ "$FACTORY_TYPE" = "help" ] || [ "$FACTORY_TYPE" = "-h" ] || \ | ||
[ "$FACTORY_TYPE" = "--help" ]; then | ||
usage_factory | ||
exit 1 | ||
fi | ||
generate_config factory ${CONFIG_DB_JSON} ${FACTORY_TYPE} | ||
fi | ||
|
||
# Take a backup of current configuration | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# conf file for config-setup | ||
# file: /etc/config-setup/config-setup.conf | ||
# | ||
KEEP_BASIC_TABLES='["MGMT_PORT","MGMT_INTERFACE","MGMT_VRF_CONFIG","PASSW_HARDENING"]' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
#!/bin/bash | ||
########################################################################### | ||
# SONIC Factory reset script # | ||
# /usr/bin/reset-factory # | ||
# This script is used to reset the system to factory settings. # | ||
# It creates factory default configuration and save it to config_db.json. # | ||
# Also, it clear logs, tech-support, reboot-cause files, warmboot files, # | ||
# docker containers non-default users, users history files and # | ||
# home directories. # | ||
########################################################################### | ||
|
||
# Initialize constants | ||
CONFIG_DB_JSON=/etc/sonic/config_db.json | ||
DEFAULT_USERS_FILE=/etc/sonic/default_users.json | ||
PERMLOG=/var/log/systemlog | ||
SONIC_VERSION=$(sonic-cfggen -y /etc/sonic/sonic_version.yml -v build_version) | ||
SONIC_OVERLAY_UPPERDIR="/host/image-$SONIC_VERSION/rw/etc/sonic" | ||
|
||
SERVICES_STOPPED=0 | ||
trap "error_cleanup" HUP INT QUIT PIPE TERM | ||
|
||
# Command usage and help | ||
usage() | ||
{ | ||
cat << EOF | ||
Usage: reset-factory < keep-all-config | only-config | keep-basic > | ||
|
||
Create factory default configuration and save it to | ||
to ${CONFIG_DB_JSON}. | ||
Clears logs, system files and reboot the system. | ||
|
||
Default - Reset configurations to factory default. Logs and files will be deleted. | ||
keep-all-config - Preserves all configurations after boot. Logs and files will be deleted. | ||
only-config - Reset configurations to factory default. Logs and files will be preserved. | ||
keep-basic - Preserves basic configurations only after boot. Logs and files will be deleted. | ||
EOF | ||
} | ||
|
||
run_reboot() | ||
{ | ||
reboot | ||
# If for any reason we reach this code, then force reboot | ||
rc=$? | ||
if [ $rc -ne 0 ]; then | ||
# Force reboot | ||
reboot -f | ||
fi | ||
} | ||
|
||
error_cleanup() | ||
{ | ||
if [ ! -z "${TEMP_CFG}" ]; then | ||
# Recover config_db.json file | ||
mv ${TEMP_CFG} ${CONFIG_DB_JSON} | ||
fi | ||
|
||
if [ $SERVICES_STOPPED -eq 0 ]; then | ||
ERRMSG="reset-factory: halted with error before stopping critical services; exiting" | ||
logger $ERRMSG | ||
echo $ERRMSG | ||
exit 1 | ||
else | ||
ERRMSG="reset-factory: halted with error after stopping critical services; rebooting" | ||
logger $ERRMSG | ||
echo $ERRMSG | ||
run_reboot | ||
fi | ||
} | ||
|
||
# Restore original /etc/sonic folder by clearing the folder in overlayfs upperdir | ||
clear_sonic_dir() | ||
{ | ||
EXCLUDE_LIST="${CONFIG_DB_JSON}\|/etc/sonic/sonic-environment" | ||
find $SONIC_OVERLAY_UPPERDIR -type f | grep -ve ${EXCLUDE_LIST} | xargs rm -rf | ||
# remount root | ||
mount -o remount / | ||
} | ||
|
||
# Get list of defaults users names and passwords from DEFAULT_USERS_FILE | ||
# Delete non-default users and restore default password of default users | ||
reset_users() | ||
{ | ||
if [ ! -f "${DEFAULT_USERS_FILE}" ]; then | ||
echo "Error: Failed to get default users information" | ||
return | ||
fi | ||
# Get default user accounts | ||
default_users=$(jq -r '. | keys[]' $DEFAULT_USERS_FILE) | ||
EXCLUDE_LIST=$(echo $default_users | tr ' ' '|') | ||
# Get non-default user accounts | ||
other_users=$(getent passwd | awk -F: '($3>=1000 && $3<=60000) {print $1}' | grep -E -v $EXCLUDE_LIST) | ||
echo "Remove non-default users" | ||
for user in ${other_users[@]} | ||
do | ||
# avoid printing home directory and mail spool errors | ||
userdel -rf $user 2> /dev/null | ||
done | ||
echo "Restore default users passwords" | ||
for user in ${default_users[@]} | ||
do | ||
# Restore default password | ||
user_pass=$(jq -r '.[$user].password' --arg user "${user}" $DEFAULT_USERS_FILE) | ||
echo "$user:$user_pass" | chpasswd -e | ||
# Check if we need to expire password | ||
expire=$(jq -r '.[$user].expire' --arg user "${user}" $DEFAULT_USERS_FILE) | ||
[ "${expire}" == "true" ] && passwd -e ${user} | ||
done | ||
} | ||
|
||
# Only root can run reset factory | ||
if [ $UID != 0 ]; then | ||
echo "You must be root to reset system to factory settings" | ||
exit 1 | ||
fi | ||
|
||
CMD=$1 | ||
FACTORY_TYPE= | ||
|
||
if [ "$CMD" = "keep-all-config" ] || [ "$CMD" = "only-config" ] || \ | ||
[ "$CMD" = "keep-basic" ] || [ -z "$CMD" ]; then | ||
FACTORY_TYPE=$CMD | ||
else | ||
usage | ||
exit 1 | ||
fi | ||
|
||
SERVICES_STOPPED=1 | ||
echo "Stop critical services" | ||
monit unmonitor container_checker | ||
systemctl stop sonic.target --job-mode replace-irreversibly | ||
|
||
rc=$? | ||
if [ $rc -ne 0 ]; then | ||
error_cleanup | ||
fi | ||
|
||
DATE=$(date "+%Y/%m/%d %H:%M:%S") | ||
HOSTNAME=$(hostname | sed 's/\./ /' | awk '{print $1}') | ||
printf "%s %s reset-factory: resetting system to factory defaults\n" "$DATE" "$HOSTNAME" >> $PERMLOG | ||
|
||
# Backup and delete config_db.json | ||
TEMP_CFG="/tmp/temp_config_db.$$" | ||
cp ${CONFIG_DB_JSON} ${TEMP_CFG} | ||
if [ "$FACTORY_TYPE" != "keep-basic" ] && [ "$FACTORY_TYPE" != "keep-all-config" ]; then | ||
rm -f ${CONFIG_DB_JSON} | ||
fi | ||
|
||
echo "Call config-setup factory" | ||
config-setup factory $FACTORY_TYPE | ||
rc=$? | ||
if [ $rc -ne 0 ]; then | ||
error_cleanup | ||
fi | ||
|
||
if [ "$FACTORY_TYPE" != "only-config" ]; then | ||
|
||
if [ "$FACTORY_TYPE" != "keep-basic" ]; then | ||
|
||
# Delete non-default users and restore default users passwords | ||
reset_users | ||
|
||
echo "Delete bash, python and vim history files" | ||
find /home /root -type f -name ".bash_history" -o -name ".python_history" -o -name ".viminfo" | xargs rm -rf | ||
|
||
echo "Delete any non-dotfiles in users home directories" | ||
find /home/ /root -type f ! -iname ".*" -delete | ||
fi | ||
|
||
echo "Remove all docker containers except the database" | ||
database_pattern=($(docker ps -a -q -f "name=database" | paste -sd '|' -)) | ||
docker rm -f $(docker ps -a -q | egrep -v ${database_pattern}) > /dev/null | ||
|
||
echo "Clear sonic directory" | ||
clear_sonic_dir | ||
|
||
echo "Clear warmboot folder" | ||
find /host/warmboot/ -type f -delete | ||
|
||
echo "Delete reboot-cause files and symlinks" | ||
find /host/reboot-cause/ -type l,f -delete | ||
|
||
echo "Delete tech-support files" | ||
rm -rf /var/dump/* | ||
|
||
echo "Delete logs files" | ||
find /var/log/ -type f ! -iname "wtmp" ! -iname "btmp" ! -iname "lastlog" ! -iname "systemlog" -delete | ||
|
||
# Clear wtmp, utmp and lastlog files | ||
rm -rf /var/log/btmp.* | ||
cat /dev/null > /var/log/btmp | ||
rm -rf /var/log/wtmp.* | ||
cat /dev/null > /var/log/wtmp | ||
rm -rf /var/log/lastlog.* | ||
cat /dev/null > /var/log/lastlog | ||
fi | ||
|
||
run_reboot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check my comment on HLD PR: sonic-net/SONiC#1231 (review) #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see my answer: sonic-net/SONiC#1231 (comment)