From 015719b9526abb6053d3249f9230678c6a03a76d Mon Sep 17 00:00:00 2001 From: catborise Date: Tue, 21 Jul 2020 14:56:00 +0300 Subject: [PATCH] add macvtap support : create macvtap virtual net, add/edit instance network for macvtap --- .../templates/instances/settings_tab.html | 13 ++- instances/views.py | 8 +- networks/forms.py | 2 +- networks/templates/create_net_block.html | 14 +-- networks/templates/network.html | 1 - networks/templates/networks.html | 6 ++ networks/views.py | 4 +- vrtManager/instance.py | 86 ++++++++++--------- vrtManager/network.py | 23 +++-- 9 files changed, 90 insertions(+), 67 deletions(-) diff --git a/instances/templates/instances/settings_tab.html b/instances/templates/instances/settings_tab.html index b31be04..62d6c5a 100644 --- a/instances/templates/instances/settings_tab.html +++ b/instances/templates/instances/settings_tab.html @@ -353,6 +353,7 @@ {% trans 'active' %} + {{ network.type }} {% trans 'MAC' %} @@ -390,10 +391,10 @@ @@ -405,7 +406,7 @@ @@ -462,7 +463,11 @@ - + + {% if network.type == 'direct' %} + {% trans 'In most configurations, macvtap does not work for host to guest network communication' %} + {% endif %} + {% endfor %} diff --git a/instances/views.py b/instances/views.py index d0e8c04..a454e84 100644 --- a/instances/views.py +++ b/instances/views.py @@ -965,8 +965,8 @@ def set_qos(request, pk): else: messages.success( request, - _(f"{qos_dir.capitalize()} QoS is set. Network XML is changed.") + - _("Stop and start network to activate new config"), + _(f"{qos_dir.capitalize()} QoS is set. Network XML is changed. \ + Stop and start network to activate new config.") ) return redirect(request.META.get('HTTP_REFERER') + '#network') @@ -984,8 +984,8 @@ def unset_qos(request, pk): else: messages.success( request, - _(f"{qos_dir.capitalize()} QoS is deleted. Network XML is changed. ") + - _("Stop and start network to activate new config."), + _(f"{qos_dir.capitalize()} QoS is deleted. Network XML is changed. \ + Stop and start network to activate new config.") ) return redirect(request.META.get('HTTP_REFERER') + '#network') diff --git a/networks/forms.py b/networks/forms.py index 5fe0cee..82d71a0 100644 --- a/networks/forms.py +++ b/networks/forms.py @@ -46,7 +46,7 @@ class AddNetPool(forms.Form): def clean_bridge_name(self): bridge_name = self.cleaned_data['bridge_name'] - if self.cleaned_data['forward'] == 'bridge': + if self.cleaned_data['forward'] in ['bridge', 'macvtap']: have_symbol = re.match('^[a-zA-Z0-9\.\_\:\-]+$', bridge_name) if not have_symbol: raise forms.ValidationError(_('The pool bridge name must not contain any special characters')) diff --git a/networks/templates/create_net_block.html b/networks/templates/create_net_block.html index a40eeba..c317084 100644 --- a/networks/templates/create_net_block.html +++ b/networks/templates/create_net_block.html @@ -28,6 +28,7 @@ + @@ -55,25 +56,25 @@ -
+
-
+
- +
- +
-
+
@@ -88,4 +89,5 @@
-{% endif %} \ No newline at end of file +{% endif %} + diff --git a/networks/templates/network.html b/networks/templates/network.html index 415a483..5deea60 100644 --- a/networks/templates/network.html +++ b/networks/templates/network.html @@ -37,7 +37,6 @@ {% include 'errors_block.html' %} - {% include 'messages_block.html' %}
diff --git a/networks/templates/networks.html b/networks/templates/networks.html index 98ace57..30a05ac 100644 --- a/networks/templates/networks.html +++ b/networks/templates/networks.html @@ -79,6 +79,12 @@ if ($(this).val() == 'bridge') { $('.bridge_name_form_group').show(); $('.bridge_name_form_group_dhcp').hide(); + } else if ($(this).val() == 'macvtap') { + $('#bridge_label').text("Dev Name"); + $('#bridge_name').attr("placeholder", "eth0"); + $('.bridge_name_form_group').show(); + $('.bridge_name_form_group_dhcp').hide(); + $('.openvswitch').hide(); } else { $('.bridge_name_form_group').hide(); $('.bridge_name_form_group_dhcp').show(); diff --git a/networks/views.py b/networks/views.py index b1c85b8..9072636 100644 --- a/networks/views.py +++ b/networks/views.py @@ -42,8 +42,8 @@ def networks(request, compute_id): if data['name'] in networks: msg = _("Network pool name already in use") error_messages.append(msg) - if data['forward'] == 'bridge' and data['bridge_name'] == '': - error_messages.append(_('Please enter bridge name')) + if data['forward'] in ['bridge', 'macvtap'] and data['bridge_name'] == '': + error_messages.append(_('Please enter bridge/dev name')) if data['subnet']: ipv4 = True gateway4, netmask4, dhcp4 = network_size(data['subnet'], data['dhcp4']) diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 5e266e5..149ca0f 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -345,6 +345,7 @@ class wvmInstance(wvmConnect): result = [] inbound = outbound = [] for net in ctx.xpath('/domain/devices/interface'): + interface_type = net.xpath('@type')[0] mac_inst = net.xpath('mac/@address')[0] nic_inst = net.xpath('source/@network|source/@bridge|source/@dev')[0] target_inst = '' if not net.xpath('target/@dev') else net.xpath('target/@dev')[0] @@ -369,6 +370,7 @@ class wvmInstance(wvmConnect): except libvirtError: ipv4, ipv6 = None, None result.append({ + 'type': interface_type, 'mac': mac_inst, 'nic': nic_inst, 'target': target_inst, @@ -1289,24 +1291,39 @@ class wvmInstance(wvmConnect): bridge_name = iface.name() else: net = self.get_network(source) - bridge_name = net.bridgeName() + try: + bridge_name = net.bridgeName() + except libvirtError: + bridge_name = None return bridge_name def add_network(self, mac_address, source, source_type='net', model='virtio', nwfilter=None): - bridge_name = self.get_bridge_name(source, source_type) + forward_mode = '' + if source_type != 'iface': + forward_mode = self.get_network_forward(source) - forward_mode = self.get_network_forward(source) if forward_mode in ['nat', 'isolated', 'routed']: interface_type = 'network' + elif forward_mode == '': + interface_type = 'direct' else: - interface_type = 'bridge' + if self.get_bridge_name(source, source_type) is None: + interface_type = 'network' + else: + interface_type = 'bridge' xml_iface = f""" """ if interface_type == 'network': xml_iface += f"""""" + elif interface_type == 'direct': + if source_type == 'net': + xml_iface += f"""""" + else: + xml_iface += f"""""" else: + bridge_name = self.get_bridge_name(source, source_type) xml_iface += f"""""" xml_iface += f"""""" if nwfilter: @@ -1342,49 +1359,38 @@ class wvmInstance(wvmConnect): net_source_type = network_data.get('net-source-' + str(num) + '-type') net_filter = network_data.get('net-nwfilter-' + str(num)) net_model = network_data.get('net-model-' + str(num)) + + source = interface.find('source') if interface.get('type') == 'bridge': bridge_name = self.get_bridge_name(net_source, net_source_type) - source = interface.find('mac') - source.set('address', net_mac) - source = interface.find('source') source.set('bridge', bridge_name) - - source = interface.find('model') - if net_model != 'default': - source.attrib['type'] = net_model + elif interface.get('type') in ['network', 'direct']: + if net_source_type == 'net': + source.set('network', net_source) + elif net_source_type == 'iface': + source.set('dev', net_source) else: - interface.remove(source) + raise libvirtError(f"Unknown network type: {net_source_type}") + else: + raise libvirtError(f"Unknown network type: {interface.get('type')}") - source = interface.find('filterref') - if net_filter: - if source is not None: source.set('filter', net_filter) - else: - element = ElementTree.Element("filterref") - element.attrib['filter'] = net_filter - interface.append(element) - else: - if source is not None: interface.remove(source) - elif interface.get('type') == 'network': - source = interface.find('mac') - source.set('address', net_mac) - source = interface.find('source') - source.set('network', net_source) + source = interface.find('model') + if net_model != 'default': + source.attrib['type'] = net_model + else: + interface.remove(source) - source = interface.find('model') - if net_model != 'default': - source.attrib['type'] = net_model + source = interface.find('mac') + source.set('address', net_mac) + source = interface.find('filterref') + if net_filter: + if source is not None: source.set('filter', net_filter) else: - interface.remove(source) - - source = interface.find('filterref') - if net_filter: - if source is not None: source.set('filter', net_filter) - else: - element = ElementTree.Element("filterref") - element.attrib['filter'] = net_filter - interface.append(element) - else: - if source is not None: interface.remove(source) + element = ElementTree.Element("filterref") + element.attrib['filter'] = net_filter + interface.append(element) + else: + if source is not None: interface.remove(source) new_xml = ElementTree.tostring(tree).decode() self._defineXML(new_xml) diff --git a/vrtManager/network.py b/vrtManager/network.py index 7173f03..dec2362 100644 --- a/vrtManager/network.py +++ b/vrtManager/network.py @@ -55,15 +55,20 @@ class wvmNetworks(wvmConnect): {name}""" if forward in ['nat', 'route', 'bridge']: xml += f"""""" - xml += """""" - if openvswitch is True: - xml += """""" - if forward != 'bridge': + if forward == 'macvtap': + xml += f""" + + """ + else: + xml += """""" + if openvswitch is True: + xml += """""" + if forward not in ['bridge', 'macvtap']: if ipv4: xml += f"""""" if dhcp4: