[Kimchi-devel] [PATCH] Choose available address for ide disk

Aline Manera alinefm at linux.vnet.ibm.com
Mon Apr 14 15:45:32 UTC 2014


Reviewed-by: Aline Manera <alinefm at linux.vnet.ibm.com>

On 04/11/2014 12:00 AM, lvroyce at linux.vnet.ibm.com wrote:
> From: Royce Lv <lvroyce at linux.vnet.ibm.com>
>
> Tested:
>   1.make check
>   2.adding more than 4 cdroms report error
>   3.less than 4 cdroms successful boot and see all cdroms.
>   4.When a vm does not have cdrom, adding succeed.
>
> When we only assign source and target type, bus information,
> libvirt may generate another controller for ide disk appending,
> this will be conflict with libvirt's limitation of 1 ide controller.
> This patch choose available bus_id and unit_id for ide disk
> to make sure we can reach the limit of 4 ide devices per vm.
> Address of 4 ide devices are:
>    <address type='drive' controller='0' bus='1' target='0' unit='1'/>
>    <address type='drive' controller='0' bus='0' target='0' unit='1'/>
>    <address type='drive' controller='0' bus='0' target='0' unit='0'/>
>    <address type='drive' controller='0' bus='1' target='0' unit='0'/>
>
> Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
> ---
>   src/kimchi/i18n.py             |  1 +
>   src/kimchi/model/vmstorages.py | 58 ++++++++++++++++++++++++++++++++----------
>   2 files changed, 45 insertions(+), 14 deletions(-)
>
> diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
> index 86ab5d6..2443b3e 100644
> --- a/src/kimchi/i18n.py
> +++ b/src/kimchi/i18n.py
> @@ -230,6 +230,7 @@ messages = {
>       "KCHCDROM0011E": _("Do not support guest CDROM hot plug attachment"),
>       "KCHCDROM0012E": _("Specify type and path to add a new virtual machine disk"),
>       "KCHCDROM0013E": _("Specify path to update virtual machine disk"),
> +    "KCHCDROM0014E": _("Controller type %(type)s limitation of %(limit)s devices reached"),
>
>       "KCHREPOS0001E": _("YUM Repository ID must be one word only string."),
>       "KCHREPOS0002E": _("Repository URL must be an http://, ftp:// or file:// URL."),
> diff --git a/src/kimchi/model/vmstorages.py b/src/kimchi/model/vmstorages.py
> index 3b5f99e..1cffa84 100644
> --- a/src/kimchi/model/vmstorages.py
> +++ b/src/kimchi/model/vmstorages.py
> @@ -37,6 +37,16 @@ DEV_TYPE_SRC_ATTR_MAP = {'file': 'file',
>                            'block': 'dev'}
>
>
> +def _get_device_xml(dom, dev_name):
> +    # Get VM xml and then devices xml
> +    xml = dom.XMLDesc(0)
> +    devices = objectify.fromstring(xml).devices
> +    disk = devices.xpath("./disk/target[@dev='%s']/.." % dev_name)
> +    if not disk:
> +        return None
> +    return disk[0]
> +
> +
>   def _get_storage_xml(params):
>       src_type = params.get('src_type')
>       disk = E.disk(type=src_type, device=params.get('type'))
> @@ -56,6 +66,12 @@ def _get_storage_xml(params):
>           disk.append(source)
>
>       disk.append(E.target(dev=params.get('dev'), bus=params.get('bus', 'ide')))
> +    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']))
>       return ET.tostring(disk)
>
>
> @@ -89,6 +105,29 @@ class VMStoragesModel(object):
>       def __init__(self, **kargs):
>           self.conn = kargs['conn']
>
> +    def _get_available_ide_address(self, vm_name):
> +        # libvirt limitation of just 1 ide controller
> +        # each controller have at most 2 buses and each bus 2 units.
> +        dom = VMModel.get_vm(vm_name, self.conn)
> +        disks = self.get_list(vm_name)
> +        valid_id = [('0', '0'), ('0', '1'), ('1', '0'), ('1', '1')]
> +        controller_id = '0'
> +        for dev_name in disks:
> +            disk = _get_device_xml(dom, dev_name)
> +            if disk.target.attrib['bus'] == 'ide':
> +                controller_id = disk.address.attrib['controller']
> +                bus_id = disk.address.attrib['bus']
> +                unit_id = disk.address.attrib['unit']
> +                if (bus_id, unit_id) in valid_id:
> +                    valid_id.remove((bus_id, unit_id))
> +                    continue
> +        if not valid_id:
> +            raise OperationFailed('KCHCDROM0014E', {'type': 'ide', 'limit': 4})
> +        else:
> +            address = {'controller': controller_id,
> +                       'bus': valid_id[0][0], 'unit': valid_id[0][1]}
> +            return dict(address=address)
> +
>       def create(self, vm_name, params):
>           dom = VMModel.get_vm(vm_name, self.conn)
>           if DOM_STATE_MAP[dom.info()[0]] != 'shutoff':
> @@ -109,8 +148,7 @@ class VMStoragesModel(object):
>           path = params['path']
>           params['src_type'] = _check_cdrom_path(path)
>
> -        # Check if path is an url
> -
> +        params.update(self._get_available_ide_address(vm_name))
>           # Add device to VM
>           dev_xml = _get_storage_xml(params)
>           try:
> @@ -147,19 +185,10 @@ class VMStorageModel(object):
>       def __init__(self, **kargs):
>           self.conn = kargs['conn']
>
> -    def _get_device_xml(self, vm_name, dev_name):
> -        # Get VM xml and then devices xml
> -        dom = VMModel.get_vm(vm_name, self.conn)
> -        xml = dom.XMLDesc(0)
> -        devices = objectify.fromstring(xml).devices
> -        disk = devices.xpath("./disk/target[@dev='%s']/.." % dev_name)
> -        if not disk:
> -            return None
> -        return disk[0]
> -
>       def lookup(self, vm_name, dev_name):
>           # Retrieve disk xml and format return dict
> -        disk = self._get_device_xml(vm_name, dev_name)
> +        dom = VMModel.get_vm(vm_name, self.conn)
> +        disk = _get_device_xml(dom, dev_name)
>           if disk is None:
>               raise NotFoundError("KCHCDROM0007E", {'dev_name': dev_name,
>                                                     'vm_name': vm_name})
> @@ -188,7 +217,8 @@ class VMStorageModel(object):
>
>       def delete(self, vm_name, dev_name):
>           # Get storage device xml
> -        disk = self._get_device_xml(vm_name, dev_name)
> +        dom = VMModel.get_vm(vm_name, self.conn)
> +        disk = _get_device_xml(dom, dev_name)
>           if disk is None:
>               raise NotFoundError("KCHCDROM0007E",
>                                   {'dev_name': dev_name,




More information about the Kimchi-devel mailing list