Add support for enabling hotplug on interfaces
This patch adds support for enabling hotplugging on interfaces (disabled by default). This is useful for configuring SR-IOV root devices so that they "return" to the system when no longer used by a VM. Note: also updates an invalid value in the interface and ib_interface sample files. Partial-Bug: #1639901 Change-Id: Idfc17d6f20bb306271838895bc53f4b109dd664d
This commit is contained in:
parent
9971eb3af9
commit
433a0f3cbe
|
@ -20,7 +20,7 @@
|
|||
"type": "ib_interface",
|
||||
"name": "ib1",
|
||||
"use_dhcp": true,
|
||||
"defroute": no
|
||||
"defroute": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@ network_config:
|
|||
type: interface
|
||||
name: ib1
|
||||
use_dhcp: true
|
||||
defroute: no
|
||||
defroute: false
|
||||
|
|
|
@ -25,8 +25,14 @@
|
|||
"type": "interface",
|
||||
"name": "em2",
|
||||
"use_dhcp": true,
|
||||
"defroute": no,
|
||||
"defroute": false,
|
||||
"ethtool_opts": "speed 1000 duplex full"
|
||||
},
|
||||
{
|
||||
"type": "interface",
|
||||
"name": "em3",
|
||||
"use_dhcp": true,
|
||||
"hotplug": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -19,5 +19,10 @@ network_config:
|
|||
type: interface
|
||||
name: em2
|
||||
use_dhcp: true
|
||||
defroute: no
|
||||
defroute: false
|
||||
ethtool_opts: "speed 1000 duplex full"
|
||||
-
|
||||
type: interface
|
||||
name: em3
|
||||
use_dhcp: true
|
||||
hotplug: true
|
||||
|
|
|
@ -127,7 +127,10 @@ class ENINetConfig(os_net_config.NetConfig):
|
|||
data += address_data
|
||||
data += " vlan-raw-device %s\n" % interface.device
|
||||
else:
|
||||
data += "auto %s\n" % interface.name
|
||||
if isinstance(interface, objects.Interface) and interface.hotplug:
|
||||
data += "allow-hotplug %s\n" % interface.name
|
||||
else:
|
||||
data += "auto %s\n" % interface.name
|
||||
data += _iface
|
||||
data += address_data
|
||||
if interface.mtu:
|
||||
|
|
|
@ -131,7 +131,10 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
|||
data = "# This file is autogenerated by os-net-config\n"
|
||||
data += "DEVICE=%s\n" % base_opt.name
|
||||
data += "ONBOOT=yes\n"
|
||||
data += "HOTPLUG=no\n"
|
||||
if isinstance(base_opt, objects.Interface) and base_opt.hotplug:
|
||||
data += "HOTPLUG=yes\n"
|
||||
else:
|
||||
data += "HOTPLUG=no\n"
|
||||
data += "NM_CONTROLLED=no\n"
|
||||
if not base_opt.dns_servers and not base_opt.use_dhcp:
|
||||
data += "PEERDNS=no\n"
|
||||
|
|
|
@ -287,7 +287,7 @@ class Interface(_BaseOpts):
|
|||
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
|
||||
routes=None, mtu=None, primary=False, nic_mapping=None,
|
||||
persist_mapping=False, defroute=True, dhclient_args=None,
|
||||
dns_servers=None, ethtool_opts=None):
|
||||
dns_servers=None, ethtool_opts=None, hotplug=False):
|
||||
addresses = addresses or []
|
||||
routes = routes or []
|
||||
dns_servers = dns_servers or []
|
||||
|
@ -296,13 +296,16 @@ class Interface(_BaseOpts):
|
|||
persist_mapping, defroute,
|
||||
dhclient_args, dns_servers)
|
||||
self.ethtool_opts = ethtool_opts
|
||||
self.hotplug = hotplug
|
||||
|
||||
@staticmethod
|
||||
def from_json(json):
|
||||
name = _get_required_field(json, 'name', 'Interface')
|
||||
hotplug = strutils.bool_from_string(str(json.get('hotplug', False)))
|
||||
opts = _BaseOpts.base_opts_from_json(json)
|
||||
ethtool_opts = json.get('ethtool_opts', None)
|
||||
return Interface(name, *opts, ethtool_opts=ethtool_opts)
|
||||
return Interface(name, *opts, ethtool_opts=ethtool_opts,
|
||||
hotplug=hotplug)
|
||||
|
||||
|
||||
class Vlan(_BaseOpts):
|
||||
|
|
|
@ -32,6 +32,12 @@ _V4_IFACE_STATIC_IP = _AUTO + """iface eth0 inet static
|
|||
netmask 255.255.255.0
|
||||
"""
|
||||
|
||||
_IFACE_HOTPLUG = """allow-hotplug eth0
|
||||
iface eth0 inet static
|
||||
address 192.168.1.2
|
||||
netmask 255.255.255.0
|
||||
"""
|
||||
|
||||
_V4_IFACE_STATIC_IP_MULTIPLE = (_V4_IFACE_STATIC_IP + _AUTO +
|
||||
"""iface eth0 inet static
|
||||
address 10.0.0.2
|
||||
|
@ -117,8 +123,9 @@ class TestENINetConfig(base.TestCase):
|
|||
def get_route_config(self):
|
||||
return self.provider.routes[self.if_name]
|
||||
|
||||
def _default_interface(self, addr=[], rts=[]):
|
||||
return objects.Interface(self.if_name, addresses=addr, routes=rts)
|
||||
def _default_interface(self, addr=[], rts=[], hotplug=False):
|
||||
return objects.Interface(self.if_name, addresses=addr, routes=rts,
|
||||
hotplug=hotplug)
|
||||
|
||||
def test_interface_no_ip(self):
|
||||
interface = self._default_interface()
|
||||
|
@ -131,6 +138,12 @@ class TestENINetConfig(base.TestCase):
|
|||
self.provider.add_interface(interface)
|
||||
self.assertEqual(_V4_IFACE_STATIC_IP, self.get_interface_config())
|
||||
|
||||
def test_add_interface_with_hotplug(self):
|
||||
v4_addr = objects.Address('192.168.1.2/24')
|
||||
interface = self._default_interface(addr=[v4_addr], hotplug=True)
|
||||
self.provider.add_interface(interface)
|
||||
self.assertEqual(_IFACE_HOTPLUG, self.get_interface_config())
|
||||
|
||||
def test_add_interface_with_v4_multiple(self):
|
||||
v4_addresses = [objects.Address('192.168.1.2/24'),
|
||||
objects.Address('10.0.0.2/8')]
|
||||
|
|
|
@ -33,6 +33,15 @@ NM_CONTROLLED=no
|
|||
PEERDNS=no
|
||||
"""
|
||||
|
||||
_HOTPLUG = """# This file is autogenerated by os-net-config
|
||||
DEVICE=em1
|
||||
ONBOOT=yes
|
||||
HOTPLUG=yes
|
||||
NM_CONTROLLED=no
|
||||
PEERDNS=no
|
||||
BOOTPROTO=none
|
||||
"""
|
||||
|
||||
_NO_IP = _BASE_IFCFG + "BOOTPROTO=none\n"
|
||||
|
||||
_V4_IFCFG = _BASE_IFCFG + """BOOTPROTO=static
|
||||
|
@ -386,6 +395,11 @@ class TestIfcfgNetConfig(base.TestCase):
|
|||
self.provider.add_interface(interface)
|
||||
self.assertEqual(_NO_IP, self.get_interface_config())
|
||||
|
||||
def test_add_interface_with_hotplug(self):
|
||||
interface = objects.Interface('em1', hotplug=True)
|
||||
self.provider.add_interface(interface)
|
||||
self.assertEqual(_HOTPLUG, self.get_interface_config())
|
||||
|
||||
def test_add_base_interface_vlan(self):
|
||||
interface = objects.Interface('em1.120')
|
||||
self.provider.add_interface(interface)
|
||||
|
|
|
@ -98,6 +98,27 @@ class TestInterface(base.TestCase):
|
|||
self.assertEqual("em1", interface.name)
|
||||
self.assertTrue(interface.use_dhcp)
|
||||
|
||||
def test_from_json_hotplug(self):
|
||||
data = """{
|
||||
"type": "interface",
|
||||
"name": "em1",
|
||||
"hotplug": true
|
||||
}
|
||||
"""
|
||||
interface = objects.object_from_json(json.loads(data))
|
||||
self.assertEqual("em1", interface.name)
|
||||
self.assertTrue(interface.hotplug)
|
||||
|
||||
def test_from_json_hotplug_off_by_default(self):
|
||||
data = """{
|
||||
"type": "interface",
|
||||
"name": "em1"
|
||||
}
|
||||
"""
|
||||
interface = objects.object_from_json(json.loads(data))
|
||||
self.assertEqual("em1", interface.name)
|
||||
self.assertFalse(interface.hotplug)
|
||||
|
||||
def test_from_json_defroute(self):
|
||||
data = '{"type": "interface", "name": "em1", "use_dhcp": true}'
|
||||
interface1 = objects.object_from_json(json.loads(data))
|
||||
|
|
Loading…
Reference in New Issue