mirror of
				https://github.com/retspen/webvirtcloud
				synced 2025-07-31 12:41:08 +00:00 
			
		
		
		
	Merge pull request #258 from catborise/master
ipv6 support enhanced & updates
This commit is contained in:
		
						commit
						0a55804251
					
				
					 8 changed files with 136 additions and 68 deletions
				
			
		|  | @ -6,10 +6,13 @@ from django.utils.translation import ugettext_lazy as _ | |||
| class AddNetPool(forms.Form): | ||||
|     name = forms.CharField(error_messages={'required': _('No pool name has been entered')}, | ||||
|                            max_length=20) | ||||
|     subnet = forms.CharField(error_messages={'required': _('No subnet has been entered')}, | ||||
|                              max_length=20) | ||||
|     subnet = forms.CharField(error_messages={'required': _('No IPv4 subnet has been entered')}, | ||||
|                              max_length=20, required=False) | ||||
|     subnet6 = forms.CharField(error_messages={'required': _('No IPv6 subnet has been entered')}, | ||||
|                              max_length=42, required=False) | ||||
|     forward = forms.CharField(max_length=100) | ||||
|     dhcp = forms.BooleanField(required=False) | ||||
|     dhcp4 = forms.BooleanField(required=False) | ||||
|     dhcp6 = forms.BooleanField(required=False) | ||||
|     fixed = forms.BooleanField(required=False) | ||||
|     bridge_name = forms.CharField(max_length=20, required=False) | ||||
|     openvswitch = forms.BooleanField(required=False) | ||||
|  | @ -25,13 +28,22 @@ class AddNetPool(forms.Form): | |||
| 
 | ||||
|     def clean_subnet(self): | ||||
|         subnet = self.cleaned_data['subnet'] | ||||
|         have_symbol = re.match('^[0-9./]+$', subnet) | ||||
|         have_symbol = re.match('^[0-9./]+$', subnet if subnet else ".") | ||||
|         if not have_symbol: | ||||
|             raise forms.ValidationError(_('The pool subnet must not contain any special characters')) | ||||
|         elif len(subnet) > 20: | ||||
|             raise forms.ValidationError(_('The pool subnet must not exceed 20 characters')) | ||||
|         return subnet | ||||
| 
 | ||||
|     def clean_subnet6(self): | ||||
|         subnet = self.cleaned_data['subnet6'] | ||||
|         have_symbol = re.match('^[0-9a-fA-F:/]+$', subnet if subnet else ":") | ||||
|         if not have_symbol: | ||||
|             raise forms.ValidationError(_('The pool subnet must not contain any special characters')) | ||||
|         elif len(subnet) > 42: | ||||
|             raise forms.ValidationError(_('The pool subnet must not exceed 42 characters')) | ||||
|         return subnet | ||||
| 
 | ||||
|     def clean_bridge_name(self): | ||||
|         bridge_name = self.cleaned_data['bridge_name'] | ||||
|         if self.cleaned_data['forward'] == 'bridge': | ||||
|  |  | |||
|  | @ -13,31 +13,13 @@ | |||
|                     <h4 class="modal-title">{% trans "Add New Network" %}</h4> | ||||
|                 </div> | ||||
|                 <div class="modal-body"> | ||||
|                     <form class="form-horizontal" method="post" action="" role="form">{% csrf_token %} | ||||
|                     <form class="form-horizontal" method="post" action="" role="form" novalidate>{% csrf_token %} | ||||
|                         <div class="form-group"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "Name" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="text" class="form-control" name="name" placeholder="default" required pattern="[a-zA-Z0-9_]+"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group_dhcp"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "Subnet pool" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="text" class="form-control" name="subnet" value="192.168.100.0/24" required pattern="[0-9\/\.]+"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group_dhcp"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "DHCP" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="checkbox" name="dhcp" value="true" checked> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group_dhcp"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "Fixed Address" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="checkbox" name="fixed" value="true"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "Type forwarding" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|  | @ -49,6 +31,42 @@ | |||
|                                 </select> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group_dhcp"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "IPv4 Subnet pool" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="text" class="form-control" name="subnet" value="" placeholder="192.168.100.0/24" required pattern="[0-9\/\.]+"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group_dhcp"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "DHCPv4" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="checkbox" name="dhcp4" value="true" checked> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group_dhcp"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "Fixed Address" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="checkbox" name="fixed" value="true"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group_dhcp"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "Enable IPv6" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="checkbox" id="enable_ipv6" name="enable_ipv6" value="false"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group_dhcp ipv6_group"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "IPv6 Subnet pool" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="text" class="form-control" name="subnet6" value="" placeholder="fd00:dead:baba:1::/64" required pattern="[0-9\/\.]+"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group_dhcp ipv6_group"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "DHCPv6" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="checkbox" name="dhcp6" value="true"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group bridge_name_form_group"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "Bridge Name" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ | |||
|                         <div class="form-group"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "ID" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="text" class="form-control" name="id" required pattern="[0-9a-dA-D\/\:]+"> | ||||
|                                 <input type="text" class="form-control" name="id" required pattern="[0-9a-fA-F\/\:]+"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group"> | ||||
|  | @ -36,7 +36,7 @@ | |||
|                         <div class="form-group"> | ||||
|                             <label class="col-sm-4 control-label">{% trans "Address" %}</label> | ||||
|                             <div class="col-sm-6"> | ||||
|                                 <input type="text" class="form-control" name="address" required pattern="[a-dA-D0-9\/\:]+"> | ||||
|                                 <input type="text" class="form-control" name="address" required pattern="[a-fA-F0-9\/\:]+"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|  |  | |||
|  | @ -39,14 +39,16 @@ | |||
| 
 | ||||
|     <div class="row"> | ||||
|         <div class="col-xs-6 col-sm-4"> | ||||
|             <p>{% trans "Network name" %}:</p> | ||||
|             <p>{% trans "Network Name" %}:</p> | ||||
|             <p>{% trans "Device" %}:</p> | ||||
|             <p>{% trans "MAC" %}:</p> | ||||
|             <p>{% trans "State" %}:</p> | ||||
|             <p>{% trans "Autostart" %}:</p> | ||||
|         </div> | ||||
|         <div class="col-xs-6 col-sm-6"> | ||||
|             <p>{{ pool }}</p> | ||||
|             <p>{{ device }}</p> | ||||
|             <p>{{ net_mac }}</p> | ||||
|             <p> | ||||
|                 <form action="" method="post" role="form">{% csrf_token %} | ||||
|                     {% ifequal state 0 %} | ||||
|  | @ -102,8 +104,8 @@ | |||
|             <div class="col-xs-6 col-sm-4"> | ||||
|                 <p>{% trans "IPv4 Forwarding" %}:</p> | ||||
|                 <p>{% trans "Network" %}:</p> | ||||
|                 <p>{% trans "DHCP" %}:</p> | ||||
|                 {% if ipv4_dhcp_range_start and ipv4_dhcp_range_end %} | ||||
|                     <p>{% trans "DHCP" %}:</p> | ||||
|                     <p>{% trans "Start" %}:</p> | ||||
|                     <p>{% trans "End" %}:</p> | ||||
|                 {% endif %} | ||||
|  | @ -123,7 +125,7 @@ | |||
|                         {% trans "ISOLATE" %} | ||||
|                     {% endif %} | ||||
|                 </p> | ||||
|                 <p>{{ ipv4_network }}</p> | ||||
|                 <p>{{ ipv4_network|default:"-"  }}</p> | ||||
|                 <p> | ||||
|                     {% if ipv4_dhcp_range_start and ipv4_dhcp_range_end %} | ||||
|                         <span class="text-success">{% trans "ON" %}</span> | ||||
|  | @ -227,8 +229,8 @@ | |||
|             <div class="col-xs-6 col-sm-4"> | ||||
|                 <p>{% trans "IPv6 Forwarding" %}:</p> | ||||
|                 <p>{% trans "Network" %}:</p> | ||||
|                 <p>{% trans "DHCP" %}:</p> | ||||
|                 {% if ipv6_dhcp_range_start and ipv6_dhcp_range_end %} | ||||
|                     <p>{% trans "DHCP" %}:</p> | ||||
|                     <p>{% trans "Start" %}:</p> | ||||
|                     <p>{% trans "End" %}:</p> | ||||
|                 {% endif %} | ||||
|  | @ -241,7 +243,7 @@ | |||
|                         {% trans "ROUTE" %} | ||||
|                     {% endif %} | ||||
|                 </p> | ||||
|                 <p>{{ ipv6_network }}</p> | ||||
|                 <p>{{ ipv6_network|default:"-" }}</p> | ||||
|                 <p> | ||||
|                     {% if ipv6_dhcp_range_start and ipv6_dhcp_range_end %} | ||||
|                         <span class="text-success">{% trans "ON" %}</span> | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ | |||
|             <div class="col-lg-12"> | ||||
|                 <div class="alert alert-warning alert-dismissable"> | ||||
|                     <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> | ||||
|                     <i class="fa fa-exclamation-triangle"></i><strong>{% trans "Warning:" %}</strong> {% trans "Hypervisor doesn't have any Networks" %} | ||||
|                     <i class="fa fa-exclamation-triangle"></i><strong>{% trans "Warning" %}:</strong> {% trans "Hypervisor doesn't have any network" %} | ||||
|                 </div> | ||||
|             </div> | ||||
|         {% else %} | ||||
|  | @ -54,8 +54,8 @@ | |||
|                         <div class="panel-body"> | ||||
|                             <div class="row"> | ||||
|                                 <div class="col-xs-4 col-sm-4"> | ||||
|                                     <p><strong>{% trans "Device:" %}</strong></p> | ||||
|                                     <p><strong>{% trans "Forward:" %}</strong></p> | ||||
|                                     <p><strong>{% trans "Device" %}:</strong></p> | ||||
|                                     <p><strong>{% trans "Forward" %}:</strong></p> | ||||
|                                 </div> | ||||
|                                 <div class="col-xs-6 col-sm-7"> | ||||
|                                     <p>{{ pool.device }}</p> | ||||
|  | @ -81,6 +81,14 @@ | |||
|                 $('.bridge_name_form_group_dhcp').show(); | ||||
|             } | ||||
|         }).change(); | ||||
| 
 | ||||
|         $('#enable_ipv6').change(function (eventObject) { | ||||
|             if ($(this).is(':checked')) { | ||||
|                 $('.ipv6_group').show(); | ||||
|             } else { | ||||
|                 $('.ipv6_group').hide(); | ||||
|             } | ||||
|         }).change(); | ||||
|     }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -31,6 +31,9 @@ def networks(request, compute_id): | |||
|                            compute.password, | ||||
|                            compute.type) | ||||
|         networks = conn.get_networks_info() | ||||
|         dhcp4 = netmask4 = gateway4 = '' | ||||
|         dhcp6 = prefix6 = gateway6 = '' | ||||
|         ipv4 = ipv6 = False | ||||
| 
 | ||||
|         if request.method == 'POST': | ||||
|             if 'create' in request.POST: | ||||
|  | @ -38,18 +41,24 @@ def networks(request, compute_id): | |||
|                 if form.is_valid(): | ||||
|                     data = form.cleaned_data | ||||
|                     if data['name'] in networks: | ||||
|                         msg = _("Pool name already in use") | ||||
|                         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') | ||||
|                     try: | ||||
|                         gateway, netmask, dhcp = network_size(data['subnet'], data['dhcp']) | ||||
|                     except: | ||||
|                         error_msg = _("Input subnet pool error") | ||||
|                         error_messages.append(error_msg) | ||||
|                     if data['subnet']: | ||||
|                         ipv4 = True | ||||
|                         gateway4, netmask4, dhcp4 = network_size(data['subnet'], data['dhcp4']) | ||||
|                     if data['subnet6']: | ||||
|                         ipv6 = True | ||||
|                         gateway6, prefix6, dhcp6 = network_size(data['subnet6'], data['dhcp6']) | ||||
|                         if prefix6 != '64': | ||||
|                             error_messages.append('For libvirt, the IPv6 network prefix must be /64') | ||||
|                     if not error_messages: | ||||
|                         conn.create_network(data['name'], data['forward'], gateway, netmask, | ||||
|                                             dhcp, data['bridge_name'], data['openvswitch'], data['fixed']) | ||||
|                         conn.create_network(data['name'], | ||||
|                                             data['forward'], | ||||
|                                             ipv4, gateway4, netmask4, dhcp4, | ||||
|                                             ipv6, gateway6, prefix6, dhcp6, | ||||
|                                             data['bridge_name'], data['openvswitch'], data['fixed']) | ||||
|                         return HttpResponseRedirect(reverse('network', args=[compute_id, data['name']])) | ||||
|                 else: | ||||
|                     for msg_err in form.errors.values(): | ||||
|  | @ -86,6 +95,7 @@ def network(request, compute_id, pool): | |||
|         state = conn.is_active() | ||||
|         device = conn.get_bridge_device() | ||||
|         autostart = conn.get_autostart() | ||||
|         net_mac = conn.get_network_mac() | ||||
|         net_forward = conn.get_network_forward() | ||||
|         dhcp_range_start = ipv4_dhcp_range_end = dict() | ||||
| 
 | ||||
|  | @ -152,7 +162,7 @@ def network(request, compute_id, pool): | |||
| 
 | ||||
|             try: | ||||
|                 ret_val = conn.modify_fixed_address(name, address, mac_duid, family) | ||||
|                 messages.success(request, "{} Fixed Address Operation Completed.".format(family)) | ||||
|                 messages.success(request, "{} Fixed Address Operation Completed.".format(family.upper())) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             except libvirtError as lib_err: | ||||
|                 error_messages.append(lib_err.message) | ||||
|  | @ -162,7 +172,7 @@ def network(request, compute_id, pool): | |||
|             ip = request.POST.get('address', '') | ||||
|             family = request.POST.get('family', 'ipv4') | ||||
|             conn.delete_fixed_address(ip, family) | ||||
|             messages.success(request, "{} Fixed Address is Deleted.".format(family)) | ||||
|             messages.success(request, "{} Fixed Address is Deleted.".format(family.upper())) | ||||
|             return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'modify_dhcp_range' in request.POST: | ||||
|             range_start = request.POST.get('range_start', '') | ||||
|  | @ -170,7 +180,7 @@ def network(request, compute_id, pool): | |||
|             family = request.POST.get('family', 'ipv4') | ||||
|             try: | ||||
|                 conn.modify_dhcp_range(range_start, range_end, family) | ||||
|                 messages.success(request, "{} DHCP Range is Changed.".format(family)) | ||||
|                 messages.success(request, "{} DHCP Range is Changed.".format(family.upper())) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             except libvirtError as lib_err: | ||||
|                 error_messages.append(lib_err.message) | ||||
|  |  | |||
							
								
								
									
										4
									
								
								static/js/Chart.bundle.min.js
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								static/js/Chart.bundle.min.js
									
										
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -7,14 +7,18 @@ from libvirt import VIR_NETWORK_UPDATE_COMMAND_ADD_LAST, VIR_NETWORK_UPDATE_COMM | |||
| from libvirt import VIR_NETWORK_UPDATE_AFFECT_LIVE, VIR_NETWORK_UPDATE_AFFECT_CONFIG | ||||
| 
 | ||||
| 
 | ||||
| def network_size(net, dhcp=None): | ||||
| def network_size(subnet, dhcp=None): | ||||
|     """ | ||||
|     Func return gateway, mask and dhcp pool. | ||||
|     """ | ||||
|     mask = IP(net).strNetmask() | ||||
|     addr = IP(net) | ||||
|     gateway = addr[1].strNormal() | ||||
|     dhcp_pool = [addr[2].strNormal(), addr[addr.len() - 2].strNormal()] | ||||
|     mask = IP(subnet).strNetmask() | ||||
|     addr = IP(subnet) | ||||
|     gateway = addr[1].strCompressed() | ||||
|     if addr.version() == 4: | ||||
|         dhcp_pool = [addr[2].strCompressed(), addr[addr.len() - 2].strCompressed()] | ||||
|     if addr.version() == 6: | ||||
|         mask = mask.lstrip('/') if '/' in mask else mask | ||||
|         dhcp_pool = [IP(addr[0].strCompressed() + hex(256)), IP(addr[0].strCompressed() + hex(512 - 1))] | ||||
|     if dhcp: | ||||
|         return gateway, mask, dhcp_pool | ||||
|     else: | ||||
|  | @ -30,15 +34,18 @@ class wvmNetworks(wvmConnect): | |||
|             net = self.get_network(network) | ||||
|             net_status = net.isActive() | ||||
|             net_bridge = net.bridgeName() | ||||
|             net_forwd = util.get_xml_path(net.XMLDesc(0), "/network/forward/@mode") | ||||
|             net_forward = util.get_xml_path(net.XMLDesc(0), "/network/forward/@mode") | ||||
|             networks.append({'name': network, 'status': net_status, | ||||
|                              'device': net_bridge, 'forward': net_forwd}) | ||||
|                              'device': net_bridge, 'forward': net_forward}) | ||||
|         return networks | ||||
| 
 | ||||
|     def define_network(self, xml): | ||||
|         self.wvm.networkDefineXML(xml) | ||||
| 
 | ||||
|     def create_network(self, name, forward, gateway, mask, dhcp, bridge, openvswitch, fixed=False): | ||||
|     def create_network(self, name, forward, | ||||
|                        ipv4, gateway, mask, dhcp4, | ||||
|                        ipv6, gateway6, prefix6, dhcp6, | ||||
|                        bridge, openvswitch, fixed=False): | ||||
|         xml = """ | ||||
|             <network> | ||||
|                 <name>%s</name>""" % name | ||||
|  | @ -53,19 +60,25 @@ class wvmNetworks(wvmConnect): | |||
|         if openvswitch is True: | ||||
|             xml += """<virtualport type='openvswitch'/>""" | ||||
|         if forward != 'bridge': | ||||
|             xml += """ | ||||
|                         <ip address='%s' netmask='%s'>""" % (gateway, mask) | ||||
|             if dhcp: | ||||
|                 xml += """<dhcp> | ||||
|                             <range start='%s' end='%s' />""" % (dhcp[0], dhcp[1]) | ||||
|                 if fixed: | ||||
|                     fist_oct = int(dhcp[0].strip().split('.')[3]) | ||||
|                     last_oct = int(dhcp[1].strip().split('.')[3]) | ||||
|                     for ip in range(fist_oct, last_oct + 1): | ||||
|                         xml += """<host mac='%s' ip='%s.%s' />""" % (util.randomMAC(), gateway[:-2], ip) | ||||
|                 xml += """</dhcp>""" | ||||
| 
 | ||||
|             xml += """</ip>""" | ||||
|             if ipv4: | ||||
|                 xml += """<ip address='%s' netmask='%s'>""" % (gateway, mask) | ||||
|                 if dhcp4: | ||||
|                     xml += """<dhcp> | ||||
|                                 <range start='%s' end='%s' />""" % (dhcp4[0], dhcp4[1]) | ||||
|                     if fixed: | ||||
|                         fist_oct = int(dhcp4[0].strip().split('.')[3]) | ||||
|                         last_oct = int(dhcp4[1].strip().split('.')[3]) | ||||
|                         for ip in range(fist_oct, last_oct + 1): | ||||
|                             xml += """<host mac='%s' ip='%s.%s' />""" % (util.randomMAC(), gateway[:-2], ip) | ||||
|                     xml += """</dhcp>""" | ||||
|                 xml += """</ip>""" | ||||
|             if ipv6: | ||||
|                 xml += """<ip family='ipv6' address='%s' prefix='%s'>""" % (gateway6, prefix6) | ||||
|                 if dhcp6: | ||||
|                     xml += """<dhcp> | ||||
|                                  <range start='%s' end='%s' />""" % (dhcp6[0], dhcp6[1]) | ||||
|                     xml += """</dhcp>""" | ||||
|                 xml += """</ip>""" | ||||
|         xml += """</network>""" | ||||
|         self.define_network(xml) | ||||
|         net = self.get_network(name) | ||||
|  | @ -119,7 +132,7 @@ class wvmNetwork(wvmConnect): | |||
|         ip_networks = dict() | ||||
|         xml = self._XMLDesc(0) | ||||
|         if util.get_xml_path(xml, "/network/ip") is None: | ||||
|             return None | ||||
|             return ip_networks | ||||
|         tree = etree.fromstring(xml) | ||||
|         ips = tree.findall('.ip') | ||||
|         for ip in ips: | ||||
|  | @ -144,6 +157,11 @@ class wvmNetwork(wvmConnect): | |||
|             ip_networks[family] = ret | ||||
|         return ip_networks | ||||
| 
 | ||||
|     def get_network_mac(self): | ||||
|         xml = self._XMLDesc(0) | ||||
|         mac = util.get_xml_path(xml, "/network/mac/@address") | ||||
|         return mac | ||||
| 
 | ||||
|     def get_network_forward(self): | ||||
|         xml = self._XMLDesc(0) | ||||
|         fw = util.get_xml_path(xml, "/network/forward/@mode") | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue