[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