On 05/02/2015 08:09, gouzongmei(a)163.com wrote:
From: Zongmei Gou <gouzongmei(a)163.com>
Deactive logical pool cause vm failed to start while storage of the vm is in this logical
pool.
Storage pool's "deactive" action call libvirt
"StoragePoolDestroy" function which causes different result on different pool
type.Once the pool is destroyed, the 'dir' type pool remains its target path and
images while the 'logical' type pool deletes its target path and images.
This patch make deactive logical pool action failed while exists vm(s) linked to this
pool.
---
src/kimchi/i18n.py | 1 +
src/kimchi/model/storagepools.py | 28 ++++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 4ab08d1..08bfe38 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -188,6 +188,7 @@ messages = {
"KCHPOOL0035E": _("Unable to delete pool %(name)s as it is
associated with some templates"),
"KCHPOOL0036E": _("A volume group named '%(name)s' already
exists. Please, choose another name to create the logical pool."),
"KCHPOOL0037E": _("Unable to update database with deep scan
information due error: %(err)s"),
+ "KCHPOOL0038E": _("Unable to deactivate pool %(name)s. There are some
virtual machines %(vms)s linked to this pool."),
"KCHVOL0001E": _("Storage volume %(name)s already exists"),
"KCHVOL0002E": _("Storage volume %(name)s does not exist in storage
pool %(pool)s"),
diff --git a/src/kimchi/model/storagepools.py b/src/kimchi/model/storagepools.py
index b85f3b4..c42b62e 100644
--- a/src/kimchi/model/storagepools.py
+++ b/src/kimchi/model/storagepools.py
@@ -18,6 +18,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import libvirt
+import os
from kimchi.scan import Scanner
from kimchi.exception import InvalidOperation, MissingParameter
@@ -27,6 +28,8 @@ from kimchi.model.host import DeviceModel
from kimchi.model.libvirtstoragepool import StoragePoolDef
from kimchi.utils import add_task, kimchi_log, pool_name_from_uri, run_command
from kimchi.xmlutils.utils import xpath_get_text
+from kimchi.model.vms import VMModel, VMsModel
+from kimchi.xmlutils.disk import get_vm_disk_info, get_vm_disks
ISO_POOL_NAME = u'kimchi_isos'
@@ -230,6 +233,24 @@ class StoragePoolModel(object):
source[key] = res
return source
+ def _get_vms_attach_to_a_storagepool(self, pool_name):
+ # find out vm(s) the vol(s) of this pool attached to.
+ pool = self.get_storagepool(pool_name, self.conn)
+ xml = pool.XMLDesc(0)
+
+ vms = []
+ pool_path = xpath_get_text(xml, "/pool/target/path")[0]
+ vms_list = VMsModel.get_vms(self.conn)
+ for vm in vms_list:
+ dom = VMModel.get_vm(vm, self.conn)
+ storages = get_vm_disks(dom)
+ for disk in storages.keys():
+ d_info = get_vm_disk_info(dom, disk)
+ if pool_path == os.path.split(d_info['path'])[0]:
+ vms.append(vm)
+ break
+ return sorted(vms)
+
Maybe would be better to use the objstore data.
There is an entry there for each storage volume in use.
Something like below:
with self.objstore as session:
paths = [path for path in session.get_list('storagevolume') if
path['ref_cnt'] > 0]
pool_re = '^' + pool_path
res = [re.match(pool_re, path) for path in paths if
re.match(pool_re, path) is not None]
if len(res) > 0:
#pool in use.
def _nfs_status_online(self, pool, poolArgs=None):
if not poolArgs:
xml = pool.XMLDesc(0)
@@ -378,6 +399,13 @@ class StoragePoolModel(object):
raise OperationFailed("KCHPOOL0033E",
{'name': name, 'server':
source['addr']})
return
+ elif (pool_type == 'logical' and
+ self._get_storagepool_vols_num(pool) > 0):
+ # can not deactive if vol(s) exists, because destroy
+ # logical pool will cause the vol deleted.
+ vms = self._get_vms_attach_to_a_storagepool(name)
+ raise InvalidOperation('KCHPOOL0038E', {'name': name,
+ 'vms': ',
'.join(vms)})
try:
persistent = pool.isPersistent()
pool.destroy()