Merge "Move create_tap_dev into privsep."

This commit is contained in:
Zuul 2019-02-26 03:51:57 +00:00 committed by Gerrit Code Review
commit 33f367ec2f
6 changed files with 121 additions and 127 deletions

View File

@ -17,40 +17,15 @@
"""Utility methods for linux networking."""
from oslo_concurrency import processutils
from oslo_log import log as logging
from nova.pci import utils as pci_utils
import nova.privsep.linux_net
from nova import utils
LOG = logging.getLogger(__name__)
def create_tap_dev(dev, mac_address=None, multiqueue=False):
if not nova.privsep.linux_net.device_exists(dev):
try:
# First, try with 'ip'
cmd = ('ip', 'tuntap', 'add', dev, 'mode', 'tap')
if multiqueue:
cmd = cmd + ('multi_queue', )
utils.execute(*cmd, run_as_root=True, check_exit_code=[0, 2, 254])
except processutils.ProcessExecutionError:
if multiqueue:
LOG.warning(
'Failed to create a tap device with ip tuntap. '
'tunctl does not support creation of multi-queue '
'enabled devices, skipping fallback.')
raise
# Second option: tunctl
utils.execute('tunctl', '-b', '-t', dev, run_as_root=True)
if mac_address:
nova.privsep.linux_net.set_device_macaddr(dev, mac_address)
nova.privsep.linux_net.set_device_enabled(dev)
def set_vf_interface_vlan(pci_addr, mac_addr, vlan=0):
pf_ifname = pci_utils.get_ifname_by_pci_address(pci_addr,
pf_interface=True)

View File

@ -87,6 +87,10 @@ def _set_device_mtu_inner(dev, mtu):
@nova.privsep.sys_admin_pctxt.entrypoint
def set_device_enabled(dev):
_set_device_enabled_inner(dev)
def _set_device_enabled_inner(dev):
processutils.execute('ip', 'link', 'set', dev, 'up',
check_exit_code=[0, 2, 254])
@ -98,6 +102,10 @@ def set_device_disabled(dev):
@nova.privsep.sys_admin_pctxt.entrypoint
def set_device_macaddr(dev, mac_addr, port_state=None):
_set_device_macaddr_inner(dev, mac_addr, port_state=port_state)
def _set_device_macaddr_inner(dev, mac_addr, port_state=None):
if port_state:
processutils.execute('ip', 'link', 'set', dev, 'address', mac_addr,
port_state, check_exit_code=[0, 2, 254])
@ -125,3 +133,33 @@ def bind_ip(device, ip, scope_is_link=False):
processutils.execute('ip', 'addr', 'add', str(ip) + '/32',
'scope', 'link', 'dev', device,
check_exit_code=[0, 2, 254])
@nova.privsep.sys_admin_pctxt.entrypoint
def create_tap_dev(dev, mac_address=None, multiqueue=False):
_create_tap_dev_inner(dev, mac_address=mac_address,
multiqueue=multiqueue)
def _create_tap_dev_inner(dev, mac_address=None, multiqueue=False):
if not device_exists(dev):
try:
# First, try with 'ip'
cmd = ('ip', 'tuntap', 'add', dev, 'mode', 'tap')
if multiqueue:
cmd = cmd + ('multi_queue', )
processutils.execute(*cmd, check_exit_code=[0, 2, 254])
except processutils.ProcessExecutionError:
if multiqueue:
LOG.warning(
'Failed to create a tap device with ip tuntap. '
'tunctl does not support creation of multi-queue '
'enabled devices, skipping fallback.')
raise
# Second option: tunctl
processutils.execute('tunctl', '-b', '-t', dev)
if mac_address:
_set_device_macaddr_inner(dev, mac_address)
_set_device_enabled_inner(dev)

View File

@ -1,97 +0,0 @@
# Copyright 2011 NTT
# All Rights Reserved.
#
# 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 mock
from oslo_concurrency import processutils
from nova.network import linux_utils as net_utils
from nova import test
class NetUtilsTestCase(test.NoDBTestCase):
@mock.patch('nova.utils.execute')
@mock.patch('nova.privsep.linux_net.set_device_enabled')
def test_create_tap_dev(self, mock_enabled, mock_execute):
net_utils.create_tap_dev('tap42')
mock_execute.assert_has_calls([
mock.call('ip', 'tuntap', 'add', 'tap42', 'mode', 'tap',
run_as_root=True, check_exit_code=[0, 2, 254])
])
mock_enabled.assert_called_once_with('tap42')
@mock.patch('os.path.exists', return_value=True)
@mock.patch('nova.utils.execute')
def test_create_tap_skipped_when_exists(self, mock_execute, mock_exists):
net_utils.create_tap_dev('tap42')
mock_exists.assert_called_once_with('/sys/class/net/tap42')
mock_execute.assert_not_called()
@mock.patch('nova.utils.execute')
@mock.patch('nova.privsep.linux_net.set_device_enabled')
@mock.patch('nova.privsep.linux_net.set_device_macaddr')
def test_create_tap_dev_mac(self, mock_set_macaddr, mock_enabled,
mock_execute):
net_utils.create_tap_dev('tap42', '00:11:22:33:44:55')
mock_execute.assert_has_calls([
mock.call('ip', 'tuntap', 'add', 'tap42', 'mode', 'tap',
run_as_root=True, check_exit_code=[0, 2, 254])
])
mock_enabled.assert_called_once_with('tap42')
mock_set_macaddr.assert_has_calls([
mock.call('tap42', '00:11:22:33:44:55')])
@mock.patch('nova.utils.execute')
@mock.patch('nova.privsep.linux_net.set_device_enabled')
def test_create_tap_dev_fallback_to_tunctl(self, mock_enabled,
mock_execute):
# ip failed, fall back to tunctl
mock_execute.side_effect = [processutils.ProcessExecutionError, 0, 0]
net_utils.create_tap_dev('tap42')
mock_execute.assert_has_calls([
mock.call('ip', 'tuntap', 'add', 'tap42', 'mode', 'tap',
run_as_root=True, check_exit_code=[0, 2, 254]),
mock.call('tunctl', '-b', '-t', 'tap42',
run_as_root=True)
])
mock_enabled.assert_called_once_with('tap42')
@mock.patch('nova.utils.execute')
@mock.patch('nova.privsep.linux_net.set_device_enabled')
def test_create_tap_dev_multiqueue(self, mock_enabled, mock_execute):
net_utils.create_tap_dev('tap42', multiqueue=True)
mock_execute.assert_has_calls([
mock.call('ip', 'tuntap', 'add', 'tap42', 'mode', 'tap',
'multi_queue',
run_as_root=True, check_exit_code=[0, 2, 254])
])
mock_enabled.assert_called_once_with('tap42')
@mock.patch('nova.utils.execute')
def test_create_tap_dev_multiqueue_tunctl_raises(self, mock_execute):
# if creation of a tap by the means of ip command fails,
# create_tap_dev() will try to do that by the means of tunctl
mock_execute.side_effect = processutils.ProcessExecutionError
# but tunctl can't create multiqueue taps, so the failure is expected
self.assertRaises(processutils.ProcessExecutionError,
net_utils.create_tap_dev,
'tap42', multiqueue=True)

View File

@ -15,6 +15,8 @@
import mock
from oslo_concurrency import processutils
import nova.privsep.linux_net
from nova import test
@ -28,3 +30,76 @@ class LinuxNetTestCase(test.NoDBTestCase):
calls = []
nova.privsep.linux_net._set_device_mtu_inner('fake-dev', None)
mock_exec.assert_has_calls(calls)
@mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('nova.privsep.linux_net._set_device_enabled_inner')
def test_create_tap_dev(self, mock_enabled, mock_execute):
nova.privsep.linux_net._create_tap_dev_inner('tap42')
mock_execute.assert_has_calls([
mock.call('ip', 'tuntap', 'add', 'tap42', 'mode', 'tap',
check_exit_code=[0, 2, 254])
])
mock_enabled.assert_called_once_with('tap42')
@mock.patch('os.path.exists', return_value=True)
@mock.patch('oslo_concurrency.processutils.execute')
def test_create_tap_skipped_when_exists(self, mock_execute, mock_exists):
nova.privsep.linux_net._create_tap_dev_inner('tap42')
mock_exists.assert_called_once_with('/sys/class/net/tap42')
mock_execute.assert_not_called()
@mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('nova.privsep.linux_net._set_device_enabled_inner')
@mock.patch('nova.privsep.linux_net._set_device_macaddr_inner')
def test_create_tap_dev_mac(self, mock_set_macaddr, mock_enabled,
mock_execute):
nova.privsep.linux_net._create_tap_dev_inner(
'tap42', '00:11:22:33:44:55')
mock_execute.assert_has_calls([
mock.call('ip', 'tuntap', 'add', 'tap42', 'mode', 'tap',
check_exit_code=[0, 2, 254])
])
mock_enabled.assert_called_once_with('tap42')
mock_set_macaddr.assert_has_calls([
mock.call('tap42', '00:11:22:33:44:55')])
@mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('nova.privsep.linux_net._set_device_enabled_inner')
def test_create_tap_dev_fallback_to_tunctl(self, mock_enabled,
mock_execute):
# ip failed, fall back to tunctl
mock_execute.side_effect = [processutils.ProcessExecutionError, 0, 0]
nova.privsep.linux_net._create_tap_dev_inner('tap42')
mock_execute.assert_has_calls([
mock.call('ip', 'tuntap', 'add', 'tap42', 'mode', 'tap',
check_exit_code=[0, 2, 254]),
mock.call('tunctl', '-b', '-t', 'tap42')
])
mock_enabled.assert_called_once_with('tap42')
@mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('nova.privsep.linux_net._set_device_enabled_inner')
def test_create_tap_dev_multiqueue(self, mock_enabled, mock_execute):
nova.privsep.linux_net._create_tap_dev_inner(
'tap42', multiqueue=True)
mock_execute.assert_has_calls([
mock.call('ip', 'tuntap', 'add', 'tap42', 'mode', 'tap',
'multi_queue', check_exit_code=[0, 2, 254])
])
mock_enabled.assert_called_once_with('tap42')
@mock.patch('oslo_concurrency.processutils.execute')
def test_create_tap_dev_multiqueue_tunctl_raises(self, mock_execute):
# if creation of a tap by the means of ip command fails,
# create_tap_dev() will try to do that by the means of tunctl
mock_execute.side_effect = processutils.ProcessExecutionError
# but tunctl can't create multiqueue taps, so the failure is expected
self.assertRaises(processutils.ProcessExecutionError,
nova.privsep.linux_net._create_tap_dev_inner,
'tap42', multiqueue=True)

View File

@ -1026,7 +1026,8 @@ class LibvirtVifTestCase(test.NoDBTestCase):
@mock.patch('nova.privsep.linux_net.device_exists')
@mock.patch('nova.privsep.libvirt.plug_plumgrid_vif')
def test_plug_iovisor(self, mock_plug, device_exists):
@mock.patch('nova.privsep.linux_net.create_tap_dev')
def test_plug_iovisor(self, mock_create_tap_dev, mock_plug, device_exists):
device_exists.return_value = True
d = vif.LibvirtGenericVIFDriver()
d.plug(self.instance, self.vif_iovisor)
@ -1119,7 +1120,9 @@ class LibvirtVifTestCase(test.NoDBTestCase):
@mock.patch('nova.privsep.linux_net.device_exists', return_value=True)
@mock.patch('nova.privsep.linux_net.set_device_mtu')
def test_plug_tap(self, mock_set_mtu, mock_device_exists):
@mock.patch('nova.privsep.linux_net.create_tap_dev')
def test_plug_tap(self, mock_create_tap_dev, mock_set_mtu,
mock_device_exists):
d = vif.LibvirtGenericVIFDriver()
d.plug(self.instance, self.vif_tap)

View File

@ -648,7 +648,7 @@ class LibvirtGenericVIFDriver(object):
dev = self.get_vif_devname(vif)
port_id = vif['id']
try:
linux_net_utils.create_tap_dev(dev)
nova.privsep.linux_net.create_tap_dev(dev)
nova.privsep.libvirt.plug_midonet_vif(port_id, dev)
except processutils.ProcessExecutionError:
LOG.exception(_("Failed while plugging vif"), instance=instance)
@ -661,7 +661,7 @@ class LibvirtGenericVIFDriver(object):
"""
dev = self.get_vif_devname(vif)
iface_id = vif['id']
linux_net_utils.create_tap_dev(dev)
nova.privsep.linux_net.create_tap_dev(dev)
net_id = vif['network']['id']
tenant_id = instance.project_id
try:
@ -674,7 +674,7 @@ class LibvirtGenericVIFDriver(object):
"""Plug a VIF_TYPE_TAP virtual interface."""
dev = self.get_vif_devname(vif)
mac = vif['details'].get(network_model.VIF_DETAILS_TAP_MAC_ADDRESS)
linux_net_utils.create_tap_dev(dev, mac)
nova.privsep.linux_net.create_tap_dev(dev, mac)
network = vif.get('network')
mtu = network.get_meta('mtu') if network else None
nova.privsep.linux_net.set_device_mtu(dev, mtu)