Remove IPTools deprecated implementation
IPTools driver [1] was implemented to avoid a bug in pyroute2 library,
currently solved. This implementation was marked as "deprecated" two
releases ago.
[1] 570c05266f
Change-Id: I16b180a298e104f393b5f665409cdf4ba5bff203
Closes-Bug: #1794524
This commit is contained in:
parent
7bfb01bcb1
commit
512e64d794
@ -62,7 +62,7 @@ pyflakes==0.8.1
|
|||||||
Pygments==2.2.0
|
Pygments==2.2.0
|
||||||
pyinotify==0.9.6
|
pyinotify==0.9.6
|
||||||
pyparsing==2.2.0
|
pyparsing==2.2.0
|
||||||
pyroute2==0.4.21
|
pyroute2==0.5.2
|
||||||
python-dateutil==2.7.0
|
python-dateutil==2.7.0
|
||||||
python-mimeparse==1.6.0
|
python-mimeparse==1.6.0
|
||||||
python-subunit==1.0.0
|
python-subunit==1.0.0
|
||||||
|
@ -10,80 +10,19 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import abc
|
|
||||||
import os
|
import os
|
||||||
import six
|
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import importutils
|
|
||||||
|
|
||||||
|
from os_vif.internal.command.ip.linux import impl_pyroute2 as linux_ip_lib
|
||||||
from os_vif.internal.command.ip.windows import impl_netifaces as win_ip_lib
|
from os_vif.internal.command.ip.windows import impl_netifaces as win_ip_lib
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
impl_map = {
|
|
||||||
'pyroute2': 'os_vif.internal.command.ip.impl_pyroute2.PyRoute2',
|
|
||||||
'IPTools': 'os_vif.internal.command.ip.impl_shell.IPTools',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _get_impl():
|
def _get_impl():
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
return win_ip_lib
|
return win_ip_lib
|
||||||
else:
|
else:
|
||||||
# NOTE(sean-k-mooney): currently pyroute2 has a file handle leak. An
|
return linux_ip_lib
|
||||||
# iptools driver has been added as a workaround but No config options
|
|
||||||
# are # exposed to the user. The iptools driver is considered
|
|
||||||
# deprecated and # will be removed when a new release of pyroute2 is
|
|
||||||
# available.
|
|
||||||
driver = 'IPTools'
|
|
||||||
return importutils.import_object(impl_map[driver])
|
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
|
||||||
class IpCommand(object):
|
|
||||||
|
|
||||||
TYPE_VETH = 'veth'
|
|
||||||
TYPE_VLAN = 'vlan'
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def set(self, device, check_exit_code=None, state=None, mtu=None,
|
|
||||||
address=None, promisc=None):
|
|
||||||
"""Method to set a parameter in an interface.
|
|
||||||
|
|
||||||
:param device: A network device (string)
|
|
||||||
:param check_exit_code: List of integers of allowed execution exit
|
|
||||||
codes
|
|
||||||
:param state: String network device state
|
|
||||||
:param mtu: Integer MTU value
|
|
||||||
:param address: String MAC address
|
|
||||||
:param promisc: Boolean promiscuous mode
|
|
||||||
:return: status of the command execution
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def add(self, device, dev_type, check_exit_code=None, peer=None, link=None,
|
|
||||||
vlan_id=None):
|
|
||||||
"""Method to add an interface.
|
|
||||||
|
|
||||||
:param device: A network device (string)
|
|
||||||
:param dev_type: String network device type (TYPE_VETH, TYPE_VLAN)
|
|
||||||
:param check_exit_code: List of integers of allowed execution exit
|
|
||||||
codes
|
|
||||||
:param peer: String peer name, for veth interfaces
|
|
||||||
:param link: String root network interface name, 'device' will be a
|
|
||||||
VLAN tagged virtual interface
|
|
||||||
:param vlan_id: Integer VLAN ID for VLAN devices
|
|
||||||
:return: status of the command execution
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def delete(self, device, check_exit_code=None):
|
|
||||||
"""Method to delete an interface.
|
|
||||||
|
|
||||||
:param device: A network device (string)
|
|
||||||
:param dev_type: String network device type (TYPE_VETH, TYPE_VLAN)
|
|
||||||
:return: status of the command execution
|
|
||||||
"""
|
|
||||||
|
@ -1,138 +0,0 @@
|
|||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
from oslo_concurrency import processutils
|
|
||||||
from oslo_utils import excutils
|
|
||||||
|
|
||||||
from os_vif.internal.command.ip import api
|
|
||||||
|
|
||||||
|
|
||||||
def _execute_command(*args):
|
|
||||||
return processutils.execute(*args)
|
|
||||||
|
|
||||||
|
|
||||||
class ShellIpCommands(object):
|
|
||||||
|
|
||||||
def __init__(self, cmd=_execute_command):
|
|
||||||
self._execute_command = cmd
|
|
||||||
|
|
||||||
def add_device(self, device, dev_type, peer=None, link=None,
|
|
||||||
vlan_id=None):
|
|
||||||
ret = None
|
|
||||||
if 'vlan' == dev_type:
|
|
||||||
ret = self._execute_command('ip', 'link', 'add', 'link', link,
|
|
||||||
'name', device, 'type', dev_type,
|
|
||||||
'id', vlan_id)
|
|
||||||
elif 'veth' == dev_type:
|
|
||||||
ret = self._execute_command('ip', 'link', 'add', device, 'type',
|
|
||||||
dev_type, 'peer', 'name', peer)
|
|
||||||
elif 'dummy' == dev_type:
|
|
||||||
ret = self._execute_command('ip', 'link', 'add', device,
|
|
||||||
'type', dev_type)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def del_device(self, device):
|
|
||||||
ret = None
|
|
||||||
if self.exist_device(device):
|
|
||||||
ret = self._execute_command('ip', 'link', 'del', device)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def set(self, device, status=None, **kwargs):
|
|
||||||
args = ['ip', 'link', 'set', device]
|
|
||||||
if status is not None:
|
|
||||||
args.append(status)
|
|
||||||
temp = [x for x in kwargs.items()]
|
|
||||||
for x in temp:
|
|
||||||
args += x
|
|
||||||
self._execute_command(*args)
|
|
||||||
|
|
||||||
def set_status_up(self, device):
|
|
||||||
self.set(device, status='up')
|
|
||||||
|
|
||||||
def set_status_down(self, device):
|
|
||||||
self.set(device, status='down')
|
|
||||||
|
|
||||||
def set_device_mtu(self, device, mtu):
|
|
||||||
args = {'mtu': mtu}
|
|
||||||
self.set(device, args)
|
|
||||||
|
|
||||||
def show_device(self, device):
|
|
||||||
val, err = _execute_command('ip', 'link', 'show', device)
|
|
||||||
return val.splitlines()
|
|
||||||
|
|
||||||
def exist_device(self, device):
|
|
||||||
try:
|
|
||||||
self._execute_command('ip', 'link', 'show', device)
|
|
||||||
return True
|
|
||||||
except processutils.ProcessExecutionError as e:
|
|
||||||
with excutils.save_and_reraise_exception() as saved_exception:
|
|
||||||
if e.exit_code == 1:
|
|
||||||
saved_exception.reraise = False
|
|
||||||
return False
|
|
||||||
|
|
||||||
def show_state(self, device):
|
|
||||||
regex = re.compile(r".*state (?P<state>\w+)")
|
|
||||||
match = regex.match(self.show_device(device)[0])
|
|
||||||
if match is None:
|
|
||||||
return
|
|
||||||
return match.group('state')
|
|
||||||
|
|
||||||
def show_promisc(self, device):
|
|
||||||
regex = re.compile(r".*(PROMISC)")
|
|
||||||
match = regex.match(self.show_device(device)[0])
|
|
||||||
return True if match else False
|
|
||||||
|
|
||||||
def show_mac(self, device):
|
|
||||||
exp = r".*link/ether (?P<mac>([0-9A-Fa-f]{2}[:]){5}[0-9A-Fa-f]{2})"
|
|
||||||
regex = re.compile(exp)
|
|
||||||
match = regex.match(self.show_device(device)[1])
|
|
||||||
if match is None:
|
|
||||||
return
|
|
||||||
return match.group('mac')
|
|
||||||
|
|
||||||
def show_mtu(self, device):
|
|
||||||
regex = re.compile(r".*mtu (?P<mtu>\d+)")
|
|
||||||
match = regex.match(self.show_device(device)[0])
|
|
||||||
if match is None:
|
|
||||||
return
|
|
||||||
return int(match.group('mtu'))
|
|
||||||
|
|
||||||
|
|
||||||
class IPTools(api.IpCommand):
|
|
||||||
|
|
||||||
def __init__(self, cmd=_execute_command):
|
|
||||||
self.ip = ShellIpCommands(cmd=cmd)
|
|
||||||
|
|
||||||
def set(self, device, check_exit_code=None, state=None, mtu=None,
|
|
||||||
address=None, promisc=None):
|
|
||||||
args = {}
|
|
||||||
if mtu is not None:
|
|
||||||
args['mtu'] = mtu
|
|
||||||
if address is not None:
|
|
||||||
args['address'] = address
|
|
||||||
if promisc is not None:
|
|
||||||
args['promisc'] = 'on' if promisc else 'off'
|
|
||||||
|
|
||||||
if isinstance(check_exit_code, int):
|
|
||||||
check_exit_code = [check_exit_code]
|
|
||||||
return self.ip.set(device, status=state, **args)
|
|
||||||
|
|
||||||
def add(self, device, dev_type, check_exit_code=None, peer=None, link=None,
|
|
||||||
vlan_id=None):
|
|
||||||
|
|
||||||
return self.ip.add_device(device, dev_type, peer=peer,
|
|
||||||
link=link, vlan_id=vlan_id)
|
|
||||||
|
|
||||||
def delete(self, device, check_exit_code=None):
|
|
||||||
return self.ip.del_device(device)
|
|
61
os_vif/internal/command/ip/ip_command.py
Normal file
61
os_vif/internal/command/ip/ip_command.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import abc
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class IpCommand(object):
|
||||||
|
|
||||||
|
TYPE_VETH = 'veth'
|
||||||
|
TYPE_VLAN = 'vlan'
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def set(self, device, check_exit_code=None, state=None, mtu=None,
|
||||||
|
address=None, promisc=None):
|
||||||
|
"""Method to set a parameter in an interface.
|
||||||
|
|
||||||
|
:param device: A network device (string)
|
||||||
|
:param check_exit_code: List of integers of allowed execution exit
|
||||||
|
codes
|
||||||
|
:param state: String network device state
|
||||||
|
:param mtu: Integer MTU value
|
||||||
|
:param address: String MAC address
|
||||||
|
:param promisc: Boolean promiscuous mode
|
||||||
|
:return: status of the command execution
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def add(self, device, dev_type, check_exit_code=None, peer=None, link=None,
|
||||||
|
vlan_id=None):
|
||||||
|
"""Method to add an interface.
|
||||||
|
|
||||||
|
:param device: A network device (string)
|
||||||
|
:param dev_type: String network device type (TYPE_VETH, TYPE_VLAN)
|
||||||
|
:param check_exit_code: List of integers of allowed execution exit
|
||||||
|
codes
|
||||||
|
:param peer: String peer name, for veth interfaces
|
||||||
|
:param link: String root network interface name, 'device' will be a
|
||||||
|
VLAN tagged virtual interface
|
||||||
|
:param vlan_id: Integer VLAN ID for VLAN devices
|
||||||
|
:return: status of the command execution
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete(self, device, check_exit_code=None):
|
||||||
|
"""Method to delete an interface.
|
||||||
|
|
||||||
|
:param device: A network device (string)
|
||||||
|
:param dev_type: String network device type (TYPE_VETH, TYPE_VLAN)
|
||||||
|
:return: status of the command execution
|
||||||
|
"""
|
@ -17,13 +17,13 @@ from pyroute2.netlink import exceptions as ipexc
|
|||||||
from pyroute2.netlink.rtnl import ifinfmsg
|
from pyroute2.netlink.rtnl import ifinfmsg
|
||||||
|
|
||||||
from os_vif import exception
|
from os_vif import exception
|
||||||
from os_vif.internal.command.ip import api
|
from os_vif.internal.command.ip import ip_command
|
||||||
from os_vif import utils
|
from os_vif import utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PyRoute2(api.IpCommand):
|
class PyRoute2(ip_command.IpCommand):
|
||||||
|
|
||||||
def _ip_link(self, ip, command, check_exit_code, **kwargs):
|
def _ip_link(self, ip, command, check_exit_code, **kwargs):
|
||||||
try:
|
try:
|
||||||
|
@ -1,180 +0,0 @@
|
|||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
from oslo_concurrency import processutils
|
|
||||||
from oslo_utils import excutils
|
|
||||||
|
|
||||||
from os_vif.internal.command.ip import impl_shell
|
|
||||||
from os_vif.tests.functional import base
|
|
||||||
from os_vif.tests.functional import privsep
|
|
||||||
|
|
||||||
|
|
||||||
@privsep.os_vif_pctxt.entrypoint
|
|
||||||
def _execute_command(*args):
|
|
||||||
return processutils.execute(*args)
|
|
||||||
|
|
||||||
|
|
||||||
class ShellIpCommands(object):
|
|
||||||
|
|
||||||
def add_device(self, device, dev_type, peer=None, link=None,
|
|
||||||
vlan_id=None):
|
|
||||||
if 'vlan' == dev_type:
|
|
||||||
_execute_command('ip', 'link', 'add', 'link', link,
|
|
||||||
'name', device, 'type', dev_type, 'vlan', 'id',
|
|
||||||
vlan_id)
|
|
||||||
elif 'veth' == dev_type:
|
|
||||||
_execute_command('ip', 'link', 'add', device, 'type', dev_type,
|
|
||||||
'peer', 'name', peer)
|
|
||||||
elif 'dummy' == dev_type:
|
|
||||||
_execute_command('ip', 'link', 'add', device, 'type', dev_type)
|
|
||||||
|
|
||||||
def del_device(self, device):
|
|
||||||
if self.exist_device(device):
|
|
||||||
_execute_command('ip', 'link', 'del', device)
|
|
||||||
|
|
||||||
def set_status_up(self, device):
|
|
||||||
_execute_command('ip', 'link', 'set', device, 'up')
|
|
||||||
|
|
||||||
def set_status_down(self, device):
|
|
||||||
_execute_command('ip', 'link', 'set', device, 'down')
|
|
||||||
|
|
||||||
def set_device_mtu(self, device, mtu):
|
|
||||||
_execute_command('ip', 'link', 'set', device, 'mtu', mtu)
|
|
||||||
|
|
||||||
def show_device(self, device):
|
|
||||||
val, err = _execute_command('ip', 'link', 'show', device)
|
|
||||||
return val.splitlines()
|
|
||||||
|
|
||||||
def exist_device(self, device):
|
|
||||||
try:
|
|
||||||
_execute_command('ip', 'link', 'show', device)
|
|
||||||
return True
|
|
||||||
except processutils.ProcessExecutionError as e:
|
|
||||||
with excutils.save_and_reraise_exception() as saved_exception:
|
|
||||||
if e.exit_code == 1:
|
|
||||||
saved_exception.reraise = False
|
|
||||||
return False
|
|
||||||
|
|
||||||
def show_state(self, device):
|
|
||||||
regex = re.compile(r".*state (?P<state>\w+)")
|
|
||||||
match = regex.match(self.show_device(device)[0])
|
|
||||||
if match is None:
|
|
||||||
return
|
|
||||||
return match.group('state')
|
|
||||||
|
|
||||||
def show_promisc(self, device):
|
|
||||||
regex = re.compile(r".*(PROMISC)")
|
|
||||||
match = regex.match(self.show_device(device)[0])
|
|
||||||
return True if match else False
|
|
||||||
|
|
||||||
def show_mac(self, device):
|
|
||||||
exp = r".*link/ether (?P<mac>([0-9A-Fa-f]{2}[:]){5}[0-9A-Fa-f]{2})"
|
|
||||||
regex = re.compile(exp)
|
|
||||||
match = regex.match(self.show_device(device)[1])
|
|
||||||
if match is None:
|
|
||||||
return
|
|
||||||
return match.group('mac')
|
|
||||||
|
|
||||||
def show_mtu(self, device):
|
|
||||||
regex = re.compile(r".*mtu (?P<mtu>\d+)")
|
|
||||||
match = regex.match(self.show_device(device)[0])
|
|
||||||
if match is None:
|
|
||||||
return
|
|
||||||
return int(match.group('mtu'))
|
|
||||||
|
|
||||||
|
|
||||||
def _ip_cmd_set(*args, **kwargs):
|
|
||||||
impl_shell.IPTools(cmd=_execute_command).set(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def _ip_cmd_add(*args, **kwargs):
|
|
||||||
impl_shell.IPTools(cmd=_execute_command).add(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def _ip_cmd_delete(*args, **kwargs):
|
|
||||||
impl_shell.IPTools(cmd=_execute_command).delete(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class TestIpCommand(ShellIpCommands, base.BaseFunctionalTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(TestIpCommand, self).setUp()
|
|
||||||
|
|
||||||
def test_set_state(self):
|
|
||||||
device1 = "iptools_dev_1"
|
|
||||||
device2 = "iptools_dev_2"
|
|
||||||
self.addCleanup(self.del_device, device1)
|
|
||||||
self.add_device(device1, 'veth', peer=device2)
|
|
||||||
_ip_cmd_set(device1, state='up')
|
|
||||||
_ip_cmd_set(device2, state='up')
|
|
||||||
self.assertEqual('UP', self.show_state(device1))
|
|
||||||
self.assertEqual('UP', self.show_state(device2))
|
|
||||||
_ip_cmd_set(device1, state='down')
|
|
||||||
_ip_cmd_set(device2, state='down')
|
|
||||||
self.assertEqual('DOWN', self.show_state(device1))
|
|
||||||
self.assertEqual('DOWN', self.show_state(device2))
|
|
||||||
|
|
||||||
def test_set_mtu(self):
|
|
||||||
device = "iptools_dev_3"
|
|
||||||
self.addCleanup(self.del_device, device)
|
|
||||||
self.add_device(device, 'dummy')
|
|
||||||
_ip_cmd_set(device, mtu=1200)
|
|
||||||
self.assertEqual(1200, self.show_mtu(device))
|
|
||||||
_ip_cmd_set(device, mtu=900)
|
|
||||||
self.assertEqual(900, self.show_mtu(device))
|
|
||||||
|
|
||||||
def test_set_address(self):
|
|
||||||
device = "iptools_dev_4"
|
|
||||||
address1 = "36:a7:e4:f9:01:01"
|
|
||||||
address2 = "36:a7:e4:f9:01:01"
|
|
||||||
self.addCleanup(self.del_device, device)
|
|
||||||
self.add_device(device, 'dummy')
|
|
||||||
_ip_cmd_set(device, address=address1)
|
|
||||||
self.assertEqual(address1, self.show_mac(device))
|
|
||||||
_ip_cmd_set(device, address=address2)
|
|
||||||
self.assertEqual(address2, self.show_mac(device))
|
|
||||||
|
|
||||||
def test_set_promisc(self):
|
|
||||||
device = "iptools_dev_5"
|
|
||||||
self.addCleanup(self.del_device, device)
|
|
||||||
self.add_device(device, 'dummy')
|
|
||||||
_ip_cmd_set(device, promisc=True)
|
|
||||||
self.assertTrue(self.show_promisc(device))
|
|
||||||
_ip_cmd_set(device, promisc=False)
|
|
||||||
self.assertFalse(self.show_promisc(device))
|
|
||||||
|
|
||||||
def test_add_vlan(self):
|
|
||||||
device = "iptools_dev_6"
|
|
||||||
link = "iptools_devlink"
|
|
||||||
self.addCleanup(self.del_device, device)
|
|
||||||
self.addCleanup(self.del_device, link)
|
|
||||||
self.add_device(link, 'dummy')
|
|
||||||
_ip_cmd_add(device, 'vlan', link=link, vlan_id=100)
|
|
||||||
self.assertTrue(self.exist_device(device))
|
|
||||||
|
|
||||||
def test_add_veth(self):
|
|
||||||
device = "iptools_dev_7"
|
|
||||||
peer = "iptools_devpeer"
|
|
||||||
self.addCleanup(self.del_device, device)
|
|
||||||
_ip_cmd_add(device, 'veth', peer=peer)
|
|
||||||
self.assertTrue(self.exist_device(device))
|
|
||||||
self.assertTrue(self.exist_device(peer))
|
|
||||||
|
|
||||||
def test_delete(self):
|
|
||||||
device = "iptools_dev_8"
|
|
||||||
self.addCleanup(self.del_device, device)
|
|
||||||
self.add_device(device, 'dummy')
|
|
||||||
self.assertTrue(self.exist_device(device))
|
|
||||||
_ip_cmd_delete(device)
|
|
||||||
self.assertFalse(self.exist_device(device))
|
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
Removed IPTools implementation. IPTools driver was implemented to avoid a
|
||||||
|
bug in pyroute2 library, currently solved. This implementation was marked
|
||||||
|
as "deprecated" two releases ago. IP Linux commands now use `Pyroute2`_.
|
||||||
|
|
||||||
|
.. _Pyroute2: https://docs.pyroute2.org/
|
@ -11,6 +11,6 @@ oslo.i18n>=3.15.3 # Apache-2.0
|
|||||||
oslo.privsep>=1.23.0 # Apache-2.0
|
oslo.privsep>=1.23.0 # Apache-2.0
|
||||||
oslo.versionedobjects>=1.28.0 # Apache-2.0
|
oslo.versionedobjects>=1.28.0 # Apache-2.0
|
||||||
ovsdbapp>=0.12.1 # Apache-2.0
|
ovsdbapp>=0.12.1 # Apache-2.0
|
||||||
pyroute2>=0.4.21;sys_platform!='win32' # Apache-2.0 (+ dual licensed GPL2)
|
pyroute2>=0.5.2;sys_platform!='win32' # Apache-2.0 (+ dual licensed GPL2)
|
||||||
six>=1.10.0 # MIT
|
six>=1.10.0 # MIT
|
||||||
stevedore>=1.20.0 # Apache-2.0
|
stevedore>=1.20.0 # Apache-2.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user