Hello.
I would like to share my patch. It allows to create vm with volumes from glusterfs pools if volume already exists.
From 4bcb5ee8ec0df615b409af242306e568d4bb9827 Mon Sep 17 00:00:00 2001 From: Anatoly Belikov <wormblood@xxxxxxxxx> Date: Thu, 23 Oct 2014 15:32:24 +0400 Subject: [PATCH] add gluster volume support to virt-install --- tests/testdriver.xml | 35 +++++++++++++++++++++++++++++++- tests/xmlparse-xml/change-disk-in.xml | 8 ++++++++ tests/xmlparse-xml/change-disk-out.xml | 8 ++++++++ tests/xmlparse.py | 13 +++++++++++- virtinst/cli.py | 31 ++++++++++++++++++++++------ virtinst/devicedisk.py | 25 +++++++++++++++-------- virtinst/diskbackend.py | 24 +++++++++++++++++----- virtinst/storage.py | 4 ++++ 8 files changed, 127 insertions(+), 21 deletions(-) diff --git a/tests/testdriver.xml b/tests/testdriver.xml index 579c756..70d5757 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>debian-gluster2.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..98d1600 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,8 +375,18 @@ class XMLParseTest(unittest.TestCase): check = self._make_checker(disk9) check("sourcePool", "defaultPool", "anotherPool") - self._alter_compare(guest.get_xml_config(), outfile) + 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): xml = ("""<disk type="file" device="disk"><source file="/a.img"/>\n""" """<target dev="hda" bus="ide"/></disk>\n""") diff --git a/virtinst/cli.py b/virtinst/cli.py index e57ffbb..17baaa6 100644 --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -1530,7 +1530,9 @@ class ParserDisk(VirtCLIParser): self.set_param(None, "size", setter_cb=noset_cb) 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,22 +1592,39 @@ 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 "" - + inst = VirtCLIParser._parse(self, opts, inst) - + create_kwargs = {"size": size, "fmt": fmt, "sparse": sparse, "vol_install": volinst, "backing_store": backing_store} 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..2acbddf 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 @@ -100,7 +101,7 @@ def _is_dir_searchable(uid, username, path): def _distill_storage(conn, do_create, nomanaged, path, vol_object, vol_install, clone_path, backing_store, - *args): + *args, **kwargs): """ Validates and updates params when the backing storage is changed """ @@ -139,7 +140,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 +184,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 +217,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 +518,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 +539,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 +618,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) @@ -618,8 +629,6 @@ class VirtualDisk(VirtualDevice): default_cb=_get_default_driver_name) 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..a7259b2 100644 --- a/virtinst/diskbackend.py +++ b/virtinst/diskbackend.py @@ -38,9 +38,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 +58,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 +72,14 @@ 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() + import xml.etree.ElementTree as ET + root = ET.fromstring(pool.XMLDesc()) + if root.attrib['type'] == 'gluster': + host_name = root.findall(".//host[@name]")[0].attrib['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 +467,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 +525,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..2b55cc6 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 -- 1.7.10.4
_______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list