Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
language: python
python: "2.7"

# Run jobs in VMs - sudo is required by ansible tests.
sudo: required

# Install ansible
addons:
apt:
packages:
- gcc
- python-apt
- python-virtualenv
- realpath

# Create a build matrix for the different test jobs.
env:
matrix:
# Run python style checks.
- TOX_ENV=pep8
# Build documentation.
- TOX_ENV=docs
# Run python2.7 unit tests.
- TOX_ENV=py27

install:
# Install tox in a virtualenv to ensure we have an up to date version.
- pip install -U pip
- pip install tox

script:
# Run the tox environment.
- tox -e ${TOX_ENV}
11 changes: 11 additions & 0 deletions networking_generic_switch/devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
{'name': 'ngs_ssh_connect_timeout', 'default': 60},
{'name': 'ngs_ssh_connect_interval', 'default': 10},
{'name': 'ngs_max_connections', 'default': 1},
# If True, disable switch ports that are not in use.
{'name': 'ngs_disable_inactive_ports', 'default': False},
]


Expand Down Expand Up @@ -91,6 +93,15 @@ def _get_physical_networks(self):
return []
return physnets.split(',')

@staticmethod
def _str_to_bool(value):
truthy = ('true', 'yes', '1')
return str(value).lower() in truthy

def _disable_inactive_ports(self):
"""Return whether inactive ports should be disabled."""
return self._str_to_bool(self.ngs_config['ngs_disable_inactive_ports'])

@abc.abstractmethod
def add_network(self, segmentation_id, network_id):
pass
Expand Down
25 changes: 17 additions & 8 deletions networking_generic_switch/devices/netmiko_devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ class NetmikoSwitch(devices.GenericSwitchDevice):

DELETE_PORT = None

ENABLE_PORT = None

DISABLE_PORT = None

PLUG_TRUNK_PORT_TO_NETWORK = None

UNPLUG_TRUNK_PORT_FROM_NETWORK = None
Expand Down Expand Up @@ -179,16 +183,21 @@ def del_network(self, segmentation_id, network_id):
self.send_commands_to_device(cmds)

def plug_port_to_network(self, port, segmentation_id):
self.send_commands_to_device(
self._format_commands(self.PLUG_PORT_TO_NETWORK,
port=port,
segmentation_id=segmentation_id))
cmds = []
if self._disable_inactive_ports() and self.ENABLE_PORT:
cmds += self._format_commands(self.ENABLE_PORT, port=port)
cmds += self._format_commands(self.PLUG_PORT_TO_NETWORK,
port=port,
segmentation_id=segmentation_id)
self.send_commands_to_device(cmds)

def delete_port(self, port, segmentation_id):
self.send_commands_to_device(
self._format_commands(self.DELETE_PORT,
port=port,
segmentation_id=segmentation_id))
cmds = self._format_commands(self.DELETE_PORT,
port=port,
segmentation_id=segmentation_id)
if self._disable_inactive_ports() and self.DISABLE_PORT:
cmds += self._format_commands(self.DISABLE_PORT, port=port)
self.send_commands_to_device(cmds)

def send_config_set(self, net_connect, cmd_set):
"""Send a set of configuration lines to the device.
Expand Down
8 changes: 8 additions & 0 deletions networking_generic_switch/devices/netmiko_devices/juniper.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ class Juniper(netmiko_devices.NetmikoSwitch):
'vlan members',
)

ENABLE_PORT = (
'delete interface {port} disable',
)

DISABLE_PORT = (
'set interface {port} disable',
)

PLUG_TRUNK_PORT_TO_NETWORK = (
'set interface {port} unit 0 family ethernet-switching '
'vlan members {segmentation_id}',
Expand Down
24 changes: 24 additions & 0 deletions networking_generic_switch/tests/unit/netmiko/test_juniper.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,19 @@ def test_plug_port_to_network(self, mock_exec):
'set interface 3333 unit 0 family ethernet-switching '
'vlan members 33'])

@mock.patch('networking_generic_switch.devices.netmiko_devices.'
'NetmikoSwitch.send_commands_to_device')
def test_plug_port_to_network_disable_inactive(self, m_sctd):
switch = self._make_switch_device(
{'ngs_disable_inactive_ports': 'true'})
switch.plug_port_to_network(3333, 33)
m_sctd.assert_called_with(
['delete interface 3333 disable',
'delete interface 3333 unit 0 family ethernet-switching '
'vlan members',
'set interface 3333 unit 0 family ethernet-switching '
'vlan members 33'])

@mock.patch('networking_generic_switch.devices.netmiko_devices.'
'NetmikoSwitch.send_commands_to_device')
def test_delete_port(self, mock_exec):
Expand All @@ -88,6 +101,17 @@ def test_delete_port(self, mock_exec):
['delete interface 3333 unit 0 family ethernet-switching '
'vlan members'])

@mock.patch('networking_generic_switch.devices.netmiko_devices.'
'NetmikoSwitch.send_commands_to_device')
def test_delete_port_disable_inactive(self, m_sctd):
switch = self._make_switch_device(
{'ngs_disable_inactive_ports': 'true'})
switch.delete_port(3333, 33)
m_sctd.assert_called_with(
['delete interface 3333 unit 0 family ethernet-switching '
'vlan members',
'set interface 3333 disable'])

def test_send_config_set(self):
connect_mock = mock.MagicMock(netmiko.base_connection.BaseConnection)
connect_mock.send_config_set.return_value = 'fake output'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,27 @@ def test_plug_port_to_network(self, m_sctd):
self.switch.plug_port_to_network(2222, 22)
m_sctd.assert_called_with([])

@mock.patch('networking_generic_switch.devices.netmiko_devices.'
'NetmikoSwitch.send_commands_to_device')
def test_plug_port_to_network_disable_inactive(self, m_sctd):
switch = self._make_switch_device(
{'ngs_disable_inactive_ports': 'true'})
switch.plug_port_to_network(2222, 22)
m_sctd.assert_called_with([])

@mock.patch('networking_generic_switch.devices.netmiko_devices.'
'NetmikoSwitch.send_commands_to_device')
def test_delete_port(self, m_sctd):
self.switch.delete_port(2222, 22)
m_sctd.assert_called_with(None)
m_sctd.assert_called_with([])

@mock.patch('networking_generic_switch.devices.netmiko_devices.'
'NetmikoSwitch.send_commands_to_device')
def test_delete_port_disable_inactive(self, m_sctd):
switch = self._make_switch_device(
{'ngs_disable_inactive_ports': 'true'})
switch.delete_port(2222, 22)
m_sctd.assert_called_with([])

def test__format_commands(self):
self.switch._format_commands(
Expand Down
2 changes: 1 addition & 1 deletion tools/tox_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
set -ex

ZUUL_CLONER=/usr/zuul-env/bin/zuul-cloner
BRANCH_NAME=master
BRANCH_NAME=stable/pike

CONSTRAINTS_FILE=$1
shift
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ envlist = py35,py27,pep8
[testenv]
usedevelop = True
install_command =
{toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
{toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/pike} {opts} {packages}
setenv = VIRTUAL_ENV={envdir}
PYTHONDONTWRITEBYTECODE = 1
PYTHONWARNINGS=default::DeprecationWarning
Expand Down