
networkxml.py was moved to xmlutils/network.py and it was also updated to use lxml.builder instead of plan text while generating the XML. Update the imports accordinly to this changes and also the test cases. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi/model/networks.py | 8 +-- src/kimchi/networkxml.py | 127 ----------------------------------------- src/kimchi/xmlutils/network.py | 123 +++++++++++++++++++++++++++++++++++++++ tests/test_networkxml.py | 27 +++++---- 4 files changed, 140 insertions(+), 145 deletions(-) delete mode 100644 src/kimchi/networkxml.py create mode 100644 src/kimchi/xmlutils/network.py diff --git a/src/kimchi/model/networks.py b/src/kimchi/model/networks.py index 92fae4d..6d21e9e 100644 --- a/src/kimchi/model/networks.py +++ b/src/kimchi/model/networks.py @@ -27,11 +27,12 @@ from xml.sax.saxutils import escape from kimchi import netinfo from kimchi import network as knetwork -from kimchi import networkxml from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import MissingParameter, NotFoundError, OperationFailed from kimchi.rollbackcontext import RollbackContext from kimchi.utils import kimchi_log, run_command +from kimchi.xmlutils.network import create_vlan_tagged_bridge_xml +from kimchi.xmlutils.network import to_network_xml from kimchi.xmlutils.utils import xpath_get_text @@ -100,7 +101,7 @@ class NetworksModel(object): self._set_network_bridge(params) params['name'] = escape(params['name']) - xml = networkxml.to_network_xml(**params) + xml = to_network_xml(**params) try: network = conn.networkDefineXML(xml.encode("utf-8")) @@ -206,8 +207,7 @@ class NetworksModel(object): # Truncate the interface name if it exceeds 8 characters to make sure # the length of bridge name is less than 15 (its maximum value). br_name = KIMCHI_BRIDGE_PREFIX + interface[-8:] + '-' + vlan_id - br_xml = networkxml.create_vlan_tagged_bridge_xml(br_name, interface, - vlan_id) + br_xml = create_vlan_tagged_bridge_xml(br_name, interface, vlan_id) conn = self.conn.get() if br_name in [net.bridgeName() for net in conn.listAllNetworks()]: diff --git a/src/kimchi/networkxml.py b/src/kimchi/networkxml.py deleted file mode 100644 index ff30f16..0000000 --- a/src/kimchi/networkxml.py +++ /dev/null @@ -1,127 +0,0 @@ -# -# Project Kimchi -# -# Copyright IBM, Corp. 2013-2014 -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -import ipaddr -import lxml.etree as ET - - -from lxml.builder import E - - -# FIXME, do not support ipv6 - -def _get_dhcp_xml(**kwargs): - """ - <dhcp> - <range start="192.168.122.100" end="192.168.122.254" /> - <host mac="00:16:3e:77:e2:ed" name="foo.test.com" ip="192.168.122.10" /> - <host mac="00:16:3e:3e:a9:1a" name="bar.test.com" ip="192.168.122.11" /> - </dhcp> - """ - xml = '' - dhcp_range = " <range start='%(start)s' end='%(end)s' />" - ipv4host = " <host mac='%(mac)s' name='%(name)s' ip='%(ip)s' />" - dhcp = [] - if 'range' in kwargs.keys(): - dhcp.append(dhcp_range % kwargs['range']) - if 'hosts' in kwargs.keys(): - dhcp.extend([ipv4host % host for host in kwargs['hosts']]) - if dhcp: - xml = "\n".join(["<dhcp>"] + dhcp + ["</dhcp>"]) - return xml - - -def _get_ip_xml(**kwargs): - """ - <ip address="192.168.152.1" netmask="255.255.255.0"> - <dhcp> - <range start="192.168.152.2" end="192.168.152.254" /> - </dhcp> - </ip> - """ - xml = "" - if 'net' in kwargs.keys(): - net = ipaddr.IPNetwork(kwargs['net']) - address = str(net.ip) - netmask = str(net.netmask) - dhcp_params = kwargs.get('dhcp', {}) - dhcp = _get_dhcp_xml(**dhcp_params) - xml = """ - <ip address='%s' netmask='%s'>" - %s - </ip>""" % (address, netmask, dhcp) - return xml - - -def _get_forward_xml(**kwargs): - """ - <forward mode='hostdev' dev='eth0' managed='yes'> - </forward> - """ - - if "mode" in kwargs.keys() and kwargs['mode'] is None: - return "" - mode = " mode='%s'" % kwargs['mode'] if 'mode' in kwargs.keys() else "" - dev = " dev='%s'" % kwargs['dev'] if 'dev' in kwargs.keys() else "" - managed = (" managed='%s'" % kwargs['managed'] - if 'managed' in kwargs.keys() else "") - xml = """ - <forward %s%s%s> - </forward> - """ % (mode, dev, managed) - return xml - - -def to_network_xml(**kwargs): - - params = {'name': kwargs['name']} - # None means is Isolated network, {} means default mode nat - forward = kwargs.get('forward', {"mode": None}) - ip = {'net': kwargs['net']} if 'net' in kwargs else {} - ip['dhcp'] = kwargs.get('dhcp', {}) - bridge = kwargs.get('bridge') - params = {'name': kwargs['name'], - 'forward': _get_forward_xml(**forward), - 'bridge': "<bridge name='%s' />" % bridge if bridge else "", - 'ip': _get_ip_xml(**ip)} - - xml = """ - <network> - <name>%(name)s</name> - %(bridge)s - %(forward)s - %(ip)s - </network> - """ % params - return xml - - -def create_vlan_tagged_bridge_xml(bridge, interface, vlan_id): - vlan = E.vlan(E.interface(name=interface)) - vlan.set('tag', vlan_id) - m = E.interface( - E.start(mode='onboot'), - E.bridge( - E.interface( - vlan, - type='vlan', - name='.'.join([interface, vlan_id]))), - type='bridge', - name=bridge) - return ET.tostring(m) diff --git a/src/kimchi/xmlutils/network.py b/src/kimchi/xmlutils/network.py new file mode 100644 index 0000000..e78779c --- /dev/null +++ b/src/kimchi/xmlutils/network.py @@ -0,0 +1,123 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2014 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import ipaddr +import lxml.etree as ET + +from lxml.builder import E + + +# FIXME, do not support ipv6 +def _get_dhcp_elem(**kwargs): + """ + <dhcp> + <range start="192.168.122.100" end="192.168.122.254" /> + <host mac="00:16:3e:77:e2:ed" name="foo.test.com" ip="192.168.122.10" /> + <host mac="00:16:3e:3e:a9:1a" name="bar.test.com" ip="192.168.122.11" /> + </dhcp> + """ + dhcp = E.dhcp() + if 'range' in kwargs.keys(): + dhcp_range = E.range(start=kwargs['range']['start'], + end=kwargs['range']['end']) + dhcp.append(dhcp_range) + + if 'hosts' in kwargs.keys(): + for host in kwargs['hosts']: + dhcp.append(E.host(mac=host['mac'], + name=host['name'], + ip=host['ip'])) + + return dhcp if len(dhcp) > 0 else None + + +def _get_ip_elem(**kwargs): + """ + <ip address="192.168.152.1" netmask="255.255.255.0"> + <dhcp> + <range start="192.168.152.2" end="192.168.152.254" /> + </dhcp> + </ip> + """ + if 'net' not in kwargs.keys(): + return None + + net = ipaddr.IPNetwork(kwargs['net']) + ip = E.ip(address=str(net.ip), netmask=str(net.netmask)) + + dhcp_params = kwargs.get('dhcp', {}) + dhcp = _get_dhcp_elem(**dhcp_params) + if dhcp is not None: + ip.append(dhcp) + + return ip + + +def _get_forward_elem(**kwargs): + """ + <forward mode='hostdev' dev='eth0' managed='yes'> + </forward> + """ + if "mode" in kwargs.keys() and kwargs['mode'] is None: + return None + + forward = E.forward() + if 'mode' in kwargs.keys(): + forward.set('mode', kwargs['mode']) + + if 'dev' in kwargs.keys(): + forward.set('dev', kwargs['dev']) + + if 'managed' in kwargs.keys(): + forward.set('managed', kwargs['managed']) + + return forward + + +def to_network_xml(**kwargs): + network = E.network(E.name(kwargs['name'])) + bridge = kwargs.get('bridge') + if bridge: + network.append(E.bridge(name=bridge)) + + # None means is Isolated network, {} means default mode nat + params = kwargs.get('forward', {"mode": None}) + forward = _get_forward_elem(**params) + if forward is not None: + network.append(forward) + + if 'net' in kwargs: + network.append(_get_ip_elem(**kwargs)) + + return ET.tostring(network) + + +def create_vlan_tagged_bridge_xml(bridge, interface, vlan_id): + vlan = E.vlan(E.interface(name=interface)) + vlan.set('tag', vlan_id) + m = E.interface( + E.start(mode='onboot'), + E.bridge( + E.interface( + vlan, + type='vlan', + name='.'.join([interface, vlan_id]))), + type='bridge', + name=bridge) + return ET.tostring(m) diff --git a/tests/test_networkxml.py b/tests/test_networkxml.py index 674008d..3706a71 100644 --- a/tests/test_networkxml.py +++ b/tests/test_networkxml.py @@ -19,12 +19,11 @@ import ipaddr import unittest +import lxml.etree as ET - -import kimchi.networkxml as nxml import utils - +from kimchi.xmlutils import network as nxml from kimchi.xmlutils.utils import xpath_get_text @@ -42,18 +41,18 @@ class NetworkXmlTests(unittest.TestCase): "ip": "192.168.122.11"} params = {} - xml = nxml._get_dhcp_xml(**params) - self.assertEquals("", xml) + dhcp = nxml._get_dhcp_elem(**params) + self.assertEquals(None, dhcp) params["range"] = dhcp_range - xml = nxml._get_dhcp_xml(**params) + xml = ET.tostring(nxml._get_dhcp_elem(**params)) start = xpath_get_text(xml, "/dhcp/range/@start") end = xpath_get_text(xml, "/dhcp/range/@end") self.assertEquals(dhcp_range['start'], start[0]) self.assertEquals(dhcp_range['end'], end[0]) params["hosts"] = [host1, host2] - xml = nxml._get_dhcp_xml(**params) + xml = ET.tostring(nxml._get_dhcp_elem(**params)) ip = xpath_get_text(xml, "/dhcp/host/@ip") self.assertEquals(ip, [host1['ip'], host2['ip']]) @@ -64,12 +63,12 @@ class NetworkXmlTests(unittest.TestCase): dhcp_range = {"start": "192.168.122.100", "end": "192.168.122.254"} params = {} - xml = nxml._get_dhcp_xml(**params) - self.assertEquals("", xml) + dhcp = nxml._get_dhcp_elem(**params) + self.assertEquals(None, dhcp) params["net"] = "192.168.122.0/255.255.255.0" params["dhcp"] = {'range': dhcp_range} - xml = nxml._get_ip_xml(**params) + xml = ET.tostring(nxml._get_ip_elem(**params)) start = xpath_get_text(xml, "/ip/dhcp/range/@start")[0] end = xpath_get_text(xml, "/ip/dhcp/range/@end")[0] self.assertEquals(dhcp_range['start'], start) @@ -83,7 +82,7 @@ class NetworkXmlTests(unittest.TestCase): # test _get_ip_xml can accepts strings: '192.168.122.0/24', # which is same as "192.168.122.0/255.255.255.0" params["net"] = "192.168.122.0/24" - xml = nxml._get_ip_xml(**params) + xml = ET.tostring(nxml._get_ip_elem(**params)) netmask = xpath_get_text(xml, "/ip/@netmask")[0] self.assertEquals(netmask, str(ipaddr.IPNetwork(params["net"]).netmask)) @@ -94,12 +93,12 @@ class NetworkXmlTests(unittest.TestCase): """ params = {"mode": None} - xml = nxml._get_forward_xml(**params) - self.assertEquals("", xml) + forward = nxml._get_forward_elem(**params) + self.assertEquals(None, forward) params["mode"] = 'nat' params["dev"] = 'eth0' - xml = nxml._get_forward_xml(**params) + xml = ET.tostring(nxml._get_forward_elem(**params)) mode = xpath_get_text(xml, "/forward/@mode")[0] dev = xpath_get_text(xml, "/forward/@dev")[0] self.assertEquals(params['mode'], mode) -- 1.9.3