|
1
2
3
4
5
6
7
8
|
#!/bin/bash -e
#
# sync-router shell scripts to synchronize cisco configuration and DHCP static
# lease files with with GIT repository. Operations performed:
# - update header of modified DHCP static lease files, upload
# them using using scp and add them to the next commit
# - restart Cisco DHCP service after updating static lease files
# - copy Cisco startup-config using scp and add to next commit
|
|
9
10
|
# - update IOS image files on the router when checked in to the
# repository, update startup-config file accordingly on router
|
|
11
12
|
# - commit changes to the git repository
#
|
|
13
|
# Version 1.2, latest version at: https://gitlab.lindenaar.net/scripts/cisco
|
|
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#
# Copyright (c) 2016 Frederik Lindenaar
#
# This script is free software: you can redistribute and/or modify it under the
# terms of version 3 of the GNU General Public License as published by the Free
# Software Foundation, or (at your option) any later version of the license.
#
# This script is distributed in the hope that it will be useful but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, visit <http://www.gnu.org/licenses/> to download it.
### Configuration ###
|
|
29
30
|
router=`basename \`dirname $0 | pwd\`` # name of router - based on directory
dhcpfiles=dhcp-\* # list/pattern of dhcp lease files
|
|
31
|
imagefiles=c\*-mz.\*.bin # list/pattern of IOS image files
|
|
32
|
filestore=flash # location of dhcp/IOS files on cisco
|
|
33
34
35
36
|
### Implementation ###
echo updating with $router
|
|
37
38
39
40
41
42
43
|
# Support function to print an error message and quit with an error exit code(1)
# parameters: $1 - message to be printed
fail() {
echo FATAL: ${1?ERROR: no error message provided for fail()}, aborted
exit 1
}
|
|
44
45
46
47
48
49
50
51
52
|
# Support function to download a file from the router
# parameters: $1 - filename to be copied and $2 - (optional) target filename
# when no target filename is provided the source file will be downloaded to the
# current directory with the same name. Adds downloaded file to git changeset
router_file_download() {
fromfile=${1?ERROR: at least one filename is required to copy from router}
tofile=${2:-$fromfile}
if [ "$fromfile" == startup-config ]; then
filesrc=nvram
|
|
53
54
|
else
filesrc=$filestore
|
|
55
56
|
fi
echo downloading $tofile from router $filesrc
|
|
57
58
59
60
61
|
if scp -q $router:$filesrc:$fromfile $tofile; then
git add $tofile
else
fail "download of $tofile failed"
fi
|
|
62
63
64
65
66
67
68
69
70
|
}
# Support function to upload a file to the router
# parameters: $1 - filename to be copied and $2 - (optional) target filename
# when a target filename is provided the source file will be moved to the target
# file after uploading and the target file is added to the git changeset
router_file_upload() {
fromfile=${1?ERROR: at least one filename is required to copy to router}
tofile=${2:-$fromfile}
|
|
71
|
if [ "$tofile" == startup-config ]; then
|
|
72
|
filedst=nvram
|
|
73
74
|
else
filedst=$filestore
|
|
75
76
|
fi
echo uploading new/updated $tofile to router $filedst
|
|
77
78
79
80
81
82
83
|
if scp -q $fromfile $router:$filedst:$tofile; then
if [ "$fromfile" != "$tofile" ]; then
mv $fromfile $tofile
git add $tofile
fi
else
fail "upload of $tofile failed"
|
|
84
85
86
87
88
89
90
91
|
fi
}
# Support function to remove a file from the router
# parameters: $1 - filename to be removed
router_file_remove() {
delfile=${1?ERROR: need a filename to remove from router}
echo removing $delfile as it is no longer in the repository
|
|
92
93
94
|
if ! ssh -q $router "delete /force $filestore:$delfile"; then
fail "removal of $delfile failed"
fi
|
|
95
96
97
98
99
100
|
}
# Fetch the start-up configuration from the router
router_file_download startup-config
|
|
101
|
# Process the DHCP static lease files that have changed
|
|
102
|
git status -s "$dhcpfiles" | while read status filename token newfilename
|
|
103
104
105
106
107
108
|
do
case $status in
\?\?)
echo skipping $filename as it is not yet added to the repository
;;
D)
|
|
109
110
111
112
113
|
router_file_remove $filename
;;
R)
router_file_remove $filename
router_file_upload $newfilename
|
|
114
|
;;
|
|
115
|
A |M|MM)
|
|
116
117
118
119
120
121
122
123
124
125
126
|
echo updating and uploading modified file $filename
head -2 $filename | while read tag value
do
case $tag in
\*time\*)
date +"$tag %h %d %Y %l:%M %p" > .$filename.$$.tmp
;;
\*version\*)
echo $tag $[ $value + 1 ] >> .$filename.$$.tmp
;;
*)
|
|
127
|
fail "found unknown entry \"$tag $value\" in $filename"
|
|
128
129
130
131
|
;;
esac
done
tail +3 $filename >> .$filename.$$.tmp
|
|
132
|
router_file_upload .$filename.$$.tmp $filename
|
|
133
134
|
;;
*)
|
|
135
|
fail "unsupported git status \"$status\" for $filename"
|
|
136
137
138
139
140
|
;;
esac
done
# Restart the DHCP service on the router if any of the dhcp files changed
|
|
141
|
if git status -s "$dhcpfiles" | egrep -q ^[MAD]; then
|
|
142
143
|
echo restarting DHCP service
cat << EOT | if ! ssh -q $router; then
|
|
144
145
146
147
148
149
|
configure terminal
no service dhcp
service dhcp
exit
exit
EOT
|
|
150
151
|
fail "unable to restart DHCP service"
fi
|
|
152
153
154
|
fi
|
|
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
# Process the IOS image files that have changed
git status -s "$imagefiles" | while read status filename token newfilename
do
case $status in
\?\?)
echo skipping $filename as it is not yet added to the repository
;;
R)
router_file_remove $filename
router_file_upload $newfilename
;;
D)
router_file_remove $filename
;;
A |M)
router_file_upload $filename
;;
*)
|
|
173
|
fail "unsupported git status \"$status\" for $filename"
|
|
174
175
176
177
178
179
|
;;
esac
done
# Update the boot images in the startup-config file if we're updating any images
if git status -s "$imagefiles" | egrep -q ^[MADR]; then
|
|
180
|
fgrep -n "boot system $filestore" startup-config | cut -d: -f1 > .startup-config.$$.lines
|
|
181
|
head -$[ `head -1 .startup-config.$$.lines` -1 ] startup-config > .startup-config.$$
|
|
182
|
git ls-files $imagefiles | sort -r | sed "s/^/boot system $filestore /g" >> .startup-config.$$
|
|
183
184
185
186
187
188
189
|
tail +$[ `tail -1 .startup-config.$$.lines` +1 ] startup-config >> .startup-config.$$
rm .startup-config.$$.lines
router_file_upload .startup-config.$$ startup-config
fi
# show what has changed in the startup config and commit to the repository
|
|
190
|
git diff --cached startup-config
|
|
191
|
git commit || git reset HEAD startup-config
|
|
192
|
|