Skip to content

Commit 8a9d746

Browse files
committed
Added EEM Config Diff->Spark
1 parent 1b9ee9d commit 8a9d746

File tree

3 files changed

+164
-0
lines changed

3 files changed

+164
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# EEM: Config Diff to Cisco Spark
2+
3+
An EEM+Python policy that pushes config change diffs to Spark
4+
5+
![](spark_notice1.png)
6+
7+
## Setup
8+
9+
This script requires the following EEM environment variables to be defined:
10+
11+
* `spark_token` : Bearer token for your Spark user/bot
12+
* `spark_room` : Spark room name to which messages will be sent
13+
14+
```
15+
event manager environment spark_token Bearer 1234abd...
16+
event manager environment spark_room Network Operators
17+
```
18+
19+
20+
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
::cisco::eem::event_register_syslog pattern "CONFIG_I"
2+
#
3+
# Copyright (c) 2017 Joe Clarke <[email protected]>
4+
# All rights reserved.
5+
#
6+
# Redistribution and use in source and binary forms, with or without
7+
# modification, are permitted provided that the following conditions
8+
# are met:
9+
# 1. Redistributions of source code must retain the above copyright
10+
# notice, this list of conditions and the following disclaimer.
11+
# 2. Redistributions in binary form must reproduce the above copyright
12+
# notice, this list of conditions and the following disclaimer in the
13+
# documentation and/or other materials provided with the distribution.
14+
#
15+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21+
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25+
# SUCH DAMAGE.
26+
#
27+
# This script requires the following EEM environment variables to be defined:
28+
#
29+
# spark_token : Bearer token for your Spark user/bot
30+
# spark_room : Spark room name to which messages will be sent
31+
#
32+
# E.g.:
33+
#
34+
# event manager environment spark_token Bearer 1234abd...
35+
# event manager environment spark_room Network Operators
36+
#
37+
38+
import eem
39+
import sys
40+
import os
41+
import requests
42+
import re
43+
44+
CFG_BAK_PY = '/flash/running-config.bak'
45+
CFG_BAK_IOS = 'flash:/running-config.bak'
46+
SPARK_API = 'https://api.ciscospark.com/v1/'
47+
48+
# Get the CLI event variables for this specific event.
49+
arr_einfo = eem.event_reqinfo()
50+
# Get the environment variables
51+
arr_envinfo = eem.env_reqinfo()
52+
53+
if 'spark_token' not in arr_envinfo:
54+
eem.action_syslog(
55+
'Environment variable "spark_token" must be set', priority='3')
56+
sys.exit(1)
57+
if 'spark_room' not in arr_envinfo:
58+
eem.action_syslog(
59+
'Environment variable "spark_room" must be set', priority='3')
60+
sys.exit(1)
61+
62+
# Get a CLI handle
63+
cli = eem.cli_open()
64+
eem.cli_exec(cli, 'enable')
65+
66+
if not os.path.isfile(CFG_BAK_PY):
67+
try:
68+
eem.cli_write(cli, 'copy runn {}'.format(CFG_BAK_IOS))
69+
prom = eem.cli_read_pattern(cli, '(filename|#)')
70+
if re.search(r'filename', prom):
71+
eem.cli_exec(cli, '\r')
72+
except Exception as e:
73+
eem.action_syslog('Failed to backup configuration to {}: {}'.format(
74+
CFG_BAK_IOS, e), priority='3')
75+
sys.exit(1)
76+
# First time through, only save the current config
77+
eem.cli_close(cli)
78+
sys.exit(0)
79+
80+
res = None
81+
try:
82+
res = eem.cli_exec(
83+
cli, 'show archive config diff {} system:running-config'.format(CFG_BAK_IOS))
84+
os.remove(CFG_BAK_PY)
85+
eem.cli_write(cli, 'copy runn {}'.format(CFG_BAK_IOS))
86+
prom = eem.cli_read_pattern(cli, 'filename')
87+
if re.search(r'filename', prom):
88+
eem.cli_exec(cli, '\r')
89+
except Exception as e:
90+
eem.action_syslog(
91+
'Failed to get config differences: {}'.format(e), priority='3')
92+
sys.exit(1)
93+
94+
eem.cli_close(cli)
95+
96+
diff_lines = re.split(r'\r?\n', res)
97+
if re.search('No changes were found', res):
98+
# No differences found
99+
sys.exit(0)
100+
101+
msg = 'Configuration differences between the running config and last backup:\n'
102+
msg += '```{}```'.format('\n'.join(diff_lines[:-1]))
103+
104+
headers = {
105+
'authorization': arr_envinfo['spark_token'],
106+
'content-type': 'application/json'
107+
}
108+
109+
# Get the Spark room ID
110+
url = SPARK_API + 'rooms'
111+
112+
r = None
113+
try:
114+
r = requests.request('GET', url, headers=headers)
115+
r.raise_for_status()
116+
except Exception as e:
117+
eem.action_syslog(
118+
'Failed to get list of Spark rooms: {}'.format(e), priority='3')
119+
sys.exit(1)
120+
121+
room_id = None
122+
for room in r.json()['items']:
123+
if room['title'] == arr_envinfo['spark_room']:
124+
room_id = room['id']
125+
break
126+
127+
if room_id is None:
128+
eem.action_syslog('Failed to find room ID for {}'.format(
129+
arr_envinfo['spark_room']))
130+
sys.exit(1)
131+
132+
# Post the message to Spark
133+
url = SPARK_API + 'messages'
134+
135+
payload = {'roomId': room_id, 'markdown': msg}
136+
137+
try:
138+
r = requests.request(
139+
'POST', url, json=payload, headers=headers)
140+
r.raise_for_status()
141+
except Exception as e:
142+
eem.action_syslog(
143+
'Error posting message to Spark: {}'.format(e), priority='3')
144+
sys.exit(1)
82 KB
Loading

0 commit comments

Comments
 (0)