-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
rc.local
executable file
·389 lines (327 loc) · 14.1 KB
/
rc.local
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
#!/bin/sh -x
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
SONIC_VERSION=$(cat /etc/sonic/sonic_version.yml | grep "build_version" | sed -e "s/build_version: //g;s/'//g")
FIRST_BOOT_FILE="/host/image-${SONIC_VERSION}/platform/firsttime"
# Move sonic-environment to /etc/sonic
SONIC_CONFIG_DIR="/host/image-${SONIC_VERSION}/sonic-config"
SONIC_ENV_FILE=${SONIC_CONFIG_DIR}/sonic-environment
if [ -d ${SONIC_CONFIG_DIR} -a -f ${SONIC_ENV_FILE} ]; then
echo "moving file ${SONIC_ENV_FILE} to /etc/sonic" 1>&2
mv ${SONIC_ENV_FILE} /etc/sonic
fi
# In case the unit is migrating from another NOS, save the logs
log_migration() {
echo $1 >> /host/migration/migration.log
}
# Import files from another NOS's partition onto SONiC
nos_migration_import() {
[ -f $1 ] && cp $1 $2 || log_migration "ERROR: $1 not found!"
}
# While migrating form another NOS, we need to preserve the MAC addresses
# of eth0 (and eventually switchports).
# Update the eth0 mac and also the EEPROM using ethtool so that subsequent
# reboots use the NOS's mac.
# Input : mgmt_interface.cfg file imported from the previous NOS.
update_mgmt_interface_macaddr() {
mgmt_config=$1
if [ ! -f "$mgmt_config" ]; then
log_migration "ERROR : unable update eth0 MAC : $mgmt_config not found!"
return
fi
# Save the previous NOS's mac
old_mac=`ip link show eth0 | grep ether | awk '{print $2}'`
[ -z "$old_mac" ] && log_migration "Unable to retrieve old mac address !" && return
# Extract, validate and set the eth0's mac address for the current session
new_mac=$(grep "macaddr" $mgmt_config | awk -F'=' '{print $2}')
log_migration "Setting eth0 mac as $new_mac."
if [ `echo $new_mac | egrep "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$"` ]; then
ip link set eth0 down
ip link set eth0 address $new_mac
ip link set eth0 up
else
log_migration "ERROR: mac imported from NOS is invalid : $new_mac !"
return
fi
# Get the ethtool magic and offset for changing the mac address in the EEPROM
ethtool_magic=$(grep "ethtool_magic" $mgmt_config | awk -F'=' '{print $2}')
ethtool_offset=$(grep "ethtool_offset" $mgmt_config | awk -F'=' '{print $2}')
if [ -z "$ethtool_magic" ] || [ -z "$ethtool_offset" ]; then
log_migration "Unable to retrieve ethtool params ($ethtool_magic,$ethtool_offset)"
return
fi
log_migration "eth0 mac in EEPROM before update:"
ethtool -e eth0 offset $ethtool_offset length 6 >> /host/migration/migration.log
# Update the mac address in the EEPROM for subsequent reboots
# Write only changed octets
for i in 1 2 3 4 5 6; do
offset=$(($ethtool_offset+$i-1))
old_mac_octet="$(echo $old_mac | cut -d":" -f$i)"
new_mac_octet="$(echo $new_mac | cut -d":" -f$i)"
if [ "$old_mac_octet" != "$new_mac_octet" ]; then
ethtool -E eth0 magic $ethtool_magic offset $offset value 0x$new_mac_octet
if [ $? != 0 ]; then
log_migration "ERROR: unable to update eth0 EEPROM!"
log_migration "index $i, magic $ethtool_magic offset $offset, value $new_mac_octet"
return
fi
fi
done
log_migration "eth0 mac in EEPROM after update:"
ethtool -e eth0 offset $ethtool_offset length 6 >> /host/migration/migration.log
}
migrate_nos_configuration()
{
rm -rf /host/migration
mkdir -p /host/migration
# Extract the previous NOS's partition that contains the migration artifacts
set -- $(cat /proc/cmdline)
for x in "$@"; do
case "$x" in
nos-config-part=*)
nos_dev="${x#nos-config-part=}"
;;
SONIC_BOOT_TYPE=fast*)
sonic_fast_reboot=true
;;
esac
done
if [ -n "$nos_dev" ]; then
# remove nos-config-part from cmdline
sed -r -i.bak "s/nos-config-part=[^[:space:]]+//" /host/grub/grub.cfg
# remove ssd-upgrader-part from cmdline
sed -r -i.bak "s/ssd-upgrader-part=[^[:space:]]+//" /host/grub/grub.cfg
# Mount the previous NOS's partition
NOS_DIR=/mnt/nos_migration
MG_GZFILE=$NOS_DIR/minigraph.xml.gz.base64.txt
MG_FILE=$NOS_DIR/minigraph.xml
ACL_GZFILE=$NOS_DIR/acl.json.gz.base64.txt
ACL_FILE=$NOS_DIR/acl.json
PORT_CONFIG_GZFILE=$NOS_DIR/port_config.json.gz.base64.txt
PORT_CONFIG_FILE=$NOS_DIR/port_config.json
SNMP_FILE=$NOS_DIR/snmp.yml
mkdir -p $NOS_DIR
mount $nos_dev $NOS_DIR
if [ $? != 0 ]; then
log_migration "ERROR: cannot mount $nos_dev"
else
# decode & unzip minigraph.xml.gz.base64.txt
[ -f $MG_GZFILE ] && /usr/bin/base64 -d $MG_GZFILE | /bin/gunzip > $MG_FILE
[ -f $ACL_GZFILE ] && /usr/bin/base64 -d $ACL_GZFILE | /bin/gunzip > $ACL_FILE
[ -f $PORT_CONFIG_GZFILE ] && /usr/bin/base64 -d $PORT_CONFIG_GZFILE | /bin/gunzip > $PORT_CONFIG_FILE
# Copy relevant files
nos_migration_import $NOS_DIR/mgmt_interface.cfg /host/migration
nos_migration_import $MG_FILE /host/migration
nos_migration_import $ACL_FILE /host/migration
nos_migration_import $PORT_CONFIG_FILE /host/migration
nos_migration_import $SNMP_FILE /host/migration
if [ "$sonic_fast_reboot" == true ]; then
mkdir -p /host/fast-reboot
nos_migration_import $NOS_DIR/arp.json /host/fast-reboot
nos_migration_import $NOS_DIR/fdb.json /host/fast-reboot
nos_migration_import $NOS_DIR/default_routes.json /host/fast-reboot
fi
umount $NOS_DIR
rmdir $NOS_DIR
fi
[ -f /host/migration/mgmt_interface.cfg ] && update_mgmt_interface_macaddr /host/migration/mgmt_interface.cfg
migration="TRUE"
fi
}
firsttime_exit() {
rm -rf $FIRST_BOOT_FILE
exit 0
}
# Given a string of tuples of the form field=value, extract the value for a field
# In : $string, $field
# Out: $value
value_extract() {
set -- $string
for x in "$@"; do
case "$x" in
$field=*)
value="${x#$field=}"
esac
done
}
program_console_speed()
{
speed=$(cat /proc/cmdline | grep -Eo 'console=ttyS[0-9]+,[0-9]+' | cut -d "," -f2)
if [ -z "$speed" ]; then
CONSOLE_SPEED=9600
else
CONSOLE_SPEED=$speed
fi
# Set correct baud rate in getty service
# First boot will find keep-baud argument with multiple baud rates as per Debian convention
# Subsequent boots may have new baud rate without finding keep-baud argument
grep agetty /lib/systemd/system/serial-getty@.service |grep keep-baud
if [ $? = 0 ]; then
sed -i "s|\-\-keep\-baud .* %I| $CONSOLE_SPEED %I|g" /lib/systemd/system/serial-getty@.service
else
sed -i "s|u' .* %I|u' $CONSOLE_SPEED %I|g" /lib/systemd/system/serial-getty@.service
fi
# Reload systemd config
systemctl daemon-reload
}
#### Begin Main Body ####
logger "SONiC version ${SONIC_VERSION} starting up..."
# If the machine.conf is absent, it indicates that the unit booted
# into SONiC from another NOS. Extract the machine.conf from ONIE.
grub_installation_needed=""
if [ ! -e /host/machine.conf ]; then
onie_dev=$(blkid | grep ONIE-BOOT | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//')
mkdir -p /mnt/onie-boot
mount $onie_dev /mnt/onie-boot
onie_grub_cfg=/mnt/onie-boot/onie/grub/grub-machine.cfg
if [ ! -e $onie_grub_cfg ]; then
log_migration "$onie_grub_cfg not found"
else
. ./$onie_grub_cfg
grep = $onie_grub_cfg | sed -e 's/onie_//' -e 's/=.*$//' | while read var ; do
eval val='$'onie_$var
echo "onie_${var}=${val}" >> /host/machine.conf
done
grub_installation_needed="TRUE"
fi
migrate_nos_configuration
umount /mnt/onie-boot
fi
. /host/machine.conf
program_console_speed
if [ -f $FIRST_BOOT_FILE ]; then
echo "First boot detected. Performing first boot tasks..."
if [ -n "$aboot_platform" ]; then
platform=$aboot_platform
elif [ -n "$onie_platform" ]; then
platform=$onie_platform
else
echo "Unknown SONiC platform"
firsttime_exit
fi
# Try to take old configuration saved during installation
# and create a flag in /tmp/ to let updategraph service know
if [ -d /host/old_config ]; then
mv -f /host/old_config /etc/sonic/
rm -rf /etc/sonic/old_config/old_config
touch /tmp/pending_config_migration
elif [ -f /host/minigraph.xml ]; then
mkdir -p /etc/sonic/old_config
mv /host/minigraph.xml /etc/sonic/old_config/
[ -f /host/acl.json ] && mv /host/acl.json /etc/sonic/old_config/
[ -f /host/port_config.json ] && mv /host/port_config.json /etc/sonic/old_config/
[ -f /host/snmp.yml ] && mv /host/snmp.yml /etc/sonic/old_config/
touch /tmp/pending_config_migration
elif [ -n "$migration" ] && [ -f /host/migration/minigraph.xml ]; then
mkdir -p /etc/sonic/old_config
mv /host/migration/minigraph.xml /etc/sonic/old_config/
[ -f /host/migration/acl.json ] && mv /host/migration/acl.json /etc/sonic/old_config/
[ -f /host/migration/port_config.json ] && mv /host/migration/port_config.json /etc/sonic/old_config/
[ -f /host/migration/snmp.yml ] && mv /host/migration/snmp.yml /etc/sonic/old_config/
touch /tmp/pending_config_migration
[ -f /etc/sonic/updategraph.conf ] && sed -i -e "s/enabled=false/enabled=true/g" /etc/sonic/updategraph.conf
else
touch /tmp/pending_config_initialization
fi
# Notify firstboot to Platform, to use it for reboot-cause
touch /tmp/notify_firstboot_to_platform
# Create /host/reboot-cause/platform/ directory
# can be used to track last reboot reason by some platforms
if [ ! -d /host/reboot-cause/platform ]; then
mkdir -p /host/reboot-cause/platform
fi
if [ -d /host/image-$SONIC_VERSION/platform/$platform ]; then
dpkg -i /host/image-$SONIC_VERSION/platform/$platform/*.deb
fi
sync
# If the unit booted into SONiC from another NOS's grub,
# we now install a grub for SONiC.
if [ -n "$onie_platform" ] && [ -n "$grub_installation_needed" ]; then
grub_bin=$(ls /host/image-$SONIC_VERSION/platform/grub/grub*.deb 2> /dev/null)
if [ -z "$grub_bin" ]; then
log_migration "Unable to locate grub package !"
firsttime_exit
fi
dpkg -i $grub_bin > /dev/null 2>&1
if [ $? != 0 ]; then
log_migration "Unable to install grub package !"
firsttime_exit
fi
# Determine the block device to install grub
sonic_dev=$(blkid | grep SONiC-OS | head -n 1 | awk '{print $1}' | sed -e 's/[0-9]:.*$//')
if [ -z "$sonic_dev" ]; then
log_migration "Unable to determine sonic partition !"
firsttime_exit
fi
grub-install --boot-directory=/host --recheck $sonic_dev 2>/dev/null
if [ $? != 0 ]; then
log_migration "grub install failed !"
firsttime_exit
fi
# The SONiC "raw" build mode has already generated a proto grub.cfg
# as part of the migration. Platform specific constants need to be
# retrieved from installer.conf (if present) and assigned.
. /usr/share/sonic/device/$platform/installer.conf
if [ ! -z "$CONSOLE_PORT" ]; then
field="\-\-port"
string=$(grep $field /host/grub.cfg)
value_extract $string $field
console_port=$value
if [ ! -z "$console_port" ] && [ "$console_port" != "$CONSOLE_PORT" ]; then
sed -i -e "s/\-\-port=$console_port/\-\-port=$CONSOLE_PORT/g" /host/grub.cfg
fi
log_migration "grub.cfg console port=$console_port & installer.conf CONSOLE_PORT=$CONSOLE_PORT"
fi
if [ ! -z "$CONSOLE_DEV" ]; then
field="console"
string=$(grep $field /host/grub.cfg)
value_extract $string $field
console_dev_name=$(echo $value | sed -e "s/^.*=//" -e "s/,.*//")
console_dev="${console_dev_name#ttyS}"
if [ "$console_dev" != "$CONSOLE_DEV" ]; then
sed -i -e "s/console=ttyS$console_dev/console=ttyS$CONSOLE_DEV/g" /host/grub.cfg
fi
log_migration "grub.cfg console dev=$console_dev & installer.conf CONSOLE_DEV=$CONSOLE_DEV"
fi
if [ ! -z "$VAR_LOG_SIZE" ]; then
field="var_log_size"
string=$(grep $field /host/grub.cfg)
value_extract $string $field
var_log_size=$value
if [ ! -z "$var_log_size" ] && [ "$var_log_size" != "$VAR_LOG_SIZE" ]; then
sed -i -e "s/var_log_size=$var_log_size/var_log_size=$VAR_LOG_SIZE/g" /host/grub.cfg
fi
log_migration "grub.cfg var_log_size=$var_log_size & installer.conf VAR_LOG_SIZE=$VAR_LOG_SIZE"
fi
# Set the root based on the label
sonic_root=$(blkid | grep SONiC-OS | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//')
sonic_root=$(echo "$sonic_root" | sed 's/\//\\\//g')
sed -i -e "s/%%SONIC_ROOT%%/$sonic_root/g" /host/grub.cfg
# Add the Diag and ONIE entries
mount $onie_dev /mnt/onie-boot
. /mnt/onie-boot/onie/grub.d/50_onie_grub >> /host/grub.cfg
umount /mnt/onie-boot
# Initialize the SONiC's grub config
mv /host/grub.cfg /host/grub/grub.cfg
fi
# Create dir where following scripts put their output files
mkdir -p /var/platform
# Kdump tools configuration
[ -f /etc/default/kdump-tools ] && sed -i -e "s/__PLATFORM__/$platform/g" /etc/default/kdump-tools
firsttime_exit
fi
# Copy the fsck log into syslog
if [ -f /var/log/fsck.log.gz ]; then
gunzip -d -c /var/log/fsck.log.gz | logger -t "FSCK"
rm -f /var/log/fsck.log.gz
fi
exit 0