
It is the first step to have xmlutils/disk.py holding all the disk XML manipulation. So we can reuse the same function on vmtemplate.py to build the guest XML. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi/model/vmstorages.py | 49 ++++------------------------ src/kimchi/xmlutils/disk.py | 73 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 43 deletions(-) create mode 100644 src/kimchi/xmlutils/disk.py diff --git a/src/kimchi/model/vmstorages.py b/src/kimchi/model/vmstorages.py index 055aa50..808b3d7 100644 --- a/src/kimchi/model/vmstorages.py +++ b/src/kimchi/model/vmstorages.py @@ -18,14 +18,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os -import socket import stat import string -import urlparse -import lxml.etree as ET from lxml import etree -from lxml.builder import E from kimchi.exception import InvalidOperation, InvalidParameter, NotFoundError from kimchi.exception import OperationFailed @@ -35,7 +31,7 @@ from kimchi.model.utils import get_vm_config_flag from kimchi.utils import check_url_path from kimchi.osinfo import lookup from kimchi.vmdisks import get_device_xml, get_vm_disk, get_vm_disk_list -from kimchi.vmdisks import DEV_TYPE_SRC_ATTR_MAP +from kimchi.xmlutils.disk import get_disk_xml HOTPLUG_TYPE = ['scsi', 'virtio'] PREFIX_MAP = {'ide': 'hd', 'virtio': 'vd', 'scsi': 'sd'} @@ -49,39 +45,6 @@ def _get_device_bus(dev_type, dom): return lookup(distro, version)[dev_type+'_bus'] -def _get_storage_xml(params, ignore_source=False): - src_type = params.get('src_type') - disk = E.disk(type=src_type, device=params.get('type')) - disk.append(E.driver(name='qemu', type=params['format'])) - - disk.append(E.target(dev=params.get('dev'), bus=params['bus'])) - if params.get('address'): - # ide disk target id is always '0' - disk.append(E.address( - type='drive', controller=params['address']['controller'], - bus=params['address']['bus'], target='0', - unit=params['address']['unit'])) - - if ignore_source: - return ET.tostring(disk) - - # Working with url paths - if src_type == 'network': - output = urlparse.urlparse(params.get('path')) - port = str(output.port or socket.getservbyname(output.scheme)) - host = E.host(name=output.hostname, port=port) - source = E.source(protocol=output.scheme, name=output.path) - source.append(host) - disk.append(source) - else: - # Fixing source attribute - source = E.source() - source.set(DEV_TYPE_SRC_ATTR_MAP[src_type], params.get('path')) - disk.append(source) - - return ET.tostring(disk) - - def _check_path(path): if check_url_path(path): src_type = 'network' @@ -164,14 +127,14 @@ class VMStoragesModel(object): {"format": vol_info['format'], "type": params['type']}) params['path'] = vol_info['path'] - params['src_type'] = _check_path(params['path']) + if (params['bus'] not in HOTPLUG_TYPE and DOM_STATE_MAP[dom.info()[0]] != 'shutoff'): raise InvalidOperation('KCHVMSTOR0011E') params.update(self._get_available_bus_address(params['bus'], vm_name)) # Add device to VM - dev_xml = _get_storage_xml(params) + dev_xml = get_disk_xml(_check_path(params['path']), params) try: conn = self.conn.get() dom = conn.lookupByName(vm_name) @@ -234,10 +197,10 @@ class VMStorageModel(object): def update(self, vm_name, dev_name, params): path = params.get('path') if path and len(path) != 0: - params['src_type'] = _check_path(path) + src_type = _check_path(path) ignore_source = False else: - params['src_type'] = 'file' + src_type = 'file' ignore_source = True dom = VMModel.get_vm(vm_name, self.conn) @@ -245,8 +208,8 @@ class VMStorageModel(object): if dev_info['type'] != 'cdrom': raise InvalidOperation("KCHVMSTOR0006E") dev_info.update(params) - xml = _get_storage_xml(dev_info, ignore_source) + xml = get_disk_xml(src_type, dev_info, ignore_source) try: dom.updateDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: diff --git a/src/kimchi/xmlutils/disk.py b/src/kimchi/xmlutils/disk.py new file mode 100644 index 0000000..8c64ff4 --- /dev/null +++ b/src/kimchi/xmlutils/disk.py @@ -0,0 +1,73 @@ +# +# 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 lxml.etree as ET +import socket +import urlparse + +from lxml.builder import E + +DEV_TYPE_SRC_ATTR_MAP = {'file': 'file', 'block': 'dev'} + + +def get_disk_xml(src_type, params, ignore_src=False): + """ + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + + [source XML according to src_type] + + <target dev='%(dev)s' bus='%(bus)s'/> + <readonly/> + </disk> + """ + disk = E.disk(type=src_type, device=params['type']) + disk.append(E.driver(name='qemu', type=params['format'])) + disk.append(E.target(dev=params['dev'], bus=params['bus'])) + + if params.get('address'): + # ide disk target id is always '0' + disk.append(E.address( + type='drive', controller=params['address']['controller'], + bus=params['address']['bus'], target='0', + unit=params['address']['unit'])) + + if ignore_src: + return ET.tostring(disk, encoding='utf-8', pretty_print=True) + + if src_type == 'network': + """ + <source protocol='%(protocol)s' name='%(url_path)s'> + <host name='%(hostname)s' port='%(port)s'/> + </source> + """ + output = urlparse.urlparse(params['path']) + port = str(output.port or socket.getservbyname(output.scheme)) + + source = E.source(protocol=output.scheme, name=output.path) + source.append(E.host(name=output.hostname, port=port)) + else: + """ + <source file='%(src)s' /> + """ + source = E.source() + source.set(DEV_TYPE_SRC_ATTR_MAP[src_type], params['path']) + + disk.append(source) + return ET.tostring(disk, encoding='utf-8', pretty_print=True) -- 1.9.3