-
Notifications
You must be signed in to change notification settings - Fork 17
/
config-sample.py
186 lines (154 loc) · 5.73 KB
/
config-sample.py
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
#!/usr/bin/env python3
import config
import ipcalc
import sqlite3
import sys
import os
import tempita
import yaml
from tempita import bunch
from collections import namedtuple
from passlib.hash import sha512_crypt
import hashlib
f = open(os.path.join(os.path.dirname(sys.argv[0]), 'switchconfig/config.yaml'), 'r')
yaml_conf = yaml.safe_load(f)
# Note: To add new variables, the generate function will need to
# be modified as well
radius = ""
username = ""
password = ""
enable = ""
snmp_ro = ""
snmp_salt = ""
# NOTE(bluecmd): 2950 doesn't support VLAN aware context, which means that
# WhereAmI and dhmon needs v2. No reason to have v3 in that case.
#snmp_user = ""
#snmp_auth = ""
#snmp_priv = ""
wifi_vlanid = yaml_conf['wifi']['vlan_id']
# Enable this if we cannot set special option82 tags
franken_net_switches = [ ]
# If you have franken net, you need snmpv3 credentials to dist
# NOTE: THERE IS NO NEED TO USE THIS IF is_franken_net == False
snmpv3_username = ''
snmpv3_auth = ''
snmpv3_priv = ''
models = {}
for model in yaml_conf['models']:
data = bunch(template=model['path'],eth=model['ports'])
if 'image' in model:
data.image = model['image']
models.update({model['name']: data})
wifi_switches = yaml_conf['wifi']['switches']
# Files to be served as they are to all devices
static_files = {}
for sf in yaml_conf['static_files']:
static_files.update(sf)
# ===============================================================
# Do not change below this if you do not know what you're doing!
# ===============================================================
# ipplan_host('myhost.event.dreamhack.se')
# returns Host object with name, ipv4, and ipv6 properties from ipplan
# database
Host = namedtuple('Host', 'name ipv4 ipv6')
def ipplan_host(hostname):
sql = '''SELECT h.name, h.ipv4_addr_txt as ipv4, h.ipv6_addr_txt as ipv6
FROM host as h
WHERE h.name = ?;'''
db = sqlite3.connect('/etc/ipplan.db')
db.row_factory = sqlite3.Row
cursor = db.cursor()
row = cursor.execute(sql, (hostname,)).fetchone()
if row is None:
raise Exception("No IPv4 address found for host %s not in ipplan" % hostname)
return Host(name=row['name'], ipv4=row['ipv4'], ipv6=row['ipv6'])
# ipplan_package('mypackage')
# returns array of Host objects containing hosts with the given package from
# ipplan database
def ipplan_package(package):
sql = '''SELECT h.name, h.ipv4_addr_txt as ipv4, h.ipv6_addr_txt as ipv6
FROM host as h
INNER JOIN package as p ON p.node_id = h.node_id
WHERE p.name = ?;'''
db = sqlite3.connect('/etc/ipplan.db')
db.row_factory = sqlite3.Row
cursor = db.cursor()
hosts = []
for row in cursor.execute(sql, (package,)):
hosts.append(Host(name=row['name'], ipv4=row['ipv4'], ipv6=row['ipv6']))
return sorted(set(hosts), key=lambda e: e.name)
def generate(switch, model_id):
model = config.models[model_id]
mgmt, vlanid = parse_metadata(switch)
if mgmt is None:
raise Exception("The switch " + switch + " was not found in ipplan")
if radius is None:
raise Exception("Radius key not set")
if username is None:
raise Exception("Username not set")
if password is None:
raise Exception("User-password not set")
if enable is None:
raise Exception("Enable password not set")
if snmp_ro is None:
raise Exception("SNMP ro not set")
if snmp_salt is None:
raise Exception("SNMP salt not set")
#
# Template function definition
#
cfg = tempita.Template(open(model.template).read())
cfg_subbed = cfg.substitute(
hostname=switch,
model=model,
mgmt_ip=mgmt['ip'],
mgmt_mask=mgmt['mask'],
mgmt_mask_cidr=mgmt['mask_cidr'],
mgmt_gw=mgmt['gw'],
mgmt_vlanid=mgmt['vlanid'],
vlanid=vlanid,
wifi_switches=config.wifi_switches,
wifi_vlanid=config.wifi_vlanid,
password=config.password,
password_sha512=sha512_crypt.hash(config.password),
enable=config.enable,
enable_sha512=sha512_crypt.hash(config.enable),
radius=config.radius,
snmp_ro=config.snmp_ro,
snmp_rw=hashlib.sha1((config.snmp_salt + mgmt['ip']).encode()).hexdigest(),
ipplan_host=lambda h: ipplan_host(h),
ipplan_pkg=lambda p: ipplan_package(p),
# snmp_user=config.snmp_user,
# snmp_auth=config.snmp_auth,
# snmp_priv=config.snmp_priv
)
# We make the Juniper config a script, to be able to add the crontab.
if "Juniper" in model_id:
jcfg = tempita.Template(open(os.path.join(os.path.dirname(sys.argv[0]), 'juniper.sh.template')).read())
cfg_subbed = jcfg.substitute(config=cfg_subbed)
return cfg_subbed
def parse_metadata(switch):
sql = '''SELECT n_mgmt.ipv4_txt, h.ipv4_addr_txt, n_mgmt.ipv4_gateway_txt,
n_mgmt.vlan, n.vlan FROM active_switch as s, network as n, host as h,
network as n_mgmt WHERE s.switch_name LIKE ? AND n.node_id = s.node_id
AND h.name = s.switch_name AND n_mgmt.node_id = h.network_id'''
db = sqlite3.connect('/etc/ipplan.db')
cursor = db.cursor()
row = cursor.execute(sql, ('%s%%' % switch.lower(),)).fetchone()
if row is None:
return None, None
network_str, mgmt_ip, gateway, mgmt_vlan, vlan = row
network = ipcalc.Network(network_str)
mgmt = {}
mgmt['ip'] = mgmt_ip
mgmt['mask'] = str(network.netmask())
mgmt['mask_cidr'] = str(network.subnet())
mgmt['gw'] = str(network.host_first())
mgmt['vlanid'] = mgmt_vlan
return mgmt, vlan
if __name__ == '__main__':
if len(sys.argv) == 3 and sys.argv[1] == 'dump-snmp-rw':
mgmt, _ = parse_metadata(sys.argv[2])
print(hashlib.sha1(config.snmp_salt + mgmt['ip']).hexdigest())
else:
print(generate("D23-A", "WS-C2950T-24"))