Skip to content

Commit

Permalink
Merge pull request avocado-framework#3440 from chloerh/network_xml
Browse files Browse the repository at this point in the history
Update class of NetworkXMLBase and add unittest
  • Loading branch information
dzhengfy authored Jun 29, 2022
2 parents f010886 + 707e54d commit fc1b6a0
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 51 deletions.
4 changes: 2 additions & 2 deletions selftests/unit/test_libvirt_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ def _from_scratch(self):
ipxml = network_xml.IPXML()
ipxml.address = ('address_test')
ipxml.netmask = ('netmask_test')
netxml.ip = ipxml
netxml.ips = [ipxml]
return netxml

def test_getters(self):
Expand All @@ -747,7 +747,7 @@ def test_valid_xml(self):

def test_ip_getter(self):
netxml = self._from_scratch()
ipxml = netxml.ip
ipxml = netxml.ips[0]
self.assertEqual(ipxml.address, 'address_test')
self.assertEqual(ipxml.netmask, 'netmask_test')

Expand Down
102 changes: 61 additions & 41 deletions virttest/libvirt_xml/network_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,8 @@ class NetworkXMLBase(base.LibvirtXMLBase):
"""

__slots__ = ('name', 'uuid', 'bridge', 'defined', 'active',
'autostart', 'persistent', 'forward', 'mac', 'ip',
'bandwidth_inbound', 'bandwidth_outbound', 'portgroup',
'autostart', 'persistent', 'forward', 'mac', 'ips',
'bandwidth_inbound', 'bandwidth_outbound', 'portgroups',
'dns', 'domain_name', 'nat_port', 'forward_interface',
'routes', 'virtualport_type', 'vf_list', 'driver', 'pf',
'mtu', 'connection', 'port', 'nat_attrs')
Expand All @@ -448,6 +448,10 @@ def __init__(self, virsh_instance=base.virsh):
tag_name='uuid')
accessors.XMLAttribute('mac', self, parent_xpath='/',
tag_name='mac', attribute='address')
accessors.XMLElementList('ips', self, parent_xpath='/',
marshal_from=self.marshal_from_ips,
marshal_to=self.marshal_to_ips,
has_subclass=True)
accessors.XMLElementDict('forward', self, parent_xpath='/',
tag_name='forward')
accessors.XMLElementList('forward_interface', self, parent_xpath='/forward',
Expand Down Expand Up @@ -479,6 +483,10 @@ def __init__(self, virsh_instance=base.virsh):
tag_name='mtu', attribute='size')
accessors.XMLAttribute('domain_name', self, parent_xpath='/',
tag_name='domain', attribute='name')
accessors.XMLElementList('portgroups', self, parent_xpath='/',
marshal_from=self.marshal_from_portgroups,
marshal_to=self.marshal_to_portgroups,
has_subclass=True)
accessors.XMLElementNest('dns', self, parent_xpath='/',
tag_name='dns', subclass=DNSXML,
subclass_dargs={
Expand Down Expand Up @@ -617,17 +625,7 @@ def get_persistent(self):
set_persistent = set_defined
del_persistent = del_defined

def get_ip(self):
xmltreefile = self.__dict_get__('xml')
try:
ip_root = xmltreefile.reroot('/ip')
except KeyError as detail:
raise xcepts.LibvirtXMLError(detail)
ipxml = IPXML(virsh_instance=self.__dict_get__('virsh'))
ipxml.xmltreefile = ip_root
return ipxml

def set_ip(self, value):
def add_ip(self, value):
if not issubclass(type(value), IPXML):
raise xcepts.LibvirtXMLError("value must be a IPXML or subclass")
xmltreefile = self.__dict_get__('xml')
Expand All @@ -636,13 +634,6 @@ def set_ip(self, value):
root.append(value.xmltreefile.getroot())
xmltreefile.write()

def del_ip(self):
xmltreefile = self.__dict_get__('xml')
element = xmltreefile.find('/ip')
if element is not None:
xmltreefile.remove(element)
xmltreefile.write()

def del_element(self, element='', index=0):
"""
Delete element from network xml
Expand All @@ -660,28 +651,57 @@ def del_element(self, element='', index=0):
xmltreefile.remove(del_elem)
xmltreefile.write()

def get_portgroup(self):
try:
portgroup_root = self.xmltreefile.reroot('/portgroup')
except KeyError as detail:
raise xcepts.LibvirtXMLError(detail)
portgroup_xml = PortgroupXML(virsh_instance=self.__dict_get__('virsh'))
portgroup_xml.xmltreefile = portgroup_root
return portgroup_xml

def set_portgroup(self, value):
if not issubclass(type(value), PortgroupXML):
raise xcepts.LibvirtXMLError("value must be a PortgroupXML"
"instance or subclass.")
root = self.xmltreefile.getroot()
root.append(value.xmltreefile.getroot())
self.xmltreefile.write()
@staticmethod
def marshal_from_ips(item, index, libvirtxml):
"""
Convert an xml object to ip tag and xml element.
"""
if isinstance(item, IPXML):
return 'ip', item
elif isinstance(item, dict):
ip = IPXML()
ip.setup_attrs(**item)
return 'ip', ip
else:
raise xcepts.LibvirtXMLError("Expected a list of IPXML "
"instances, not a %s" % str(item))

@staticmethod
def marshal_to_ips(tag, new_treefile, index, libvirtxml):
"""
Convert a ip tag xml element to an object of IPXML.
"""
if tag != 'ip':
return None # Don't convert this item
newone = IPXML(virsh_instance=libvirtxml.virsh)
newone.xmltreefile = new_treefile
return newone

def del_portgroup(self):
element = self.xmltreefile.find("/portgroup")
if element is not None:
self.xmltreefile.remove(element)
self.xmltreefile.write()
@staticmethod
def marshal_from_portgroups(item, index, libvirtxml):
"""
Convert an xml object to portgroup tag and xml element.
"""
if isinstance(item, PortgroupXML):
return 'portgroup', item
elif isinstance(item, dict):
portgroup = PortgroupXML()
portgroup.setup_attrs(**item)
return 'portgroup', portgroup
else:
raise xcepts.LibvirtXMLError("Expected a list of PortgroupXML "
"instances, not a %s" % str(item))

@staticmethod
def marshal_to_portgroups(tag, new_treefile, index, libvirtxml):
"""
Convert a portgroup tag xml element to an object of PortgroupXML.
"""
if tag != 'portgroup':
return None # Don't convert this item
newone = PortgroupXML(virsh_instance=libvirtxml.virsh)
newone.xmltreefile = new_treefile
return newone

def get_interface_connection(self):
try:
Expand Down
3 changes: 2 additions & 1 deletion virttest/libvirt_xml/vm_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .. import xml_utils
from .. import utils_misc
from ..libvirt_xml import base, accessors, xcepts
from ..libvirt_xml.base import LibvirtXMLBase
from ..libvirt_xml.devices import librarian

LOG = logging.getLogger('avocado.' + __name__)
Expand Down Expand Up @@ -56,7 +57,7 @@ def by_device_tag(self, tag):
return result


class VMXMLBase(base.LibvirtXMLBase):
class VMXMLBase(LibvirtXMLBase):

"""
Accessor methods for VMXML class properties (items in __slots__)
Expand Down
104 changes: 104 additions & 0 deletions virttest/unittests/libvirt_xml/test_network_xml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import unittest

from virttest.libvirt_xml import network_xml

# TODO: The current test doesn't cover all attributes of a network xml.
# It needs update later
XML = '''
<network>
<name>testnet</name>
<forward mode='bridge'/>
<bridge name='br0'/>
<port isolated='yes'/>
<ip address="192.168.122.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.122.2" end="192.168.122.254"/>
</dhcp>
</ip>
<ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" netmask="255.255.255.0">
<dhcp>
<host name="paul" ip="2001:db8:ca2:2:3::1"/>
<host id="0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66" ip="2001:db8:ca2:2:3::2"/>
<host id="0:3:0:1:0:16:3e:11:22:33" name="ralph" ip="2001:db8:ca2:2:3::3"/>
<host id="0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63"
name="badbob" ip="2001:db8:ca2:2:3::4"/>
</dhcp>
</ip>
<portgroup name='engineering' default='yes'>
<virtualport type='802.1Qbh'/>
<bandwidth>
<inbound average='1000' peak='5000' burst='5120'/>
<outbound average='1000' peak='5000' burst='5120'/>
</bandwidth>
</portgroup>
<portgroup name='sales' trustGuestRxFilters='no'>
<virtualport type='802.1Qbh'/>
<bandwidth>
<inbound average='500' peak='2000' burst='2560'/>
<outbound average='128' peak='256' burst='256'/>
</bandwidth>
</portgroup>
</network>
'''

network_attrs = {
'bridge': {'name': 'br0'},
'forward': {'mode': 'bridge'},
'ips': [{'address': '192.168.122.1',
'dhcp_ranges': {'attrs': {'end': '192.168.122.254',
'start': '192.168.122.2'}},
'netmask': '255.255.255.0'},
{'address': '2001:db8:ca2:2::1',
'family': 'ipv6',
'hosts': [{'attrs': {'ip': '2001:db8:ca2:2:3::1', 'name': 'paul'}},
{'attrs': {'id': '0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66',
'ip': '2001:db8:ca2:2:3::2'}},
{'attrs': {'id': '0:3:0:1:0:16:3e:11:22:33',
'ip': '2001:db8:ca2:2:3::3',
'name': 'ralph'}},
{'attrs': {'id': '0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63',
'ip': '2001:db8:ca2:2:3::4',
'name': 'badbob'}}],
'netmask': '255.255.255.0',
'prefix': '64'}],
'name': 'testnet',
'port': {'isolated': 'yes'},
'portgroups': [{'bandwidth_inbound': {'average': '1000',
'burst': '5120',
'peak': '5000'},
'bandwidth_outbound': {'average': '1000',
'burst': '5120',
'peak': '5000'},
'default': 'yes',
'name': 'engineering',
'virtualport_type': '802.1Qbh'},
{'bandwidth_inbound': {'average': '500',
'burst': '2560',
'peak': '2000'},
'bandwidth_outbound': {'average': '128',
'burst': '256',
'peak': '256'},
'name': 'sales',
'virtualport_type': '802.1Qbh'}]
}


class TestNetworkXML(unittest.TestCase):

def test_setup_network_default(self):
network = network_xml.NetworkXML()
network.setup_attrs(**network_attrs)

cmp_device = network_xml.NetworkXML()
cmp_device.xml = XML.strip()
self.assertEqual(network, cmp_device)

def test_fetch_attrs_network_default(self):
network = network_xml.NetworkXML()
network.xml = XML.strip()
fetched_attrs = network.fetch_attrs()
self.assertEqual(network_attrs, fetched_attrs)


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion virttest/utils_libvirt/libvirt_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def modify_network_xml(net_dict, testnet_xml):
if del_nat is True:
testnet_xml.del_nat_attrs()
if del_ip:
testnet_xml.del_ip()
testnet_xml.del_ips()
if dns_txt:
dns_dict = {"txt": ast.literal_eval(dns_txt)}
dns_obj = testnet_xml.new_dns(**dns_dict)
Expand Down
14 changes: 8 additions & 6 deletions virttest/utils_test/libvirt.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def create_network_xml_with_dhcp(self):
ran = network_xml.RangeXML()
ran.attrs = {'start': dhcp_start, 'end': dhcp_end}
ip.dhcp_ranges = ran
net_xml.ip = ip
net_xml.ips = [ip]
net_xml.bridge = {'name': self.kwargs.get('br_name'), 'stp': 'on', 'delay': '0'}
return net_xml

Expand All @@ -133,7 +133,7 @@ def create_vnet_xml(self):
ran = network_xml.RangeXML()
ran.attrs = {'start': dhcp_start, 'end': dhcp_end}
ip.dhcp_ranges = ran
net_xml.ip = ip
net_xml.ips = [ip]
return address, net_xml

def create_macvtap_xml(self):
Expand Down Expand Up @@ -1879,7 +1879,7 @@ def create_net_xml(net_name, params):
if not virsh.net_info(net_name, ignore_status=True).exit_status:
# Edit an existed network
netxml = network_xml.NetworkXML.new_from_net_dumpxml(net_name)
netxml.del_ip()
netxml.del_ips()
else:
netxml = network_xml.NetworkXML(net_name)
if disable_dns:
Expand Down Expand Up @@ -1950,7 +1950,7 @@ def create_net_xml(net_name, params):
host_xml_6.attrs = {"name": guest_name,
"ip": guest_ipv6}
ipxml.hosts = [host_xml_6]
netxml.set_ip(ipxml)
netxml.add_ip(ipxml)
if net_ip_address:
ipxml = network_xml.IPXML(net_ip_address,
net_ip_netmask)
Expand All @@ -1970,7 +1970,7 @@ def create_net_xml(net_name, params):
"ip": guest_ipv4,
"mac": guest_mac}
ipxml.hosts = [host_xml_4]
netxml.set_ip(ipxml)
netxml.add_ip(ipxml)
if routes:
netxml.routes = [ast.literal_eval(x) for x in routes]
if pg_name:
Expand All @@ -1983,6 +1983,7 @@ def create_net_xml(net_name, params):
pg_bandwidth_outbound = params.get(
"portgroup_bandwidth_outbound", "").split()
pg_vlan = params.get("portgroup_vlan", "").split()
pgs = []
for i in range(len(pg_name)):
pgxml = network_xml.PortgroupXML()
pgxml.name = pg_name[i]
Expand All @@ -1998,7 +1999,8 @@ def create_net_xml(net_name, params):
pg_bandwidth_outbound[i])
if len(pg_vlan) > i:
pgxml.vlan_tag = ast.literal_eval(pg_vlan[i])
netxml.set_portgroup(pgxml)
pgs.append(pgxml)
netxml.portgroups = pgs

vf_list = ast.literal_eval(vf_list_attrs)
if vf_list:
Expand Down

0 comments on commit fc1b6a0

Please sign in to comment.