-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcisco.py
163 lines (140 loc) · 4.95 KB
/
cisco.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
import abc
import device
# Password recovery on Cisco devices shuts down all interfaces,
# so we have to bring them up explicitly and then reload for
# auto install to do its thing. By having this default config shown
# below we work around a lot of weird issues with autoinstall and
# force it to trigger explicitly.
IOS_DEFAULT_CONFIG = """
en
conf t
snmp-server community public RO
snmp-server community private RW
snmp-server system-shutdown
boot host dhcp
interface vlan 1
no ip address
no shut
end
"""
class CiscoSwitch(device.DeviceModel):
def boot(self):
"""Boot device."""
self._write(b'boot\n')
def set_switch_number(self, num):
"""Configure switch stack identity."""
# Set stack member 1 to prio 14, stack member 2 prio 13 and so on
prio = 15 - num
self._write(b'set SWITCH_NUMBER ' + str(num).encode() + b'\n')
self._read_line(['switch: '])
self._write(b'set SWITCH_PRIORITY ' + str(prio).encode() + b'\n')
self._read_line(['switch: '])
def wait_for_boot_complete(self):
"""Wait for system bootup complete."""
while True:
cisco_config_prompt = (
'Would you like to enter the initial configuration dialog\? \[yes/no\]: ')
cisco_booted = '.*Press RETURN to get started.*'
line = self._read_line([cisco_config_prompt, cisco_booted, '.*Switch>'])
if line == cisco_config_prompt:
self._write(b'no\n')
continue
# Even though Cisco says that you can press enter to get started,
# it might take a while to wake up
old_timeout = self.port.timeout
self.port.timeout = 10
for i in range(10):
try:
self._write(b'\r')
self._read_line(['.*Switch>'])
break
except device.DeviceTimeoutError:
print('Console not responsive yet, retrying')
self.port.timeout = old_timeout
self._clear_buffer()
return
class Cisco3850(CiscoSwitch):
def __init__(self, port):
self.port = port
self._is_stack_primary = None
@staticmethod
def matches_model(model):
return model.startswith('WS-C3850-')
def is_potentially_stack(self):
"""If the device will potentially be part of a stack."""
return True
def is_stack_primary(self):
"""If the device is the primary switch in the stack."""
# If the mgmt if is up, we consider this device to be the primary.
if self._is_stack_primary == None:
self._is_stack_primary = self._probe_mgmt_if()
return self._is_stack_primary
def _probe_mgmt_if(self):
"""Detect management if port status."""
self._write(b'mgmt_init\n')
mgmt_up = 'switch: '
mgmt_down = '.*PHY link is down'
line = self._read_line([mgmt_up, mgmt_down])
if line != mgmt_up:
# Make sure to read the extra stuff before we return
self._read_line(['switch: '])
return (line == mgmt_up)
def clear_config(self):
"""Remove all persistent configuration from device."""
self._write(b'set SWITCH_IGNORE_STARTUP_CFG 1\n')
# Needed for reseting the above later, but also good to have in general
self._write(b'set ENABLE_BREAK 1\n')
self._read_line(['switch: '])
def configure(self):
"""Bring the device to a state where swboot can configure it."""
# Erase config on master device and reload both
if self.is_stack_primary():
self._clear_buffer()
self.poke()
self._write(IOS_DEFAULT_CONFIG.encode())
self._write(b'wr\n')
self._write(b'\n')
self._write(b'reload\n')
self._write(b'\n')
self.wait_for_bootloader()
self._write(b'set SWITCH_IGNORE_STARTUP_CFG 0\n')
self._read_line(['switch: '])
self._write(b'boot\n')
class Cisco2950(CiscoSwitch):
def __init__(self, port):
self.port = port
@staticmethod
def matches_model(model):
return model.startswith('WS-C2950')
def is_potentially_stack(self):
"""If the device will potentially be part of a stack."""
return False
def is_stack_primary(self):
"""If the device is the primary switch in the stack."""
# This is always a primary switch given that we have no stack
return True
def clear_config(self):
"""Remove all persistent configuration from device."""
self._write(b'flash_init\n')
self._read_line([
'...done initializing flash.',
'...The flash is already initialized.'])
self._read_line(['switch: '])
self._write(b'del flash:/config.text\ny\n')
self._read_line(['switch: '])
self._write(b'del flash:/vlan.dat\ny\n')
self._read_line(['switch: '])
self._write(b'del flash:/private-config.text\ny\n')
self._read_line(['switch: '])
self._write(b'del flash:/env_vars\ny\n')
self._read_line(['switch: '])
def configure(self):
"""Bring the device to a state where swboot can configure it."""
# Erase config on master device and reload both
self._clear_buffer()
self.poke()
self._write(IOS_DEFAULT_CONFIG.encode())
self._write(b'wr\n')
self._write(b'\n')
self._write(b'reload\n')
self._write(b'\n')