[virt-tools-list] [virt-manager PATCH 1/2] Add glusterfs volumes support to virt-install
Chen Hanxiao
chenhanxiao at cn.fujitsu.com
Wed Oct 29 06:40:18 UTC 2014
From: Anatoly Belikov <wormblood at gmail.com>
Signed-off-by: Anatoly Belikov <wormblood at gmail.com>
Signed-off-by: Chen Hanxiao <chenhanxiao at cn.fujitsu.com>
---
tests/testdriver.xml | 35 +++++++++++++++++++++++++++++++++-
tests/xmlparse-xml/change-disk-in.xml | 8 ++++++++
tests/xmlparse-xml/change-disk-out.xml | 8 ++++++++
tests/xmlparse.py | 11 +++++++++++
virtinst/cli.py | 22 +++++++++++++++++++--
virtinst/devicedisk.py | 23 +++++++++++++++-------
virtinst/diskbackend.py | 26 ++++++++++++++++++++-----
virtinst/storage.py | 10 +++++++---
8 files changed, 125 insertions(+), 18 deletions(-)
diff --git a/tests/testdriver.xml b/tests/testdriver.xml
index 579c756..43c0755 100644
--- a/tests/testdriver.xml
+++ b/tests/testdriver.xml
@@ -1739,7 +1739,40 @@ ba</description>
</pool>
-
+<pool type='gluster'>
+ <name>gluster-pool</name>
+ <uuid>7b83ef6d-28da-44f1-841f-2011320f13b0</uuid>
+ <capacity unit='bytes'>492258959360</capacity>
+ <allocation unit='bytes'>16975638528</allocation>
+ <available unit='bytes'>475283320832</available>
+ <source>
+ <host name='192.168.1.100'/>
+ <dir path='/'/>
+ <name>test-volume</name>
+ </source>
+ <volume type='network'>
+ <name>test-volume2.raw</name>
+ <key>gluster://192.168.1.100/test-volume/test-gluster.raw</key>
+ <source>
+ </source>
+ <capacity unit='bytes'>10737418240</capacity>
+ <allocation unit='bytes'>2489327616</allocation>
+ <target>
+ <path>gluster://192.168.1.100/test-volume/test-gluster.raw</path>
+ <format type='raw'/>
+ <permissions>
+ <mode>0666</mode>
+ <owner>0</owner>
+ <group>0</group>
+ </permissions>
+ <timestamps>
+ <atime>1413881655.870313004</atime>
+ <mtime>1411649104.965642390</mtime>
+ <ctime>1412163870.190503958</ctime>
+ </timestamps>
+ </target>
+ </volume>
+</pool>
diff --git a/tests/xmlparse-xml/change-disk-in.xml b/tests/xmlparse-xml/change-disk-in.xml
index 9725e9b..16c1140 100644
--- a/tests/xmlparse-xml/change-disk-in.xml
+++ b/tests/xmlparse-xml/change-disk-in.xml
@@ -68,6 +68,14 @@
<target dev='vda' bus='virtio'/>
<readonly/>
</disk>
+ <disk type='network' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source protocol='sheepdog' name='sheepdog-pool/test-sheepdog.raw'>
+ <host name='test.domain'/>
+ </source>
+ <target dev='vdc' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
+ </disk>
<input type="mouse" bus="ps2"/>
<graphics type="vnc" display=":3.4" xauth="/tmp/.Xauthority"/>
<console type="pty"/>
diff --git a/tests/xmlparse-xml/change-disk-out.xml b/tests/xmlparse-xml/change-disk-out.xml
index d9af1e3..5acd34a 100644
--- a/tests/xmlparse-xml/change-disk-out.xml
+++ b/tests/xmlparse-xml/change-disk-out.xml
@@ -70,6 +70,14 @@
<target dev="vda" bus="virtio"/>
<readonly/>
</disk>
+ <disk type="network" device="disk">
+ <driver name="qemu" type="raw"/>
+ <source protocol="gluster" name="test-volume/test-gluster.raw">
+ <host name="192.168.1.100"/>
+ </source>
+ <target dev="vdc" bus="virtio"/>
+ <address type="pci" domain="0x0000" bus="0x00" slot="0x05" function="0x0"/>
+ </disk>
<input type="mouse" bus="ps2"/>
<graphics type="vnc" display=":3.4" xauth="/tmp/.Xauthority"/>
<console type="pty"/>
diff --git a/tests/xmlparse.py b/tests/xmlparse.py
index 62aa410..0bde7b2 100644
--- a/tests/xmlparse.py
+++ b/tests/xmlparse.py
@@ -332,6 +332,7 @@ class XMLParseTest(unittest.TestCase):
disk6 = disks[5]
disk6.size = 1
disk9 = disks[8]
+ disk_gl = disks[9]
check = self._make_checker(disk1)
check("path", "/tmp/test.img", "/dev/null")
@@ -374,6 +375,16 @@ class XMLParseTest(unittest.TestCase):
check = self._make_checker(disk9)
check("sourcePool", "defaultPool", "anotherPool")
+ check = self._make_checker(disk_gl)
+
+ check("source_protocol", "sheepdog", "gluster")
+
+ check("host_name", "test.domain", "192.168.1.100")
+ pool = conn.storagePoolLookupByName('gluster-pool')
+ vol = pool.listAllVolumes()[0] # virStorageVolLookupByName is not available yet
+ self.assertEquals(disk_gl.path, "sheepdog-pool/test-sheepdog.raw")
+ disk_gl.path = vol
+ self.assertEquals(disk_gl.path, "test-volume/test-gluster.raw")
self._alter_compare(guest.get_xml_config(), outfile)
def testSingleDisk(self):
diff --git a/virtinst/cli.py b/virtinst/cli.py
index b170aa4..a6bb831 100644
--- a/virtinst/cli.py
+++ b/virtinst/cli.py
@@ -1531,6 +1531,8 @@ class ParserDisk(VirtCLIParser):
self.set_param(None, "format", setter_cb=noset_cb)
self.set_param(None, "sparse", setter_cb=noset_cb)
+ self.set_param("source_protocol", "source_protocol")
+ self.set_param("host_name", "host_name")
self.set_param("path", "path")
self.set_param("device", "device")
self.set_param("bus", "bus")
@@ -1590,11 +1592,24 @@ class ParserDisk(VirtCLIParser):
size = parse_size(opts.get_opt_param("size"))
fmt = opts.get_opt_param("format")
sparse = _on_off_convert("sparse", opts.get_opt_param("sparse"))
+ host_name = None
+ protocol = None
abspath, volinst, volobj = _parse_disk_source(
self.guest, path, pool, vol, size, fmt, sparse)
- path = volobj and volobj.path() or abspath
+ if volobj and volobj.path():
+ gluster_protocol = 'gluster://'
+ if volobj.path().startswith('gluster://'):
+ path = volobj
+ protocol = 'gluster'
+ tmp = volobj.path()[len(gluster_protocol):]
+ host_name = tmp.split('/')[0]
+ else:
+ path = volobj.path()
+ else:
+ path = abspath
+
if had_path or path:
opts.opts["path"] = path or ""
@@ -1605,7 +1620,10 @@ class ParserDisk(VirtCLIParser):
if any(create_kwargs.values()):
inst.set_create_storage(**create_kwargs)
inst.cli_size = size
-
+ if protocol:
+ inst.source_protocol = protocol
+ if host_name:
+ inst.host_name = host_name
if not inst.target:
skip_targets = [d.target for d in self.guest.get_devices("disk")]
inst.generate_target(skip_targets)
diff --git a/virtinst/devicedisk.py b/virtinst/devicedisk.py
index 1d764d9..4516a02 100644
--- a/virtinst/devicedisk.py
+++ b/virtinst/devicedisk.py
@@ -24,6 +24,7 @@ import stat
import pwd
import subprocess
import logging
+import libvirt
import re
import urlgrabber.progress as progress
@@ -116,7 +117,6 @@ def _distill_storage(conn, do_create, nomanaged,
path = os.path.abspath(path)
(vol_object, pool, path_is_pool) = diskbackend.manage_path(conn, path)
-
creator = None
backend = diskbackend.StorageBackend(conn, path, vol_object,
path_is_pool and pool or None)
@@ -139,7 +139,7 @@ def _distill_storage(conn, do_create, nomanaged,
return backend, creator
-_TARGET_PROPS = ["file", "dev", "dir"]
+_TARGET_PROPS = ["file", "dev", "dir", "name"]
class VirtualDisk(VirtualDevice):
@@ -183,7 +183,8 @@ class VirtualDisk(VirtualDevice):
TYPE_BLOCK = "block"
TYPE_DIR = "dir"
TYPE_VOLUME = "volume"
- types = [TYPE_FILE, TYPE_BLOCK, TYPE_DIR, TYPE_VOLUME]
+ TYPE_NETWORK = "network"
+ types = [TYPE_FILE, TYPE_BLOCK, TYPE_DIR, TYPE_NETWORK]
IO_MODE_NATIVE = "native"
IO_MODE_THREADS = "threads"
@@ -215,6 +216,8 @@ class VirtualDisk(VirtualDevice):
return "dev"
elif disk_type == VirtualDisk.TYPE_DIR:
return "dir"
+ elif disk_type == VirtualDisk.TYPE_NETWORK:
+ return "name"
elif disk_type == VirtualDisk.TYPE_VOLUME:
return "volume"
return "file"
@@ -514,7 +517,7 @@ class VirtualDisk(VirtualDevice):
"type", "device",
"driver_name", "driver_type",
"driver_cache", "driver_discard", "driver_io", "error_policy",
- "_xmlpath", "target", "bus",
+ "_xmlpath", "source_protocol", "host_name", "target", "bus",
]
def __init__(self, *args, **kwargs):
@@ -535,14 +538,18 @@ class VirtualDisk(VirtualDevice):
if self._storage_creator:
return self._storage_creator.path
return self._storage_backend.path
+
def _set_path(self, val):
if self._storage_creator:
raise ValueError("Can't change disk path if storage creation info "
"has been set.")
- self._change_backend(val, None)
+ if type(val) == libvirt.virStorageVol:
+ self._change_backend(None, val)
+ else:
+ self._change_backend(val, None)
self._xmlpath = self.path
- path = property(_get_path, _set_path)
+ path = property(_get_path, _set_path)
def get_sparse(self):
if self._storage_creator:
@@ -610,6 +617,9 @@ class VirtualDisk(VirtualDevice):
_TARGET_PROPS])
sourcePool = XMLProperty("./source/@pool")
+ source_protocol = XMLProperty("./source/@protocol")
+ host_name = XMLProperty("./source/host/@name")
+
sourceStartupPolicy = XMLProperty("./source/@startupPolicy")
device = XMLProperty("./@device",
default_cb=lambda s: s.DEVICE_DISK)
@@ -619,7 +629,6 @@ class VirtualDisk(VirtualDevice):
driver_type = XMLProperty("./driver/@type",
default_cb=_get_default_driver_type)
-
bus = XMLProperty("./target/@bus")
target = XMLProperty("./target/@dev")
removable = XMLProperty("./target/@removable", is_onoff=True)
diff --git a/virtinst/diskbackend.py b/virtinst/diskbackend.py
index 32715d1..29ceb9a 100644
--- a/virtinst/diskbackend.py
+++ b/virtinst/diskbackend.py
@@ -22,6 +22,7 @@ import logging
import os
import statvfs
+import libxml2
import libvirt
from . import util
@@ -38,9 +39,9 @@ def check_if_path_managed(conn, path):
verr = None
path_is_pool = False
- def lookup_vol_by_path():
+ def lookup_vol_by_path(a_vol_path):
try:
- vol = conn.storageVolLookupByPath(path)
+ vol = conn.storageVolLookupByPath(a_vol_path)
vol.info()
return vol, None
except libvirt.libvirtError, e:
@@ -58,7 +59,7 @@ def check_if_path_managed(conn, path):
pass
return None
- vol = lookup_vol_by_path()[0]
+ vol = lookup_vol_by_path(path)[0]
if not vol:
pool = StoragePool.lookup_pool_by_path(conn, os.path.dirname(path))
@@ -72,7 +73,15 @@ def check_if_path_managed(conn, path):
# Pool may need to be refreshed, but if it errors,
# invalidate it
pool.refresh(0)
- vol, verr = lookup_vol_by_path()
+
+ pool_xml = libxml2.parseDoc(pool.XMLDesc())
+ if pool_xml.getRootElement().prop('type') == 'gluster':
+ ctxt = pool_xml.xpathNewContext()
+ host_name = ctxt.xpathEval("//host[@name]")[0].prop('name')
+ vol_path = 'gluster://' + host_name + '/' + path
+ else:
+ vol_path = path
+ vol, verr = lookup_vol_by_path(vol_path)
if verr:
vol = lookup_vol_name(os.path.basename(path))
except Exception, e:
@@ -460,7 +469,12 @@ class StorageBackend(_StorageBase):
def _get_path(self):
if self._vol_object:
- return self._get_vol_xml().target_path
+ result = self._get_vol_xml().target_path
+ gluster_protocol = 'gluster://'
+ if result.startswith(gluster_protocol):
+ tmp = result[len(gluster_protocol):]
+ return result.split(tmp[:tmp.find('/') + 1])[1]
+ return result
return self._path
path = property(_get_path)
@@ -513,6 +527,8 @@ class StorageBackend(_StorageBase):
self._dev_type = "file"
elif t == libvirt.VIR_STORAGE_VOL_BLOCK:
self._dev_type = "block"
+ elif t == libvirt.VIR_STORAGE_VOL_NETWORK:
+ self._dev_type = "network"
else:
self._dev_type = "file"
diff --git a/virtinst/storage.py b/virtinst/storage.py
index d090ce4..5ceb695 100644
--- a/virtinst/storage.py
+++ b/virtinst/storage.py
@@ -254,6 +254,10 @@ class StoragePool(_StorageObject):
if use_source:
xml_path = pool.source_path
else:
+ if pool.type == 'gluster':
+ if pool.source_name == path:
+ return True
+ return False
xml_path = pool.target_path
if xml_path is not None and os.path.abspath(xml_path) == path:
return True
@@ -291,14 +295,14 @@ class StoragePool(_StorageObject):
pass
if pool:
raise ValueError(_("Name '%s' already in use by another pool." %
- name))
+ name))
def _get_default_target_path(self):
if not self.supports_property("target_path"):
return None
if (self.type == self.TYPE_DIR or
- self.type == self.TYPE_NETFS or
- self.type == self.TYPE_FS):
+ self.type == self.TYPE_NETFS or
+ self.type == self.TYPE_FS):
return (DEFAULT_DIR_TARGET_BASE + self.name)
if self.type == self.TYPE_LOGICAL:
name = self.name
--
1.9.3
More information about the virt-tools-list
mailing list