Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend virt.network_define to create NAT networks #54197

Merged
merged 1 commit into from
Jan 2, 2020
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
47 changes: 44 additions & 3 deletions salt/modules/virt.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
from salt.exceptions import CommandExecutionError, SaltInvocationError
from salt.ext import six
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
from salt._compat import ipaddress

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -654,7 +655,8 @@ def _gen_net_xml(name,
bridge,
forward,
vport,
tag=None):
tag=None,
ip_configs=None):
'''
Generate the XML string to define a libvirt network
'''
Expand All @@ -664,6 +666,10 @@ def _gen_net_xml(name,
'forward': forward,
'vport': vport,
'tag': tag,
'ip_configs': [{
'address': ipaddress.ip_network(config['cidr']),
'dhcp_ranges': config.get('dhcp_ranges', []),
} for config in ip_configs or []],
}
fn_ = 'libvirt_network.jinja'
try:
Expand Down Expand Up @@ -4279,7 +4285,12 @@ def cpu_baseline(full=False, migratable=False, out='libvirt', **kwargs):
return cpu.toxml()


def network_define(name, bridge, forward, **kwargs):
def network_define(name,
bridge,
forward,
ipv4_config=None,
ipv6_config=None,
**kwargs):
'''
Create libvirt network.

Expand All @@ -4290,10 +4301,38 @@ def network_define(name, bridge, forward, **kwargs):
:param tag: Vlan tag
:param autostart: Network autostart (default True)
:param start: Network start (default True)
:param ipv4_config: IP v4 configuration
Dictionary describing the IP v4 setup like IP range and
a possible DHCP configuration. The structure is documented
in net-define-ip_.

..versionadded:: Neon
:type ipv4_config: dict or None

:param ipv6_config: IP v6 configuration
Dictionary describing the IP v6 setup like IP range and
a possible DHCP configuration. The structure is documented
in net-define-ip_.

..versionadded:: Neon
:type ipv6_config: dict or None

:param connection: libvirt connection URI, overriding defaults
:param username: username to connect with, overriding defaults
:param password: password to connect with, overriding defaults

.. _net-define-ip:

** IP configuration definition

Both the IPv4 and IPv6 configuration dictionaries can contain the following properties:

cidr
CIDR notation for the network. For example '192.168.124.0/24'

dhcp_ranges
A list of dictionary with ``'start'`` and ``'end'`` properties.

CLI Example:

.. code-block:: bash
Expand All @@ -4307,12 +4346,14 @@ def network_define(name, bridge, forward, **kwargs):
tag = kwargs.get('tag', None)
autostart = kwargs.get('autostart', True)
starting = kwargs.get('start', True)

net_xml = _gen_net_xml(
name,
bridge,
forward,
vport,
tag,
tag=tag,
ip_configs=[config for config in [ipv4_config, ipv6_config] if config],
)
try:
conn.networkDefineXML(net_xml)
Expand Down
38 changes: 38 additions & 0 deletions salt/states/virt.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,13 +637,34 @@ def network_running(name,
forward,
vport=None,
tag=None,
ipv4_config=None,
ipv6_config=None,
autostart=True,
connection=None,
username=None,
password=None):
'''
Defines and starts a new network with specified arguments.

:param bridge: Bridge name
:param forward: Forward mode(bridge, router, nat)
:param vport: Virtualport type (Default: ``'None'``)
:param tag: Vlan tag (Default: ``'None'``)
:param ipv4_config:
IPv4 network configuration. See the :py:func`virt.network_define
<salt.modules.virt.network_define>` function corresponding parameter documentation
for more details on this dictionary.
(Default: None).

.. versionadded:: neon
:param ipv6_config:
IPv6 network configuration. See the :py:func`virt.network_define
<salt.modules.virt.network_define>` function corresponding parameter documentation
for more details on this dictionary.
(Default: None).

.. versionadded:: neon
:param autostart: Network autostart (default ``'True'``)
:param connection: libvirt connection URI, overriding defaults

.. versionadded:: 2019.2.0
Expand All @@ -669,6 +690,21 @@ def network_running(name,
- tag: 180
- autostart: True

.. code-block:: yaml

network_name:
virt.network_define:
- bridge: natted
- forward: nat
- ipv4_config:
cidr: 192.168.42.0/24
dhcp_ranges:
- start: 192.168.42.10
end: 192.168.42.25
- start: 192.168.42.100
end: 192.168.42.150
- autostart: True

'''
ret = {'name': name,
'changes': {},
Expand All @@ -691,6 +727,8 @@ def network_running(name,
forward,
vport=vport,
tag=tag,
ipv4_config=ipv4_config,
ipv6_config=ipv6_config,
autostart=autostart,
start=True,
connection=connection,
Expand Down
13 changes: 12 additions & 1 deletion salt/templates/virt/libvirt_network.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,15 @@
<vlan>
<tag id='{{ tag }}'/>
</vlan>{% endif %}
</network>
{% for ip_config in ip_configs %}
<ip family='ipv{{ ip_config.address.version }}'
address='{{ ip_config.address.network_address }}'
prefix='{{ ip_config.address.prefixlen }}'>
<dhcp>
{% for range in ip_config.dhcp_ranges %}
<range start='{{ range.start }}' end='{{ range.end }}' />
{% endfor %}
</dhcp>
</ip>
{% endfor %}
</network>
26 changes: 26 additions & 0 deletions tests/unit/modules/test_virt.py
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,32 @@ def test_network(self):
self.assertEqual(root.find('forward').attrib['mode'], 'bridge')
self.assertEqual(root.find('virtualport').attrib['type'], 'openvswitch')

def test_network_nat(self):
'''
Test virt._get_net_xml() in a nat setup
'''
xml_data = virt._gen_net_xml('network', 'main', 'nat', None, ip_configs=[
{
'cidr': '192.168.2.0/24',
'dhcp_ranges': [
{'start': '192.168.2.10', 'end': '192.168.2.25'},
{'start': '192.168.2.110', 'end': '192.168.2.125'},
]
}
])
root = ET.fromstring(xml_data)
self.assertEqual(root.find('name').text, 'network')
self.assertEqual(root.find('bridge').attrib['name'], 'main')
self.assertEqual(root.find('forward').attrib['mode'], 'nat')
self.assertEqual(root.find("./ip[@address='192.168.2.0']").attrib['prefix'], '24')
self.assertEqual(root.find("./ip[@address='192.168.2.0']").attrib['family'], 'ipv4')
self.assertEqual(
root.find("./ip[@address='192.168.2.0']/dhcp/range[@start='192.168.2.10']").attrib['end'],
'192.168.2.25')
self.assertEqual(
root.find("./ip[@address='192.168.2.0']/dhcp/range[@start='192.168.2.110']").attrib['end'],
'192.168.2.125')

def test_domain_capabilities(self):
'''
Test the virt.domain_capabilities parsing
Expand Down
26 changes: 26 additions & 0 deletions tests/unit/states/test_virt.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,19 @@ def test_network_running(self):
'bridge',
vport='openvswitch',
tag=180,
ipv4_config={
'cidr': '192.168.2.0/24',
'dhcp_ranges': [
{'start': '192.168.2.10', 'end': '192.168.2.25'},
{'start': '192.168.2.110', 'end': '192.168.2.125'},
]
},
ipv6_config={
'cidr': '2001:db8:ca2:2::1/64',
'dhcp_ranges': [
{'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
]
},
autostart=False,
connection='myconnection',
username='user',
Expand All @@ -610,6 +623,19 @@ def test_network_running(self):
tag=180,
autostart=False,
start=True,
ipv4_config={
'cidr': '192.168.2.0/24',
'dhcp_ranges': [
{'start': '192.168.2.10', 'end': '192.168.2.25'},
{'start': '192.168.2.110', 'end': '192.168.2.125'},
]
},
ipv6_config={
'cidr': '2001:db8:ca2:2::1/64',
'dhcp_ranges': [
{'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
]
},
connection='myconnection',
username='user',
password='secret')
Expand Down