Merge "Move some linux network helpers to use privsep."

This commit is contained in:
Zuul 2019-01-15 03:04:30 +00:00 committed by Gerrit Code Review
commit 89c2d1056b
11 changed files with 157 additions and 107 deletions

View File

@ -933,7 +933,7 @@ def get_dhcp_opts(context, network_ref, fixedips):
def release_dhcp(dev, address, mac_address):
if linux_net_utils.device_exists(dev):
if nova.privsep.linux_net.device_exists(dev):
try:
utils.execute('dhcp_release', dev, address, mac_address,
run_as_root=True)
@ -1233,22 +1233,22 @@ def _ovs_vsctl(args):
def create_fp_dev(dev, sockpath, sockmode):
if not linux_net_utils.device_exists(dev):
if not nova.privsep.linux_net.device_exists(dev):
utils.execute('fp-vdev', 'add', dev, '--sockpath', sockpath,
'--sockmode', sockmode, run_as_root=True)
linux_net_utils.set_device_mtu(dev)
nova.privsep.linux_net.set_device_mtu(dev)
utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True,
check_exit_code=[0, 2, 254])
def delete_fp_dev(dev):
if linux_net_utils.device_exists(dev):
if nova.privsep.linux_net.device_exists(dev):
utils.execute('fp-vdev', 'del', dev, run_as_root=True)
def delete_bridge_dev(dev):
"""Delete a network bridge."""
if linux_net_utils.device_exists(dev):
if nova.privsep.linux_net.device_exists(dev):
try:
utils.execute('ip', 'link', 'set', dev, 'down', run_as_root=True)
nova.privsep.linux_net.delete_bridge(dev)
@ -1375,7 +1375,7 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver):
"""Create a vlan unless it already exists."""
if interface is None:
interface = 'vlan%s' % vlan_num
if not linux_net_utils.device_exists(interface):
if not nova.privsep.linux_net.device_exists(interface):
LOG.debug('Starting VLAN interface %s', interface)
_execute('ip', 'link', 'add', 'link', bridge_interface,
'name', interface, 'type', 'vlan',
@ -1391,7 +1391,7 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver):
check_exit_code=[0, 2, 254])
# NOTE(vish): set mtu every time to ensure that changes to mtu get
# propagated
linux_net_utils.set_device_mtu(interface, mtu)
nova.privsep.linux_net.set_device_mtu(interface, mtu)
return interface
@staticmethod
@ -1399,7 +1399,7 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver):
def remove_vlan(vlan_num):
"""Delete a vlan."""
vlan_interface = 'vlan%s' % vlan_num
linux_net_utils.delete_net_dev(vlan_interface)
nova.privsep.linux_net.delete_net_dev(vlan_interface)
@staticmethod
@utils.synchronized('lock_bridge', external=True)
@ -1420,7 +1420,7 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver):
interface onto the bridge and reset the default gateway if necessary.
"""
if not linux_net_utils.device_exists(bridge):
if not nova.privsep.linux_net.device_exists(bridge):
LOG.debug('Starting Bridge %s', bridge)
out, err = nova.privsep.linux_net.add_bridge(bridge)
if (err and err != "device %s already exists; can't create "
@ -1505,7 +1505,7 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver):
@utils.synchronized('lock_bridge', external=True)
def remove_bridge(bridge, gateway=True, filtering=True):
"""Delete a bridge."""
if not linux_net_utils.device_exists(bridge):
if not nova.privsep.linux_net.device_exists(bridge):
return
else:
if filtering:
@ -1659,7 +1659,7 @@ class LinuxOVSInterfaceDriver(LinuxNetInterfaceDriver):
def plug(self, network, mac_address, gateway=True):
dev = self.get_dev(network)
if not linux_net_utils.device_exists(dev):
if not nova.privsep.linux_net.device_exists(dev):
bridge = CONF.linuxnet_ovs_integration_bridge
_ovs_vsctl(['--', '--may-exist', 'add-port', bridge, dev,
'--', 'set', 'Interface', dev, 'type=internal',

View File

@ -17,62 +17,19 @@
"""Utility methods for linux networking."""
import os
from oslo_concurrency import processutils
from oslo_log import log as logging
from oslo_utils import excutils
from nova.pci import utils as pci_utils
import nova.privsep.linux_net
from nova import utils
LOG = logging.getLogger(__name__)
def device_exists(device):
"""Check if ethernet device exists."""
return os.path.exists('/sys/class/net/%s' % device)
def delete_net_dev(dev):
"""Delete a network device only if it exists."""
if device_exists(dev):
try:
utils.execute('ip', 'link', 'delete', dev, run_as_root=True,
check_exit_code=[0, 2, 254])
LOG.debug("Net device removed: '%s'", dev)
except processutils.ProcessExecutionError:
with excutils.save_and_reraise_exception():
LOG.error("Failed removing net device: '%s'", dev)
def set_device_mtu(dev, mtu=None):
"""Set the device MTU."""
if mtu:
utils.execute('ip', 'link', 'set', dev, 'mtu',
mtu, run_as_root=True,
check_exit_code=[0, 2, 254])
def create_veth_pair(dev1_name, dev2_name, mtu=None):
"""Create a pair of veth devices with the specified names,
deleting any previous devices with those names.
"""
for dev in [dev1_name, dev2_name]:
delete_net_dev(dev)
utils.execute('ip', 'link', 'add', dev1_name, 'type', 'veth', 'peer',
'name', dev2_name, run_as_root=True)
for dev in [dev1_name, dev2_name]:
utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True)
utils.execute('ip', 'link', 'set', dev, 'promisc', 'on',
run_as_root=True)
set_device_mtu(dev, mtu)
def create_tap_dev(dev, mac_address=None, multiqueue=False):
if not device_exists(dev):
if not nova.privsep.linux_net.device_exists(dev):
try:
# First, try with 'ip'
cmd = ('ip', 'tuntap', 'add', dev, 'mode', 'tap')

View File

@ -17,9 +17,17 @@
Linux network specific helpers.
"""
from oslo_concurrency import processutils
import nova.privsep
import os
from oslo_concurrency import processutils
from oslo_log import log as logging
from oslo_utils import excutils
import nova.privsep.linux_net
LOG = logging.getLogger(__name__)
@nova.privsep.sys_admin_pctxt.entrypoint
@ -38,3 +46,60 @@ def delete_bridge(interface):
:param interface: the name of the bridge
"""
processutils.execute('brctl', 'delbr', interface)
def device_exists(device):
"""Check if ethernet device exists."""
return os.path.exists('/sys/class/net/%s' % device)
def delete_net_dev(dev):
"""Delete a network device only if it exists."""
if device_exists(dev):
try:
delete_net_dev_escalated(dev)
LOG.debug("Net device removed: '%s'", dev)
except processutils.ProcessExecutionError:
with excutils.save_and_reraise_exception():
LOG.error("Failed removing net device: '%s'", dev)
@nova.privsep.sys_admin_pctxt.entrypoint
def delete_net_dev_escalated(dev):
_delete_net_dev_inner(dev)
def _delete_net_dev_inner(dev):
processutils.execute('ip', 'link', 'delete', dev,
check_exit_code=[0, 2, 254])
@nova.privsep.sys_admin_pctxt.entrypoint
def set_device_mtu(dev, mtu):
_set_device_mtu_inner(dev, mtu)
def _set_device_mtu_inner(dev, mtu):
if mtu:
processutils.execute('ip', 'link', 'set', dev, 'mtu',
mtu, check_exit_code=[0, 2, 254])
@nova.privsep.sys_admin_pctxt.entrypoint
def create_veth_pair(dev1_name, dev2_name, mtu=None):
"""Create a pair of veth devices with the specified names,
deleting any previous devices with those names.
"""
_create_veth_pair_inner(dev1_name, dev2_name, mtu=mtu)
def _create_veth_pair_inner(dev1_name, dev2_name, mtu=None):
for dev in [dev1_name, dev2_name]:
delete_net_dev(dev)
processutils.execute('ip', 'link', 'add', dev1_name, 'type', 'veth',
'peer', 'name', dev2_name)
for dev in [dev1_name, dev2_name]:
processutils.execute('ip', 'link', 'set', dev, 'up')
processutils.execute('ip', 'link', 'set', dev, 'promisc', 'on')
_set_device_mtu_inner(dev, mtu)

View File

@ -124,6 +124,7 @@ class ApiSampleTestBaseV21(testscenarios.WithScenarios,
def fake_noop(*args, **kwargs):
return '', ''
self.stub_out('nova.privsep.linux_net.add_bridge', fake_noop)
self.stub_out('nova.privsep.linux_net.set_device_mtu', fake_noop)
def _setup_services(self):
pass

View File

@ -33,7 +33,6 @@ from nova.db import api as db
from nova import exception
from nova.network import driver
from nova.network import linux_net
from nova.network import linux_utils as linux_net_utils
from nova import objects
from nova import test
from nova import utils
@ -609,7 +608,7 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
"share_address": False}, "fakemac")
self.assertEqual(2, mock_add_rule.call_count)
@mock.patch('nova.network.linux_utils.device_exists')
@mock.patch('nova.privsep.linux_net.device_exists')
@mock.patch.object(utils, 'execute')
def test_linux_ovs_driver_plug_exception(self, mock_execute,
mock_device_exists):
@ -1140,7 +1139,7 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
]
}
with test.nested(
mock.patch('nova.network.linux_utils.device_exists',
mock.patch('nova.privsep.linux_net.device_exists',
return_value=True),
mock.patch.object(linux_net, '_execute', return_value=('', '')),
mock.patch.object(netifaces, 'ifaddresses')
@ -1160,7 +1159,7 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
return ('', '')
with test.nested(
mock.patch('nova.network.linux_utils.device_exists',
mock.patch('nova.privsep.linux_net.device_exists',
return_value=True),
mock.patch.object(linux_net, '_execute', fake_execute)
) as (device_exists, _):
@ -1178,7 +1177,7 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
return ('', '')
with test.nested(
mock.patch('nova.network.linux_utils.device_exists',
mock.patch('nova.privsep.linux_net.device_exists',
return_value=False),
mock.patch('nova.privsep.linux_net.add_bridge', fake_execute)
) as (device_exists, _):
@ -1186,26 +1185,6 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
driver.ensure_bridge('brq1234567-89', '')
device_exists.assert_called_once_with('brq1234567-89')
def _create_veth_pair(self, calls):
with mock.patch.object(utils, 'execute', return_value=('', '')) as ex:
linux_net_utils.create_veth_pair('fake-dev1', 'fake-dev2')
ex.assert_has_calls(calls)
def test_create_veth_pair(self):
calls = [
mock.call('ip', 'link', 'add', 'fake-dev1', 'type', 'veth',
'peer', 'name', 'fake-dev2', run_as_root=True),
mock.call('ip', 'link', 'set', 'fake-dev1', 'up',
run_as_root=True),
mock.call('ip', 'link', 'set', 'fake-dev1', 'promisc', 'on',
run_as_root=True),
mock.call('ip', 'link', 'set', 'fake-dev2', 'up',
run_as_root=True),
mock.call('ip', 'link', 'set', 'fake-dev2', 'promisc', 'on',
run_as_root=True)
]
self._create_veth_pair(calls)
def test_exec_ebtables_success(self):
executes = []
@ -1300,8 +1279,8 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
self.assertEqual([mock.call('fake-bridge')], mock_delete.mock_calls)
@mock.patch.object(linux_net, '_execute')
@mock.patch('nova.network.linux_utils.device_exists', return_value=False)
@mock.patch('nova.network.linux_utils.set_device_mtu')
@mock.patch('nova.privsep.linux_net.device_exists', return_value=False)
@mock.patch('nova.privsep.linux_net.set_device_mtu')
def test_ensure_vlan(self, mock_set_device_mtu, mock_device_exists,
mock_execute):
interface = linux_net.LinuxBridgeInterfaceDriver.ensure_vlan(
@ -1321,8 +1300,8 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
mock_set_device_mtu.assert_called_once_with('vlan_name', 'MTU')
@mock.patch.object(linux_net, '_execute')
@mock.patch('nova.network.linux_utils.device_exists', return_value=True)
@mock.patch('nova.network.linux_utils.set_device_mtu')
@mock.patch('nova.privsep.linux_net.device_exists', return_value=True)
@mock.patch('nova.privsep.linux_net.set_device_mtu')
def test_ensure_vlan_device_exists(self, mock_set_device_mtu,
mock_device_exists, mock_execute):
interface = linux_net.LinuxBridgeInterfaceDriver.ensure_vlan(1, 'eth0')

View File

@ -1922,11 +1922,11 @@ class VlanNetworkTestCase(test.TestCase):
'DE:AD:BE:EF:00:00',
run_as_root=True)
@mock.patch('nova.network.linux_utils.device_exists', return_value=True)
@mock.patch('nova.privsep.linux_net.device_exists', return_value=True)
def test_deallocate_fixed_with_dhcp(self, mock_dev_exists):
self._deallocate_fixed_with_dhcp(mock_dev_exists)
@mock.patch('nova.network.linux_utils.device_exists', return_value=False)
@mock.patch('nova.privsep.linux_net.device_exists', return_value=False)
def test_deallocate_fixed_without_dhcp(self, mock_dev_exists):
self._deallocate_fixed_with_dhcp(mock_dev_exists)
@ -2834,7 +2834,8 @@ class AllocateTestCase(test.TestCase):
fakes.FAKE_PROJECT_ID)
@mock.patch('nova.privsep.linux_net.add_bridge', return_value=('', ''))
def test_allocate_for_instance(self, mock_add_bridge):
@mock.patch('nova.privsep.linux_net.set_device_mtu')
def test_allocate_for_instance(self, mock_set_mtu, mock_add_bridge):
address = "10.10.10.10"
self.flags(auto_assign_floating_ip=True)
@ -2899,7 +2900,9 @@ class AllocateTestCase(test.TestCase):
requested_networks=requested_networks)
@mock.patch('nova.privsep.linux_net.add_bridge', return_value=('', ''))
def test_allocate_for_instance_with_mac(self, mock_add_bridge):
@mock.patch('nova.privsep.linux_net.set_device_mtu')
def test_allocate_for_instance_with_mac(self, mock_set_mtu,
mock_add_bridge):
available_macs = set(['ca:fe:de:ad:be:ef'])
inst = db.instance_create(self.context, {'host': HOST,
'display_name': HOST,

View File

@ -23,12 +23,6 @@ from nova import test
class NetUtilsTestCase(test.NoDBTestCase):
def test_set_device_mtu_default(self):
calls = []
with mock.patch('nova.utils.execute', return_value=('', '')) as ex:
net_utils.set_device_mtu('fake-dev')
ex.assert_has_calls(calls)
@mock.patch('nova.utils.execute')
def test_create_tap_dev(self, mock_execute):
net_utils.create_tap_dev('tap42')

View File

@ -0,0 +1,48 @@
# Copyright 2016 Red Hat, Inc
# Copyright 2017 Rackspace Australia
#
# 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
import nova.privsep.linux_net
from nova import test
class LinuxNetTestCase(test.NoDBTestCase):
"""Test networking helpers."""
def _create_veth_pair(self, calls):
with mock.patch('oslo_concurrency.processutils.execute',
return_value=('', '')) as ex:
nova.privsep.linux_net._create_veth_pair_inner(
'fake-dev1', 'fake-dev2')
ex.assert_has_calls(calls)
def test_create_veth_pair(self):
calls = [
mock.call('ip', 'link', 'add', 'fake-dev1', 'type', 'veth',
'peer', 'name', 'fake-dev2'),
mock.call('ip', 'link', 'set', 'fake-dev1', 'up'),
mock.call('ip', 'link', 'set', 'fake-dev1', 'promisc', 'on'),
mock.call('ip', 'link', 'set', 'fake-dev2', 'up'),
mock.call('ip', 'link', 'set', 'fake-dev2', 'promisc', 'on')
]
self._create_veth_pair(calls)
@mock.patch('oslo_concurrency.processutils.execute',
return_value=('', ''))
def test_set_device_mtu_default(self, mock_exec):
calls = []
nova.privsep.linux_net._set_device_mtu_inner('fake-dev', None)
mock_exec.assert_has_calls(calls)

View File

@ -999,7 +999,7 @@ class LibvirtVifTestCase(test.NoDBTestCase):
d = vif.LibvirtGenericVIFDriver()
d.unplug(self.instance, self.vif_iovisor)
@mock.patch('nova.network.linux_utils.device_exists')
@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):
device_exists.return_value = True
@ -1143,9 +1143,9 @@ class LibvirtVifTestCase(test.NoDBTestCase):
self._assertTypeAndMacEquals(node, "ethernet", "target", "dev",
self.vif_tap, br_want)
@mock.patch('nova.network.linux_utils.device_exists')
def test_plug_tap(self, device_exists):
device_exists.return_value = True
@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):
d = vif.LibvirtGenericVIFDriver()
d.plug(self.instance, self.vif_tap)

View File

@ -1136,7 +1136,9 @@ class XenAPIVMTestCase(stubs.XenAPITestBase,
@mock.patch.object(vmops.VMOps, '_create_vifs')
@mock.patch('nova.privsep.linux_net.add_bridge', return_value=('', ''))
def test_spawn_vlanmanager(self, mock_add_bridge, mock_create_vifs):
@mock.patch('nova.privsep.linux_net.set_device_mtu')
def test_spawn_vlanmanager(self, mock_set_mtu, mock_add_bridge,
mock_create_vifs):
self.flags(network_manager='nova.network.manager.VlanManager',
vlan_interface='fake0')
# Reset network table

View File

@ -35,6 +35,7 @@ from nova.network import linux_utils as linux_net_utils
from nova.network import model as network_model
from nova.network import os_vif_util
from nova import objects
import nova.privsep.linux_net
from nova import profiler
from nova import utils
from nova.virt.libvirt import config as vconfig
@ -715,7 +716,7 @@ class LibvirtGenericVIFDriver(object):
linux_net_utils.create_tap_dev(dev, mac)
network = vif.get('network')
mtu = network.get_meta('mtu') if network else None
linux_net_utils.set_device_mtu(dev, mtu)
nova.privsep.linux_net.set_device_mtu(dev, mtu)
def plug_vhostuser(self, instance, vif):
pass
@ -851,7 +852,7 @@ class LibvirtGenericVIFDriver(object):
port_id = vif['id']
try:
nova.privsep.libvirt.unplug_midonet_vif(port_id)
linux_net_utils.delete_net_dev(dev)
nova.privsep.linux_net.delete_net_dev(dev)
except processutils.ProcessExecutionError:
LOG.exception(_("Failed while unplugging vif"), instance=instance)
@ -859,7 +860,7 @@ class LibvirtGenericVIFDriver(object):
"""Unplug a VIF_TYPE_TAP virtual interface."""
dev = self.get_vif_devname(vif)
try:
linux_net_utils.delete_net_dev(dev)
nova.privsep.linux_net.delete_net_dev(dev)
except processutils.ProcessExecutionError:
LOG.exception(_("Failed while unplugging vif"), instance=instance)
@ -872,7 +873,7 @@ class LibvirtGenericVIFDriver(object):
dev = self.get_vif_devname(vif)
try:
nova.privsep.libvirt.unplug_plumgrid_vif(dev)
linux_net_utils.delete_net_dev(dev)
nova.privsep.linux_net.delete_net_dev(dev)
except processutils.ProcessExecutionError:
LOG.exception(_("Failed while unplugging vif"), instance=instance)
@ -888,7 +889,7 @@ class LibvirtGenericVIFDriver(object):
port_id = vif['id']
try:
nova.privsep.libvirt.unplug_contrail_vif(port_id)
linux_net_utils.delete_net_dev(dev)
nova.privsep.linux_net.delete_net_dev(dev)
except processutils.ProcessExecutionError:
LOG.exception(_("Failed while unplugging vif"), instance=instance)