From: Royce Lv <lvroyce(a)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.
Now when just pass 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 cdroms per vm.
Signed-off-by: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
---
src/kimchi/i18n.py | 1 +
src/kimchi/model/vmstorages.py | 56 +++++++++++++++++++++++++++++++-----------
2 files changed, 43 insertions(+), 14 deletions(-)
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 86ab5d6..4ca83d9 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 %(limit)s
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..b3f22db 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'):
+ print params['address']
+ 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,27 @@ class VMStoragesModel(object):
def __init__(self, **kargs):
self.conn = kargs['conn']
+ def _get_available_ide_address(self, vm_name):
+ 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 +146,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 +183,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 +215,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,
--
1.8.3.2