diff options
author | Zuul <zuul@review.openstack.org> | 2018-07-30 12:08:41 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2018-07-30 12:08:41 +0000 |
commit | c38b2d15c28e63ff8272dd64ba2f5667fc065fe5 (patch) | |
tree | 0b906daead021368dbcaafb1da85318a8fe7d47a | |
parent | bdf571d48f0c5dc7858a8db79710983d9db48e03 (diff) | |
parent | e3878ac7e1cac09e98690a5daa7f14979635abe2 (diff) |
Merge "Adds ngs_switchport_mode config option to Dell PowerConnect driver"
6 files changed, 107 insertions, 0 deletions
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst index 580e237..f8100c0 100644 --- a/doc/source/configuration.rst +++ b/doc/source/configuration.rst | |||
@@ -98,6 +98,12 @@ for the Dell PowerConnect device:: | |||
98 | password = password | 98 | password = password |
99 | secret = secret | 99 | secret = secret |
100 | 100 | ||
101 | # You can set ngs_switchport_mode according to switchmode you have set on | ||
102 | # the switch. The following options are supported: general, access. It | ||
103 | # will default to access mode if left unset. In general mode, the port | ||
104 | # be set to transmit untagged packets. | ||
105 | ngs_switchport_mode = access | ||
106 | |||
101 | Dell PowerConnect devices have been seen to have issues with multiple | 107 | Dell PowerConnect devices have been seen to have issues with multiple |
102 | concurrent configuration sessions. See :ref:`synchronization` for details on | 108 | concurrent configuration sessions. See :ref:`synchronization` for details on |
103 | how to limit the number of concurrent active connections to each device. | 109 | how to limit the number of concurrent active connections to each device. |
diff --git a/networking_generic_switch/devices/__init__.py b/networking_generic_switch/devices/__init__.py index 2dd1ab2..6ca744e 100644 --- a/networking_generic_switch/devices/__init__.py +++ b/networking_generic_switch/devices/__init__.py | |||
@@ -34,6 +34,7 @@ NGS_INTERNAL_OPTS = [ | |||
34 | {'name': 'ngs_ssh_connect_timeout', 'default': 60}, | 34 | {'name': 'ngs_ssh_connect_timeout', 'default': 60}, |
35 | {'name': 'ngs_ssh_connect_interval', 'default': 10}, | 35 | {'name': 'ngs_ssh_connect_interval', 'default': 10}, |
36 | {'name': 'ngs_max_connections', 'default': 1}, | 36 | {'name': 'ngs_max_connections', 'default': 1}, |
37 | {'name': 'ngs_switchport_mode', 'default': 'access'} | ||
37 | ] | 38 | ] |
38 | 39 | ||
39 | 40 | ||
diff --git a/networking_generic_switch/devices/netmiko_devices/dell.py b/networking_generic_switch/devices/netmiko_devices/dell.py index 7529ca1..8a9ce3f 100644 --- a/networking_generic_switch/devices/netmiko_devices/dell.py +++ b/networking_generic_switch/devices/netmiko_devices/dell.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # under the License. | 13 | # under the License. |
14 | 14 | ||
15 | from networking_generic_switch.devices import netmiko_devices | 15 | from networking_generic_switch.devices import netmiko_devices |
16 | from networking_generic_switch import exceptions as exc | ||
16 | 17 | ||
17 | 18 | ||
18 | class DellNos(netmiko_devices.NetmikoSwitch): | 19 | class DellNos(netmiko_devices.NetmikoSwitch): |
@@ -57,6 +58,26 @@ class DellNos(netmiko_devices.NetmikoSwitch): | |||
57 | class DellPowerConnect(netmiko_devices.NetmikoSwitch): | 58 | class DellPowerConnect(netmiko_devices.NetmikoSwitch): |
58 | """Netmiko device driver for Dell PowerConnect switches.""" | 59 | """Netmiko device driver for Dell PowerConnect switches.""" |
59 | 60 | ||
61 | def _switch_to_general_mode(self): | ||
62 | self.PLUG_PORT_TO_NETWORK = self.PLUG_PORT_TO_NETWORK_GENERAL | ||
63 | self.DELETE_PORT = self.DELETE_PORT_GENERAL | ||
64 | |||
65 | def __init__(self, device_cfg): | ||
66 | super(DellPowerConnect, self).__init__(device_cfg) | ||
67 | port_mode = self.ngs_config['ngs_switchport_mode'] | ||
68 | switchport_mode = { | ||
69 | 'general': self._switch_to_general_mode, | ||
70 | 'access': lambda: () | ||
71 | } | ||
72 | |||
73 | def on_invalid_switchmode(): | ||
74 | raise exc.GenericSwitchConfigException( | ||
75 | option="ngs_switchport_mode", | ||
76 | allowed_options=switchport_mode.keys() | ||
77 | ) | ||
78 | |||
79 | switchport_mode.get(port_mode.lower(), on_invalid_switchmode)() | ||
80 | |||
60 | ADD_NETWORK = ( | 81 | ADD_NETWORK = ( |
61 | 'vlan database', | 82 | 'vlan database', |
62 | 'vlan {segmentation_id}', | 83 | 'vlan {segmentation_id}', |
@@ -69,12 +90,26 @@ class DellPowerConnect(netmiko_devices.NetmikoSwitch): | |||
69 | 'exit', | 90 | 'exit', |
70 | ) | 91 | ) |
71 | 92 | ||
93 | PLUG_PORT_TO_NETWORK_GENERAL = ( | ||
94 | 'interface {port}', | ||
95 | 'switchport general allowed vlan add {segmentation_id} untagged', | ||
96 | 'switchport general pvid {segmentation_id}', | ||
97 | 'exit', | ||
98 | ) | ||
99 | |||
72 | PLUG_PORT_TO_NETWORK = ( | 100 | PLUG_PORT_TO_NETWORK = ( |
73 | 'interface {port}', | 101 | 'interface {port}', |
74 | 'switchport access vlan {segmentation_id}', | 102 | 'switchport access vlan {segmentation_id}', |
75 | 'exit', | 103 | 'exit', |
76 | ) | 104 | ) |
77 | 105 | ||
106 | DELETE_PORT_GENERAL = ( | ||
107 | 'interface {port}', | ||
108 | 'switchport general allowed vlan remove {segmentation_id}', | ||
109 | 'no switchport general pvid', | ||
110 | 'exit', | ||
111 | ) | ||
112 | |||
78 | DELETE_PORT = ( | 113 | DELETE_PORT = ( |
79 | 'interface {port}', | 114 | 'interface {port}', |
80 | 'switchport access vlan none', | 115 | 'switchport access vlan none', |
diff --git a/networking_generic_switch/exceptions.py b/networking_generic_switch/exceptions.py index 29fc074..b3649da 100644 --- a/networking_generic_switch/exceptions.py +++ b/networking_generic_switch/exceptions.py | |||
@@ -21,6 +21,10 @@ class GenericSwitchException(exceptions.NeutronException): | |||
21 | message = _("%(method)s failed.") | 21 | message = _("%(method)s failed.") |
22 | 22 | ||
23 | 23 | ||
24 | class GenericSwitchConfigException(exceptions.NeutronException): | ||
25 | message = _("%(option)s must be one of: %(allowed_options)s") | ||
26 | |||
27 | |||
24 | class GenericSwitchEntrypointLoadError(GenericSwitchException): | 28 | class GenericSwitchEntrypointLoadError(GenericSwitchException): |
25 | message = _("Failed to load entrypoint %(ep)s: %(err)s") | 29 | message = _("Failed to load entrypoint %(ep)s: %(err)s") |
26 | 30 | ||
diff --git a/networking_generic_switch/tests/unit/netmiko/test_dell.py b/networking_generic_switch/tests/unit/netmiko/test_dell.py index 0052b56..8ce9686 100644 --- a/networking_generic_switch/tests/unit/netmiko/test_dell.py +++ b/networking_generic_switch/tests/unit/netmiko/test_dell.py | |||
@@ -15,6 +15,7 @@ | |||
15 | import mock | 15 | import mock |
16 | 16 | ||
17 | from networking_generic_switch.devices.netmiko_devices import dell | 17 | from networking_generic_switch.devices.netmiko_devices import dell |
18 | from networking_generic_switch import exceptions as exc | ||
18 | from networking_generic_switch.tests.unit.netmiko import test_netmiko_base | 19 | from networking_generic_switch.tests.unit.netmiko import test_netmiko_base |
19 | 20 | ||
20 | 21 | ||
@@ -133,6 +134,18 @@ class TestNetmikoDellPowerConnect(test_netmiko_base.NetmikoSwitchTestBase): | |||
133 | m_exec.assert_called_with( | 134 | m_exec.assert_called_with( |
134 | ['vlan database', 'vlan 33', 'exit']) | 135 | ['vlan database', 'vlan 33', 'exit']) |
135 | 136 | ||
137 | def test_invalid_switchmode(self): | ||
138 | with self.assertRaises(exc.GenericSwitchConfigException): | ||
139 | self._make_switch_device({'ngs_switchport_mode': 'BAD_PORT_MODE'}) | ||
140 | |||
141 | def test_switchmode_general(self): | ||
142 | # should not raise an exception | ||
143 | self._make_switch_device({'ngs_switchport_mode': 'GENERAL'}) | ||
144 | |||
145 | def test_switchmode_access(self): | ||
146 | # should not raise an exception | ||
147 | self._make_switch_device({'ngs_switchport_mode': 'access'}) | ||
148 | |||
136 | @mock.patch('networking_generic_switch.devices.netmiko_devices.' | 149 | @mock.patch('networking_generic_switch.devices.netmiko_devices.' |
137 | 'NetmikoSwitch.send_commands_to_device') | 150 | 'NetmikoSwitch.send_commands_to_device') |
138 | def test_add_network_with_trunk_ports(self, mock_exec): | 151 | def test_add_network_with_trunk_ports(self, mock_exec): |
@@ -174,11 +187,33 @@ class TestNetmikoDellPowerConnect(test_netmiko_base.NetmikoSwitchTestBase): | |||
174 | 187 | ||
175 | @mock.patch('networking_generic_switch.devices.netmiko_devices.' | 188 | @mock.patch('networking_generic_switch.devices.netmiko_devices.' |
176 | 'NetmikoSwitch.send_commands_to_device') | 189 | 'NetmikoSwitch.send_commands_to_device') |
190 | def test_plug_port_to_network_general_mode(self, mock_exec): | ||
191 | switch = self._make_switch_device({'ngs_switchport_mode': 'GENERAL'}) | ||
192 | switch.plug_port_to_network(3333, 33) | ||
193 | mock_exec.assert_called_with( | ||
194 | ['interface 3333', | ||
195 | 'switchport general allowed vlan add 33 untagged', | ||
196 | 'switchport general pvid 33', | ||
197 | 'exit']) | ||
198 | |||
199 | @mock.patch('networking_generic_switch.devices.netmiko_devices.' | ||
200 | 'NetmikoSwitch.send_commands_to_device') | ||
177 | def test_delete_port(self, mock_exec): | 201 | def test_delete_port(self, mock_exec): |
178 | self.switch.delete_port(3333, 33) | 202 | self.switch.delete_port(3333, 33) |
179 | mock_exec.assert_called_with( | 203 | mock_exec.assert_called_with( |
180 | ['interface 3333', 'switchport access vlan none', 'exit']) | 204 | ['interface 3333', 'switchport access vlan none', 'exit']) |
181 | 205 | ||
206 | @mock.patch('networking_generic_switch.devices.netmiko_devices.' | ||
207 | 'NetmikoSwitch.send_commands_to_device') | ||
208 | def test_delete_port_general(self, mock_exec): | ||
209 | switch = self._make_switch_device({'ngs_switchport_mode': 'GENERAL'}) | ||
210 | switch.delete_port(3333, 33) | ||
211 | mock_exec.assert_called_with( | ||
212 | ['interface 3333', | ||
213 | 'switchport general allowed vlan remove 33', | ||
214 | 'no switchport general pvid', | ||
215 | 'exit']) | ||
216 | |||
182 | def test__format_commands(self): | 217 | def test__format_commands(self): |
183 | cmd_set = self.switch._format_commands( | 218 | cmd_set = self.switch._format_commands( |
184 | dell.DellPowerConnect.ADD_NETWORK, | 219 | dell.DellPowerConnect.ADD_NETWORK, |
@@ -221,3 +256,24 @@ class TestNetmikoDellPowerConnect(test_netmiko_base.NetmikoSwitchTestBase): | |||
221 | self.assertEqual(cmd_set, | 256 | self.assertEqual(cmd_set, |
222 | ['interface 3333', | 257 | ['interface 3333', |
223 | 'switchport general allowed vlan remove 33', 'exit']) | 258 | 'switchport general allowed vlan remove 33', 'exit']) |
259 | |||
260 | def test__format_commands_general_mode(self): | ||
261 | switch = self._make_switch_device({'ngs_switchport_mode': 'GENERAL'}) | ||
262 | cmd_set = switch._format_commands( | ||
263 | dell.DellPowerConnect.PLUG_PORT_TO_NETWORK_GENERAL, | ||
264 | port=3333, | ||
265 | segmentation_id=33) | ||
266 | self.assertEqual(cmd_set, | ||
267 | ['interface 3333', | ||
268 | 'switchport general allowed vlan add 33 untagged', | ||
269 | 'switchport general pvid 33', | ||
270 | 'exit']) | ||
271 | cmd_set = switch._format_commands( | ||
272 | dell.DellPowerConnect.DELETE_PORT_GENERAL, | ||
273 | port=3333, | ||
274 | segmentation_id=33) | ||
275 | self.assertEqual(cmd_set, | ||
276 | ['interface 3333', | ||
277 | 'switchport general allowed vlan remove 33', | ||
278 | 'no switchport general pvid', | ||
279 | 'exit']) | ||
diff --git a/releasenotes/notes/add-switchmode-option-to-dell-powerconnect-87718a84430444ef.yaml b/releasenotes/notes/add-switchmode-option-to-dell-powerconnect-87718a84430444ef.yaml new file mode 100644 index 0000000..745885d --- /dev/null +++ b/releasenotes/notes/add-switchmode-option-to-dell-powerconnect-87718a84430444ef.yaml | |||
@@ -0,0 +1,5 @@ | |||
1 | --- | ||
2 | features: | ||
3 | - | | ||
4 | Adds a new config option, ``ngs_switchport_mode`` to the Dell | ||
5 | PowerConnect driver. | ||