mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-02 09:47:16 +03:00
Use XMLBuilder for Storage object handling
Simplify the API a bunch while we are at it, add tests, etc.
This commit is contained in:
parent
3db5cb5f06
commit
aff0ddb259
@ -226,7 +226,7 @@ class Command(object):
|
||||
|
||||
if bool(code) == self.check_success:
|
||||
raise AssertionError(
|
||||
("Expected command to %s, but failed.\n" %
|
||||
("Expected command to %s, but it didn't.\n" %
|
||||
(self.check_success and "pass" or "fail")) +
|
||||
("Command was: %s\n" % self.cmdstr) +
|
||||
("Error code : %d\n" % code) +
|
||||
@ -613,7 +613,6 @@ c.add_invalid("--disk vol=%(POOL)s/foovol") # Specify a nonexistent volume
|
||||
c.add_invalid("--disk pool=%(POOL)s") # Specify a pool with no size
|
||||
c.add_invalid("--disk path=%(EXISTIMG1)s,perms=ro,size=.0001,cache=FOOBAR") # Unknown cache type
|
||||
c.add_invalid("--disk path=%(NEWIMG1)s,format=qcow2,size=.0000001") # Unmanaged file using non-raw format
|
||||
c.add_invalid("--disk path=%(MANAGEDNEW1)s,format=frob,size=.0000001") # Managed file using unknown format
|
||||
c.add_invalid("--disk path=%(MANAGEDDISKNEW1)s,format=raw,size=.0000001") # Managed disk using any format
|
||||
c.add_invalid("--disk %(NEWIMG1)s") # Not specifying path= and non existent storage w/ no size
|
||||
c.add_invalid("--disk %(COLLIDE)s") # Colliding storage without --force
|
||||
|
@ -3,7 +3,7 @@
|
||||
<capacity>10737418240</capacity>
|
||||
<allocation>5368709120</allocation>
|
||||
<target>
|
||||
<format type='raw'/>
|
||||
<format type="raw"/>
|
||||
<permissions>
|
||||
<mode>0700</mode>
|
||||
<owner>10736</owner>
|
||||
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<volume>
|
||||
<name>pool-dir-volclone</name>
|
||||
<key>/some/target/path/pool-dir-vol</key>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<capacity>10737418240</capacity>
|
||||
<allocation>5368709120</allocation>
|
||||
<target>
|
||||
<format type='raw'/>
|
||||
<format type="raw"/>
|
||||
<permissions>
|
||||
<mode>0700</mode>
|
||||
<owner>10736</owner>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<pool type='dir'>
|
||||
<pool type="dir">
|
||||
<name>pool-dir</name>
|
||||
<uuid>10010511-4100-1051-1410-010511410010</uuid>
|
||||
<target>
|
||||
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<volume>
|
||||
<name>pool-disk-volclone</name>
|
||||
<key>/some/target/path/pool-disk-vol</key>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<capacity>10737418240</capacity>
|
||||
<allocation>5368709120</allocation>
|
||||
<target>
|
||||
<format type="none"/>
|
||||
<permissions>
|
||||
<mode>0700</mode>
|
||||
<owner>10736</owner>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<pool type='disk'>
|
||||
<pool type="disk">
|
||||
<name>pool-disk</name>
|
||||
<uuid>10010511-5107-1001-0511-510710010511</uuid>
|
||||
<source>
|
||||
@ -6,6 +6,6 @@
|
||||
<device path="/some/source/path"/>
|
||||
</source>
|
||||
<target>
|
||||
<path>/some/target/path</path>
|
||||
<path>/some/target/path</path>
|
||||
</target>
|
||||
</pool>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<capacity>10737418240</capacity>
|
||||
<allocation>5368709120</allocation>
|
||||
<target>
|
||||
<format type='raw'/>
|
||||
<format type="raw"/>
|
||||
<permissions>
|
||||
<mode>0700</mode>
|
||||
<owner>10736</owner>
|
||||
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<volume>
|
||||
<name>pool-fs-volclone</name>
|
||||
<key>/some/target/path/pool-fs-vol</key>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<capacity>10737418240</capacity>
|
||||
<allocation>5368709120</allocation>
|
||||
<target>
|
||||
<format type='raw'/>
|
||||
<format type="raw"/>
|
||||
<permissions>
|
||||
<mode>0700</mode>
|
||||
<owner>10736</owner>
|
||||
|
@ -1,9 +1,9 @@
|
||||
<pool type='fs'>
|
||||
<pool type="fs">
|
||||
<name>pool-fs</name>
|
||||
<uuid>10211510-2115-1021-1510-211510211510</uuid>
|
||||
<source>
|
||||
<format type='auto'/>
|
||||
<device path='/some/source/path'/>
|
||||
<format type="auto"/>
|
||||
<device path="/some/source/path"/>
|
||||
</source>
|
||||
<target>
|
||||
<path>/some/target/path</path>
|
||||
|
@ -1,14 +0,0 @@
|
||||
<pool type='iscsi'>
|
||||
<name>pool-iscsi-iqn</name>
|
||||
<uuid>10511599-1151-0545-1051-131101051159</uuid>
|
||||
<source>
|
||||
<host name="some.random.hostname"/>
|
||||
<device path="/some/source/path"/>
|
||||
<initiator>
|
||||
<iqn name="foo.bar.baz.iqn"/>
|
||||
</initiator>
|
||||
</source>
|
||||
<target>
|
||||
<path>/some/target/path</path>
|
||||
</target>
|
||||
</pool>
|
@ -1,9 +1,12 @@
|
||||
<pool type='iscsi'>
|
||||
<pool type="iscsi">
|
||||
<name>pool-iscsi</name>
|
||||
<uuid>10511599-1151-0510-5115-991151051051</uuid>
|
||||
<source>
|
||||
<host name="some.random.hostname"/>
|
||||
<device path="/some/source/path"/>
|
||||
<initiator>
|
||||
<iqn name="foo.bar.baz.iqn"/>
|
||||
</initiator>
|
||||
</source>
|
||||
<target>
|
||||
<path>/some/target/path</path>
|
||||
|
@ -1,8 +1,9 @@
|
||||
<pool type='logical'>
|
||||
<pool type="logical">
|
||||
<name>pool-logical-list0</name>
|
||||
<uuid>10811110-3105-9997-1084-510810511511</uuid>
|
||||
<source>
|
||||
<device path='/dev/sda20'/>
|
||||
<format type="lvm2"/>
|
||||
<device path="/dev/sda20"/>
|
||||
<name>testvg1</name>
|
||||
</source>
|
||||
<target>
|
||||
|
@ -1,8 +1,9 @@
|
||||
<pool type='logical'>
|
||||
<pool type="logical">
|
||||
<name>pool-logical-list1</name>
|
||||
<uuid>10811110-3105-9997-1084-510810511511</uuid>
|
||||
<source>
|
||||
<device path='/dev/sda21'/>
|
||||
<format type="lvm2"/>
|
||||
<device path="/dev/sda21"/>
|
||||
<name>testvg2</name>
|
||||
</source>
|
||||
<target>
|
||||
|
@ -1,13 +0,0 @@
|
||||
<pool type='logical'>
|
||||
<name>pool-logical-manydev</name>
|
||||
<uuid>10811110-3105-9997-1084-510997110121</uuid>
|
||||
<source>
|
||||
<device path='/tmp/path1'/>
|
||||
<device path='/tmp/path2'/>
|
||||
<device path='/tmp/path3'/>
|
||||
<name>pool-logical-manydev</name>
|
||||
</source>
|
||||
<target>
|
||||
<path>/some/target/path</path>
|
||||
</target>
|
||||
</pool>
|
@ -1,8 +1,8 @@
|
||||
<pool type='logical'>
|
||||
<pool type="logical">
|
||||
<name>pool-logical-srcname</name>
|
||||
<uuid>10811110-3105-9997-1084-511511499110</uuid>
|
||||
<source>
|
||||
<device path='/some/source/path'/>
|
||||
<device path="/some/source/path"/>
|
||||
<name>vgname</name>
|
||||
</source>
|
||||
<target>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<pool type='logical'>
|
||||
<pool type="logical">
|
||||
<name>pool-logical-target-srcname</name>
|
||||
<uuid>10811110-3105-9997-1084-511697114103</uuid>
|
||||
<source>
|
||||
<device path='/some/source/path'/>
|
||||
<device path="/some/source/path"/>
|
||||
<name>vgfoobar</name>
|
||||
</source>
|
||||
<target>
|
||||
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<volume>
|
||||
<name>pool-logical-volclone</name>
|
||||
<key>/dev/pool-logical/pool-logical-vol</key>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<pool type='logical'>
|
||||
<pool type="logical">
|
||||
<name>pool-logical</name>
|
||||
<uuid>10811110-3105-9997-1081-081111031059</uuid>
|
||||
<source>
|
||||
<device path='/some/source/path'/>
|
||||
<device path="/some/source/path"/>
|
||||
<name>pool-logical</name>
|
||||
</source>
|
||||
<target>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<pool type='mpath'>
|
||||
<pool type="mpath">
|
||||
<name>pool-mpath</name>
|
||||
<uuid>10911297-1161-0410-9112-971161041091</uuid>
|
||||
<target>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<pool type='netfs'>
|
||||
<pool type="netfs">
|
||||
<name>pool-netfs-list0</name>
|
||||
<uuid>11010111-6102-1154-5108-105115116481</uuid>
|
||||
<source>
|
||||
@ -7,6 +7,6 @@
|
||||
<dir path="/testshare"/>
|
||||
</source>
|
||||
<target>
|
||||
<path>/var/lib/libvirt/images/pool-netfs-list</path>
|
||||
<path>/var/lib/libvirt/images/pool-netfs-list0</path>
|
||||
</target>
|
||||
</pool>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<capacity>10737418240</capacity>
|
||||
<allocation>5368709120</allocation>
|
||||
<target>
|
||||
<format type='raw'/>
|
||||
<format type="raw"/>
|
||||
<permissions>
|
||||
<mode>0700</mode>
|
||||
<owner>10736</owner>
|
||||
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<volume>
|
||||
<name>pool-netfs-volclone</name>
|
||||
<key>/some/target/path/pool-netfs-vol</key>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<capacity>10737418240</capacity>
|
||||
<allocation>5368709120</allocation>
|
||||
<target>
|
||||
<format type='raw'/>
|
||||
<format type="raw"/>
|
||||
<permissions>
|
||||
<mode>0700</mode>
|
||||
<owner>10736</owner>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<pool type='netfs'>
|
||||
<pool type="netfs">
|
||||
<name>pool-netfs</name>
|
||||
<uuid>11010111-6102-1151-1010-111610211511</uuid>
|
||||
<source>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<pool type='scsi'>
|
||||
<pool type="scsi">
|
||||
<name>pool-scsi</name>
|
||||
<uuid>11599115-1051-1599-1151-051159911510</uuid>
|
||||
<source>
|
||||
|
126
tests/storage.py
126
tests/storage.py
@ -17,7 +17,7 @@
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from virtinst import Storage
|
||||
from virtinst import StoragePool, StorageVolume
|
||||
|
||||
from tests import utils
|
||||
|
||||
@ -28,7 +28,6 @@ basepath = os.path.join(os.getcwd(), "tests", "storage-xml")
|
||||
|
||||
|
||||
def generate_uuid_from_string(msg):
|
||||
|
||||
res = msg.split("-", 1)
|
||||
if len(res) > 1:
|
||||
# Split off common prefix
|
||||
@ -39,19 +38,16 @@ def generate_uuid_from_string(msg):
|
||||
numstr += str(ord(c))
|
||||
|
||||
numstr *= 32
|
||||
numstr = numstr[0:32]
|
||||
|
||||
return numstr
|
||||
return "-".join([numstr[0:8], numstr[8:12], numstr[12:16], numstr[16:20],
|
||||
numstr[20:32]])
|
||||
|
||||
|
||||
def _findFreePoolName(conn, namebase):
|
||||
|
||||
i = 0
|
||||
while True:
|
||||
poolname = namebase + "-%d" % i
|
||||
try:
|
||||
Storage.StorageVolume.lookup_pool_by_name(conn=conn,
|
||||
pool_name=poolname)
|
||||
StorageVolume.lookup_pool_by_name(conn=conn, pool_name=poolname)
|
||||
i += 1
|
||||
except:
|
||||
return poolname
|
||||
@ -59,7 +55,6 @@ def _findFreePoolName(conn, namebase):
|
||||
|
||||
def createPool(conn, ptype, poolname=None, fmt=None, target_path=None,
|
||||
source_path=None, source_name=None, uuid=None, iqn=None):
|
||||
poolclass = Storage.StoragePool.get_pool_class(ptype)
|
||||
|
||||
if poolname is None:
|
||||
poolname = _findFreePoolName(conn, str(ptype) + "-pool")
|
||||
@ -67,21 +62,25 @@ def createPool(conn, ptype, poolname=None, fmt=None, target_path=None,
|
||||
if uuid is None:
|
||||
uuid = generate_uuid_from_string(poolname)
|
||||
|
||||
pool_inst = poolclass(conn=conn, name=poolname, uuid=uuid)
|
||||
pool_inst = StoragePool(conn)
|
||||
pool_inst.name = poolname
|
||||
pool_inst.type = ptype
|
||||
pool_inst.uuid = uuid
|
||||
|
||||
if hasattr(pool_inst, "host"):
|
||||
if pool_inst.supports_property("host"):
|
||||
pool_inst.host = "some.random.hostname"
|
||||
if hasattr(pool_inst, "source_path"):
|
||||
if pool_inst.supports_property("source_path"):
|
||||
pool_inst.source_path = source_path or "/some/source/path"
|
||||
if hasattr(pool_inst, "target_path"):
|
||||
if pool_inst.supports_property("target_path"):
|
||||
pool_inst.target_path = target_path or "/some/target/path"
|
||||
if fmt and hasattr(pool_inst, "format"):
|
||||
if fmt and pool_inst.supports_property("format"):
|
||||
pool_inst.format = fmt
|
||||
if source_name and hasattr(pool_inst, "source_name"):
|
||||
if source_name and pool_inst.supports_property("source_name"):
|
||||
pool_inst.source_name = source_name
|
||||
if iqn and hasattr(pool_inst, "iqn"):
|
||||
if iqn and pool_inst.supports_property("iqn"):
|
||||
pool_inst.iqn = iqn
|
||||
|
||||
pool_inst.validate()
|
||||
return poolCompare(pool_inst)
|
||||
|
||||
|
||||
@ -97,33 +96,33 @@ def poolCompare(pool_inst):
|
||||
|
||||
|
||||
def createVol(conn, poolobj, volname=None, input_vol=None, clone_vol=None):
|
||||
volclass = Storage.StorageVolume.get_volume_for_pool(pool_object=poolobj)
|
||||
|
||||
if volname is None:
|
||||
volname = poolobj.name() + "-vol"
|
||||
|
||||
alloc = 5 * 1024 * 1024 * 1024
|
||||
cap = 10 * 1024 * 1024 * 1024
|
||||
vol_inst = volclass(conn,
|
||||
name=volname, capacity=cap, allocation=alloc,
|
||||
pool=poolobj)
|
||||
vol_inst = StorageVolume(conn)
|
||||
vol_inst.pool = poolobj
|
||||
vol_inst.name = volname
|
||||
vol_inst.capacity = cap
|
||||
vol_inst.allocation = alloc
|
||||
|
||||
perms = {}
|
||||
perms["mode"] = 0700
|
||||
perms["owner"] = 10736
|
||||
perms["group"] = 10736
|
||||
vol_inst.permissions.mode = "0700"
|
||||
vol_inst.permissions.owner = "10736"
|
||||
vol_inst.permissions.group = "10736"
|
||||
|
||||
vol_inst.perms = perms
|
||||
if input_vol:
|
||||
vol_inst.input_vol = input_vol
|
||||
vol_inst.sync_input_vol()
|
||||
elif clone_vol:
|
||||
vol_inst = Storage.CloneVolume(conn, volname, clone_vol)
|
||||
vol_inst = StorageVolume(conn, parsexml=clone_vol.XMLDesc(0))
|
||||
vol_inst.input_vol = clone_vol
|
||||
vol_inst.sync_input_vol()
|
||||
vol_inst.name = volname
|
||||
|
||||
vol_inst.validate()
|
||||
filename = os.path.join(basepath, vol_inst.name + ".xml")
|
||||
|
||||
# Make sure permissions are properly set
|
||||
utils.diff_compare(vol_inst.get_xml_config(), filename)
|
||||
|
||||
return vol_inst.install(meter=False)
|
||||
|
||||
|
||||
@ -134,7 +133,7 @@ class TestStorage(unittest.TestCase):
|
||||
|
||||
def testDirPool(self):
|
||||
poolobj = createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_DIR, "pool-dir")
|
||||
StoragePool.TYPE_DIR, "pool-dir")
|
||||
invol = createVol(self.conn, poolobj)
|
||||
createVol(self.conn, poolobj,
|
||||
volname=invol.name() + "input", input_vol=invol)
|
||||
@ -143,7 +142,7 @@ class TestStorage(unittest.TestCase):
|
||||
|
||||
def testFSPool(self):
|
||||
poolobj = createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_FS, "pool-fs")
|
||||
StoragePool.TYPE_FS, "pool-fs")
|
||||
invol = createVol(self.conn, poolobj)
|
||||
createVol(self.conn, poolobj,
|
||||
volname=invol.name() + "input", input_vol=invol)
|
||||
@ -152,7 +151,7 @@ class TestStorage(unittest.TestCase):
|
||||
|
||||
def testNetFSPool(self):
|
||||
poolobj = createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_NETFS, "pool-netfs")
|
||||
StoragePool.TYPE_NETFS, "pool-netfs")
|
||||
invol = createVol(self.conn, poolobj)
|
||||
createVol(self.conn, poolobj,
|
||||
volname=invol.name() + "input", input_vol=invol)
|
||||
@ -161,7 +160,7 @@ class TestStorage(unittest.TestCase):
|
||||
|
||||
def testLVPool(self):
|
||||
poolobj = createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_LOGICAL,
|
||||
StoragePool.TYPE_LOGICAL,
|
||||
"pool-logical",
|
||||
target_path="/dev/pool-logical")
|
||||
invol = createVol(self.conn, poolobj)
|
||||
@ -171,24 +170,25 @@ class TestStorage(unittest.TestCase):
|
||||
poolobj, volname=invol.name() + "clone", clone_vol=invol)
|
||||
|
||||
# Test parsing source name for target path
|
||||
createPool(self.conn, Storage.StoragePool.TYPE_LOGICAL,
|
||||
createPool(self.conn, StoragePool.TYPE_LOGICAL,
|
||||
"pool-logical-target-srcname",
|
||||
target_path="/dev/vgfoobar")
|
||||
|
||||
# Test with source name
|
||||
createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_LOGICAL, "pool-logical-srcname",
|
||||
StoragePool.TYPE_LOGICAL, "pool-logical-srcname",
|
||||
source_name="vgname")
|
||||
|
||||
# Test creating with many devices
|
||||
createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_LOGICAL, "pool-logical-manydev",
|
||||
source_path=["/tmp/path1", "/tmp/path2", "/tmp/path3"],
|
||||
target_path=None)
|
||||
# XXX: Need to wire this up
|
||||
#createPool(self.conn,
|
||||
# StoragePool.TYPE_LOGICAL, "pool-logical-manydev",
|
||||
# source_path=["/tmp/path1", "/tmp/path2", "/tmp/path3"],
|
||||
# target_path=None)
|
||||
|
||||
def testDiskPool(self):
|
||||
poolobj = createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_DISK,
|
||||
StoragePool.TYPE_DISK,
|
||||
"pool-disk", fmt="dos")
|
||||
invol = createVol(self.conn, poolobj)
|
||||
createVol(self.conn, poolobj,
|
||||
@ -197,58 +197,40 @@ class TestStorage(unittest.TestCase):
|
||||
volname=invol.name() + "clone", clone_vol=invol)
|
||||
|
||||
def testISCSIPool(self):
|
||||
poolobj = createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_ISCSI, "pool-iscsi")
|
||||
# Not supported
|
||||
#volobj = createVol(poolobj)
|
||||
self.assertRaises(RuntimeError, createVol, self.conn, poolobj)
|
||||
|
||||
createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_ISCSI, "pool-iscsi-iqn",
|
||||
StoragePool.TYPE_ISCSI, "pool-iscsi",
|
||||
iqn="foo.bar.baz.iqn")
|
||||
|
||||
def testSCSIPool(self):
|
||||
poolobj = createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_SCSI, "pool-scsi")
|
||||
# Not supported
|
||||
#volobj = createVol(poolobj)
|
||||
self.assertRaises(RuntimeError, createVol, self.conn, poolobj)
|
||||
createPool(self.conn, StoragePool.TYPE_SCSI, "pool-scsi")
|
||||
|
||||
def testMpathPool(self):
|
||||
poolobj = createPool(self.conn,
|
||||
Storage.StoragePool.TYPE_MPATH, "pool-mpath")
|
||||
# Not supported
|
||||
#volobj = createVol(poolobj)
|
||||
self.assertRaises(RuntimeError, createVol, self.conn, poolobj)
|
||||
createPool(self.conn, StoragePool.TYPE_MPATH, "pool-mpath")
|
||||
|
||||
def _enumerateCompare(self, pool_list):
|
||||
def _enumerateCompare(self, name, pool_list):
|
||||
for pool in pool_list:
|
||||
pool.name = pool.name + str(pool_list.index(pool))
|
||||
pool.name = name + str(pool_list.index(pool))
|
||||
pool.uuid = generate_uuid_from_string(pool.name)
|
||||
poolCompare(pool)
|
||||
|
||||
def testEnumerateLogical(self):
|
||||
name = "pool-logical-list"
|
||||
|
||||
lst = Storage.StoragePool.pool_list_from_sources(self.conn, name,
|
||||
Storage.StoragePool.TYPE_LOGICAL)
|
||||
self._enumerateCompare(lst)
|
||||
lst = StoragePool.pool_list_from_sources(self.conn,
|
||||
StoragePool.TYPE_LOGICAL)
|
||||
self._enumerateCompare(name, lst)
|
||||
|
||||
def testEnumerateNetFS(self):
|
||||
name = "pool-netfs-list"
|
||||
host = "example.com"
|
||||
|
||||
lst = Storage.StoragePool.pool_list_from_sources(self.conn, name,
|
||||
Storage.StoragePool.TYPE_NETFS,
|
||||
lst = StoragePool.pool_list_from_sources(self.conn,
|
||||
StoragePool.TYPE_NETFS,
|
||||
host=host)
|
||||
self._enumerateCompare(lst)
|
||||
self._enumerateCompare(name, lst)
|
||||
|
||||
def testEnumerateiSCSI(self):
|
||||
name = "pool-iscsi-list"
|
||||
host = "example.com"
|
||||
|
||||
lst = Storage.StoragePool.pool_list_from_sources(self.conn, name,
|
||||
Storage.StoragePool.TYPE_ISCSI,
|
||||
lst = StoragePool.pool_list_from_sources(self.conn,
|
||||
StoragePool.TYPE_ISCSI,
|
||||
host=host)
|
||||
self.assertTrue(len(lst) == 0)
|
||||
|
||||
|
15
tests/xmlparse-xml/pool-dir-vol-out.xml
Normal file
15
tests/xmlparse-xml/pool-dir-vol-out.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<volume>
|
||||
<name>pool-dir-vol</name>
|
||||
<capacity>2000</capacity>
|
||||
<allocation>1000</allocation>
|
||||
<target>
|
||||
<format type="qcow2"/>
|
||||
<permissions>
|
||||
<mode>0744</mode>
|
||||
<owner>10000</owner>
|
||||
<group>10000</group>
|
||||
<label>foo.label</label>
|
||||
</permissions>
|
||||
<path>/foo/bar</path>
|
||||
</target>
|
||||
</volume>
|
15
tests/xmlparse-xml/pool-fs-out.xml
Normal file
15
tests/xmlparse-xml/pool-fs-out.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<pool type="dir">
|
||||
<name>foo-new</name>
|
||||
<uuid>10211510-2115-1021-1510-211510211999</uuid>
|
||||
<capacity unit="bytes">200000</capacity>
|
||||
<allocation unit="bytes">150000</allocation>
|
||||
<available unit="bytes">50000</available>
|
||||
<source>
|
||||
<format type="ext3"/>
|
||||
<device path="/dev/foo/bar"/>
|
||||
<name>fooname</name>
|
||||
</source>
|
||||
<target>
|
||||
<path>/mnt/my/foo</path>
|
||||
</target>
|
||||
</pool>
|
14
tests/xmlparse-xml/pool-fs.xml
Normal file
14
tests/xmlparse-xml/pool-fs.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<pool type="fs">
|
||||
<name>pool-fs</name>
|
||||
<uuid>10211510-2115-1021-1510-211510211510</uuid>
|
||||
<capacity unit='bytes'>984373075968</capacity>
|
||||
<allocation unit='bytes'>756681687040</allocation>
|
||||
<available unit='bytes'>227691388928</available>
|
||||
<source>
|
||||
<format type="auto"/>
|
||||
<device path="/some/source/path"/>
|
||||
</source>
|
||||
<target>
|
||||
<path>/some/target/path</path>
|
||||
</target>
|
||||
</pool>
|
14
tests/xmlparse-xml/pool-iscsi-out.xml
Normal file
14
tests/xmlparse-xml/pool-iscsi-out.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<pool type="iscsi">
|
||||
<name>pool-iscsi</name>
|
||||
<uuid>10511599-1151-0510-5115-991151051051</uuid>
|
||||
<source>
|
||||
<host name="my.host"/>
|
||||
<device path="/some/source/path"/>
|
||||
<initiator>
|
||||
<iqn name="my.iqn"/>
|
||||
</initiator>
|
||||
</source>
|
||||
<target>
|
||||
<path>/some/target/path</path>
|
||||
</target>
|
||||
</pool>
|
@ -903,6 +903,69 @@ class XMLParseTest(unittest.TestCase):
|
||||
utils.test_create(conn, iface.get_xml_config(), "interfaceDefineXML")
|
||||
|
||||
|
||||
#################
|
||||
# Storage tests #
|
||||
#################
|
||||
|
||||
def testFSPool(self):
|
||||
basename = "pool-fs"
|
||||
infile = "tests/xmlparse-xml/%s.xml" % basename
|
||||
outfile = "tests/xmlparse-xml/%s-out.xml" % basename
|
||||
pool = virtinst.StoragePool(conn, parsexml=file(infile).read())
|
||||
|
||||
check = self._make_checker(pool)
|
||||
check("type", "fs", "dir")
|
||||
check("name", "pool-fs", "foo-new")
|
||||
check("uuid", "10211510-2115-1021-1510-211510211510",
|
||||
"10211510-2115-1021-1510-211510211999")
|
||||
check("capacity", 984373075968, 200000)
|
||||
check("allocation", 756681687040, 150000)
|
||||
check("available", 227691388928, 50000)
|
||||
|
||||
check("format", "auto", "ext3")
|
||||
check("source_path", "/some/source/path", "/dev/foo/bar")
|
||||
check("target_path", "/some/target/path", "/mnt/my/foo")
|
||||
check("source_name", None, "fooname")
|
||||
|
||||
utils.diff_compare(pool.get_xml_config(), outfile)
|
||||
utils.test_create(conn, pool.get_xml_config(), "storagePoolDefineXML")
|
||||
|
||||
def testISCSIPool(self):
|
||||
basename = "pool-iscsi"
|
||||
infile = "tests/storage-xml/%s.xml" % basename
|
||||
outfile = "tests/xmlparse-xml/%s-out.xml" % basename
|
||||
pool = virtinst.StoragePool(conn, parsexml=file(infile).read())
|
||||
|
||||
check = self._make_checker(pool)
|
||||
check("host", "some.random.hostname", "my.host")
|
||||
check("iqn", "foo.bar.baz.iqn", "my.iqn")
|
||||
|
||||
utils.diff_compare(pool.get_xml_config(), outfile)
|
||||
utils.test_create(conn, pool.get_xml_config(), "storagePoolDefineXML")
|
||||
|
||||
def testVol(self):
|
||||
basename = "pool-dir-vol"
|
||||
infile = "tests/storage-xml/%s.xml" % basename
|
||||
outfile = "tests/xmlparse-xml/%s-out.xml" % basename
|
||||
vol = virtinst.StorageVolume(conn, parsexml=file(infile).read())
|
||||
|
||||
check = self._make_checker(vol)
|
||||
check("capacity", 10737418240, 2000)
|
||||
check("allocation", 5368709120, 1000)
|
||||
check("format", "raw", "qcow2")
|
||||
check("target_path", None, "/foo/bar")
|
||||
|
||||
check = self._make_checker(vol.permissions)
|
||||
check("mode", "0700", "0744")
|
||||
check("owner", "10736", "10000")
|
||||
check("group", "10736", "10000")
|
||||
check("label", None, "foo.label")
|
||||
|
||||
utils.diff_compare(vol.get_xml_config(), outfile)
|
||||
|
||||
|
||||
|
||||
|
||||
##############
|
||||
# Misc tests #
|
||||
##############
|
||||
|
@ -1229,7 +1229,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
fmt = self.config.get_storage_format()
|
||||
if (self.is_default_storage() and
|
||||
disk.get_vol_install() and
|
||||
fmt in disk.get_vol_install().formats):
|
||||
fmt in disk.get_vol_install().list_formats()):
|
||||
logging.debug("Setting disk format from prefs: %s", fmt)
|
||||
disk.get_vol_install().format = fmt
|
||||
|
||||
|
@ -35,7 +35,6 @@ import virtinst
|
||||
from virtinst import pollhelpers
|
||||
from virtinst import util
|
||||
|
||||
from virtManager import uihelpers
|
||||
from virtManager import connectauth
|
||||
from virtManager.baseclass import vmmGObject
|
||||
from virtManager.domain import vmmDomain
|
||||
@ -431,7 +430,7 @@ class vmmConnection(vmmGObject):
|
||||
else:
|
||||
# Try to create the default storage pool
|
||||
try:
|
||||
uihelpers.build_default_pool(self)
|
||||
virtinst.StoragePool.build_default_pool(self.get_backend())
|
||||
except Exception, e:
|
||||
logging.debug("Building default pool failed: %s", str(e))
|
||||
|
||||
@ -699,7 +698,7 @@ class vmmConnection(vmmGObject):
|
||||
def get_vol_by_path(self, path):
|
||||
for pool in self.pools.values():
|
||||
for vol in pool.get_volumes().values():
|
||||
if vol.get_path() == path:
|
||||
if vol.get_target_path() == path:
|
||||
return vol
|
||||
return None
|
||||
|
||||
|
@ -1685,7 +1685,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
fmt = self.config.get_storage_format()
|
||||
if (self.is_default_storage() and
|
||||
disk.get_vol_install() and
|
||||
fmt in disk.get_vol_install().formats):
|
||||
fmt in disk.get_vol_install().list_formats()):
|
||||
logging.debug("Setting disk format from prefs: %s", fmt)
|
||||
disk.get_vol_install().format = fmt
|
||||
disk.validate()
|
||||
|
@ -23,14 +23,13 @@ from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
# pylint: enable=E0611
|
||||
|
||||
import copy
|
||||
import logging
|
||||
|
||||
from virtManager.baseclass import vmmGObjectUI
|
||||
from virtManager.asyncjob import vmmAsyncJob
|
||||
from virtManager import uihelpers
|
||||
|
||||
from virtinst import Storage
|
||||
from virtinst import StoragePool
|
||||
|
||||
PAGE_NAME = 0
|
||||
PAGE_FORMAT = 1
|
||||
@ -44,7 +43,6 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
self.conn = conn
|
||||
|
||||
self._pool = None
|
||||
self._pool_class = Storage.StoragePool
|
||||
|
||||
self.builder.connect_signals({
|
||||
"on_pool_forward_clicked" : self.forward,
|
||||
@ -178,11 +176,11 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
def populate_pool_type(self):
|
||||
model = self.widget("pool-type").get_model()
|
||||
model.clear()
|
||||
types = Storage.StoragePool.get_pool_types()
|
||||
types = StoragePool.get_pool_types()
|
||||
types.sort()
|
||||
for typ in types:
|
||||
model.append([typ, "%s: %s" %
|
||||
(typ, Storage.StoragePool.get_pool_type_desc(typ))])
|
||||
(typ, StoragePool.get_pool_type_desc(typ))])
|
||||
|
||||
def populate_pool_format(self, formats):
|
||||
model = self.widget("pool-format").get_model()
|
||||
@ -202,24 +200,24 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
use_list = source_list
|
||||
use_model = source_model
|
||||
entry_list = []
|
||||
if self._pool.type == Storage.StoragePool.TYPE_SCSI:
|
||||
if self._pool.type == StoragePool.TYPE_SCSI:
|
||||
entry_list = self.list_scsi_adapters()
|
||||
use_list = source_list
|
||||
use_model = source_model
|
||||
|
||||
elif self._pool.type == Storage.StoragePool.TYPE_LOGICAL:
|
||||
elif self._pool.type == StoragePool.TYPE_LOGICAL:
|
||||
pool_list = self.list_pool_sources()
|
||||
entry_list = [[p.target_path, p.target_path, p]
|
||||
for p in pool_list]
|
||||
use_list = target_list
|
||||
use_model = target_model
|
||||
|
||||
elif self._pool.type == Storage.StoragePool.TYPE_DISK:
|
||||
elif self._pool.type == StoragePool.TYPE_DISK:
|
||||
entry_list = self.list_disk_devs()
|
||||
use_list = source_list
|
||||
use_model = source_model
|
||||
|
||||
elif self._pool.type == Storage.StoragePool.TYPE_NETFS:
|
||||
elif self._pool.type == StoragePool.TYPE_NETFS:
|
||||
host = self.get_config_host()
|
||||
if host:
|
||||
pool_list = self.list_pool_sources(host=host)
|
||||
@ -240,12 +238,11 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
|
||||
clean_list = []
|
||||
for h in host_list:
|
||||
tmppool = copy.copy(self._pool)
|
||||
name = "host%s" % h
|
||||
|
||||
tmppool = self._make_stub_pool()
|
||||
tmppool.source_path = name
|
||||
entry = [name, name, tmppool]
|
||||
|
||||
entry = [name, name, tmppool]
|
||||
if name not in [l[0] for l in clean_list]:
|
||||
clean_list.append(entry)
|
||||
|
||||
@ -262,7 +259,7 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
devlist.sort()
|
||||
clean_list = []
|
||||
for dev in devlist:
|
||||
tmppool = copy.copy(self._pool)
|
||||
tmppool = self._make_stub_pool()
|
||||
tmppool.source_path = dev
|
||||
|
||||
entry = [dev, dev, tmppool]
|
||||
@ -272,14 +269,13 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
return clean_list
|
||||
|
||||
def list_pool_sources(self, host=None):
|
||||
name = self.get_config_name()
|
||||
pool_type = self._pool.type
|
||||
|
||||
plist = []
|
||||
try:
|
||||
plist = Storage.StoragePool.pool_list_from_sources(
|
||||
plist = StoragePool.pool_list_from_sources(
|
||||
self.conn.get_backend(),
|
||||
name, pool_type,
|
||||
pool_type,
|
||||
host=host)
|
||||
except Exception:
|
||||
logging.exception("Pool enumeration failed")
|
||||
@ -291,19 +287,19 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
self.widget(base + "-label").set_visible(do_show)
|
||||
self.widget(base + "-box").set_visible(do_show)
|
||||
|
||||
src = hasattr(self._pool, "source_path")
|
||||
src_b = src and not self.conn.is_remote()
|
||||
tgt = hasattr(self._pool, "target_path")
|
||||
tgt_b = tgt and not self.conn.is_remote()
|
||||
host = hasattr(self._pool, "host")
|
||||
fmt = hasattr(self._pool, "formats")
|
||||
iqn = hasattr(self._pool, "iqn")
|
||||
src = self._pool.supports_property("source_path")
|
||||
src_b = src and not self.conn.is_remote()
|
||||
tgt = self._pool.supports_property("target_path")
|
||||
tgt_b = tgt and not self.conn.is_remote()
|
||||
host = self._pool.supports_property("host")
|
||||
fmt = self._pool.supports_property("formats")
|
||||
iqn = self._pool.supports_property("iqn")
|
||||
builddef, buildsens = self.get_build_default()
|
||||
|
||||
# Source path broswing is meaningless for net pools
|
||||
if self._pool.type in [Storage.StoragePool.TYPE_NETFS,
|
||||
Storage.StoragePool.TYPE_ISCSI,
|
||||
Storage.StoragePool.TYPE_SCSI]:
|
||||
if self._pool.type in [StoragePool.TYPE_NETFS,
|
||||
StoragePool.TYPE_ISCSI,
|
||||
StoragePool.TYPE_SCSI]:
|
||||
src_b = False
|
||||
|
||||
show_row("pool-target", tgt)
|
||||
@ -313,14 +309,15 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
show_row("pool-build", buildsens)
|
||||
show_row("pool-iqn", iqn)
|
||||
|
||||
self.widget("pool-target-path").get_child().set_text(self._pool.target_path)
|
||||
self.widget("pool-target-path").get_child().set_text(
|
||||
self._pool.target_path)
|
||||
self.widget("pool-target-button").set_sensitive(tgt_b)
|
||||
self.widget("pool-source-button").set_sensitive(src_b)
|
||||
self.widget("pool-build").set_active(builddef)
|
||||
|
||||
self.widget("pool-format").set_active(-1)
|
||||
if fmt:
|
||||
self.populate_pool_format(getattr(self._pool, "formats"))
|
||||
self.populate_pool_format(self._pool.list_formats("formats"))
|
||||
self.widget("pool-format").set_active(0)
|
||||
|
||||
self.populate_pool_sources()
|
||||
@ -385,13 +382,13 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
""" Return (default value, whether build option can be changed)"""
|
||||
if not self._pool:
|
||||
return (False, False)
|
||||
if self._pool.type in [Storage.StoragePool.TYPE_DIR,
|
||||
Storage.StoragePool.TYPE_FS,
|
||||
Storage.StoragePool.TYPE_NETFS]:
|
||||
if self._pool.type in [StoragePool.TYPE_DIR,
|
||||
StoragePool.TYPE_FS,
|
||||
StoragePool.TYPE_NETFS]:
|
||||
# Building for these simply entails creating a directory
|
||||
return (True, False)
|
||||
elif self._pool.type in [Storage.StoragePool.TYPE_LOGICAL,
|
||||
Storage.StoragePool.TYPE_DISK]:
|
||||
elif self._pool.type in [StoragePool.TYPE_LOGICAL,
|
||||
StoragePool.TYPE_DISK]:
|
||||
# This is a dangerous operation, anything (False, True)
|
||||
# should be assumed to be one.
|
||||
return (False, True)
|
||||
@ -489,8 +486,7 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
source_list = self.widget("pool-source-path")
|
||||
target_list = self.widget("pool-target-path")
|
||||
|
||||
pool = copy.copy(self._pool)
|
||||
|
||||
pool = None
|
||||
if source_list.get_active() != -1:
|
||||
pool = source_list.get_model()[source_list.get_active()][2]
|
||||
elif target_list.get_active() != -1:
|
||||
@ -498,55 +494,65 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
|
||||
return pool
|
||||
|
||||
def _make_stub_pool(self):
|
||||
pool = StoragePool(self.conn.get_backend())
|
||||
pool.type = self.get_config_type()
|
||||
return pool
|
||||
|
||||
def _validate_page_name(self, usepool=None):
|
||||
try:
|
||||
if usepool:
|
||||
self._pool = usepool
|
||||
else:
|
||||
self._pool = self._make_stub_pool()
|
||||
self._pool.name = self.get_config_name()
|
||||
except ValueError, e:
|
||||
return self.err.val_err(_("Pool Parameter Error"), e)
|
||||
|
||||
return True
|
||||
|
||||
def _validate_page_format(self):
|
||||
target = self.get_config_target_path()
|
||||
host = self.get_config_host()
|
||||
source = self.get_config_source_path()
|
||||
fmt = self.get_config_format()
|
||||
iqn = self.get_config_iqn()
|
||||
|
||||
if not self._validate_page_name(self.get_pool_to_validate()):
|
||||
return
|
||||
|
||||
try:
|
||||
self._pool.target_path = target
|
||||
if host:
|
||||
self._pool.host = host
|
||||
if source:
|
||||
self._pool.source_path = source
|
||||
if fmt:
|
||||
self._pool.format = fmt
|
||||
if iqn:
|
||||
self._pool.iqn = iqn
|
||||
|
||||
self._pool.validate()
|
||||
except ValueError, e:
|
||||
return self.err.val_err(_("Pool Parameter Error"), e)
|
||||
|
||||
buildval = self.widget("pool-build").get_active()
|
||||
buildsen = (self.widget("pool-build").get_sensitive() and
|
||||
self.widget("pool-build-box").get_visible())
|
||||
if buildsen and buildval:
|
||||
ret = self.err.yes_no(_("Building a pool of this type will "
|
||||
"format the source device. Are you "
|
||||
"sure you want to 'build' this pool?"))
|
||||
if not ret:
|
||||
return ret
|
||||
|
||||
return True
|
||||
|
||||
def validate(self, page):
|
||||
if page == PAGE_NAME:
|
||||
typ = self.get_config_type()
|
||||
name = self.get_config_name()
|
||||
conn = self.conn.get_backend()
|
||||
|
||||
try:
|
||||
self._pool_class = Storage.StoragePool.get_pool_class(typ)
|
||||
self._pool = self._pool_class(conn, name=name)
|
||||
except ValueError, e:
|
||||
return self.err.val_err(_("Pool Parameter Error"), e)
|
||||
|
||||
return True
|
||||
|
||||
return self._validate_page_name()
|
||||
elif page == PAGE_FORMAT:
|
||||
target = self.get_config_target_path()
|
||||
host = self.get_config_host()
|
||||
source = self.get_config_source_path()
|
||||
fmt = self.get_config_format()
|
||||
iqn = self.get_config_iqn()
|
||||
|
||||
tmppool = self.get_pool_to_validate()
|
||||
try:
|
||||
tmppool.target_path = target
|
||||
if host:
|
||||
tmppool.host = host
|
||||
if source:
|
||||
tmppool.source_path = source
|
||||
if fmt:
|
||||
tmppool.format = fmt
|
||||
if iqn:
|
||||
tmppool.iqn = iqn
|
||||
|
||||
tmppool.get_xml_config()
|
||||
except ValueError, e:
|
||||
return self.err.val_err(_("Pool Parameter Error"), e)
|
||||
|
||||
buildval = self.widget("pool-build").get_active()
|
||||
buildsen = (self.widget("pool-build").get_sensitive() and
|
||||
self.widget("pool-build-box").get_visible())
|
||||
if buildsen and buildval:
|
||||
ret = self.err.yes_no(_("Building a pool of this type will "
|
||||
"format the source device. Are you "
|
||||
"sure you want to 'build' this pool?"))
|
||||
if not ret:
|
||||
return ret
|
||||
|
||||
self._pool = tmppool
|
||||
return True
|
||||
return self._validate_page_format()
|
||||
|
||||
def _update_doc(self, param, infobox):
|
||||
doc = self._build_doc_str(param)
|
||||
@ -570,9 +576,9 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
def update_build_doc(self, *ignore):
|
||||
doc = ""
|
||||
docstr = ""
|
||||
if self._pool.type == Storage.StoragePool.TYPE_DISK:
|
||||
if self._pool.type == StoragePool.TYPE_DISK:
|
||||
docstr = _("Format the source device.")
|
||||
elif self._pool.type == Storage.StoragePool.TYPE_LOGICAL:
|
||||
elif self._pool.type == StoragePool.TYPE_LOGICAL:
|
||||
docstr = _("Create a logical volume group from the source device.")
|
||||
|
||||
if docstr:
|
||||
@ -586,9 +592,9 @@ class vmmCreatePool(vmmGObjectUI):
|
||||
|
||||
if docstr:
|
||||
doc = doctmpl % (prettyname, docstr)
|
||||
elif hasattr(self._pool_class, param):
|
||||
elif not self._pool or self._pool.supports_property(param):
|
||||
doc = doctmpl % (prettyname,
|
||||
getattr(self._pool_class, param).__doc__)
|
||||
getattr(StoragePool, param).__doc__)
|
||||
|
||||
return doc
|
||||
|
||||
|
@ -29,7 +29,7 @@ from gi.repository import Gdk
|
||||
from virtManager.baseclass import vmmGObjectUI
|
||||
from virtManager.asyncjob import vmmAsyncJob
|
||||
|
||||
from virtinst import Storage
|
||||
from virtinst import StorageVolume
|
||||
|
||||
DEFAULT_ALLOC = 0
|
||||
DEFAULT_CAP = 8192
|
||||
@ -47,7 +47,6 @@ class vmmCreateVolume(vmmGObjectUI):
|
||||
|
||||
self.name_hint = None
|
||||
self.vol = None
|
||||
self.vol_class = Storage.StoragePool.get_volume_for_pool(parent_pool.get_type())
|
||||
|
||||
self.builder.connect_signals({
|
||||
"on_vmm_create_vol_delete_event" : self.close,
|
||||
@ -101,7 +100,6 @@ class vmmCreateVolume(vmmGObjectUI):
|
||||
def set_parent_pool(self, conn, pool):
|
||||
self.conn = conn
|
||||
self.parent_pool = pool
|
||||
self.vol_class = Storage.StoragePool.get_volume_for_pool(self.parent_pool.get_type())
|
||||
|
||||
|
||||
def default_vol_name(self):
|
||||
@ -111,7 +109,7 @@ class vmmCreateVolume(vmmGObjectUI):
|
||||
suffix = self.default_suffix()
|
||||
ret = ""
|
||||
try:
|
||||
ret = Storage.StorageVolume.find_free_name(self.name_hint,
|
||||
ret = StorageVolume.find_free_name(self.name_hint,
|
||||
pool_object=self.parent_pool.get_backend(),
|
||||
suffix=suffix)
|
||||
ret = ret.rstrip(suffix)
|
||||
@ -122,11 +120,17 @@ class vmmCreateVolume(vmmGObjectUI):
|
||||
|
||||
def default_suffix(self):
|
||||
suffix = ""
|
||||
if self.vol_class == Storage.FileVolume:
|
||||
if self.vol.file_type == self.vol.TYPE_FILE:
|
||||
suffix = ".img"
|
||||
return suffix
|
||||
|
||||
def _make_stub_vol(self):
|
||||
self.vol = StorageVolume(self.conn.get_backend())
|
||||
self.vol.pool = self.parent_pool.get_backend()
|
||||
|
||||
def reset_state(self):
|
||||
self._make_stub_vol()
|
||||
|
||||
default_name = self.default_vol_name()
|
||||
self.widget("vol-name").set_text("")
|
||||
self.widget("vol-create").set_sensitive(False)
|
||||
@ -137,7 +141,7 @@ class vmmCreateVolume(vmmGObjectUI):
|
||||
self.populate_vol_format()
|
||||
self.populate_vol_suffix()
|
||||
|
||||
if len(self.vol_class.formats):
|
||||
if len(self.vol.list_formats()):
|
||||
self.widget("vol-format").set_sensitive(True)
|
||||
self.widget("vol-format").set_active(0)
|
||||
else:
|
||||
@ -174,11 +178,11 @@ class vmmCreateVolume(vmmGObjectUI):
|
||||
model = self.widget("vol-format").get_model()
|
||||
model.clear()
|
||||
|
||||
formats = self.vol_class.formats
|
||||
if hasattr(self.vol_class, "create_formats"):
|
||||
formats = getattr(self.vol_class, "create_formats")
|
||||
formats = self.vol.list_formats()
|
||||
if self.vol.list_create_formats() is not None:
|
||||
formats = self.vol.list_create_formats()
|
||||
|
||||
if (self.vol_class == Storage.FileVolume and
|
||||
if (self.vol.file_type == self.vol.TYPE_FILE and
|
||||
not self.conn.rhel6_defaults_caps()):
|
||||
newfmts = []
|
||||
for f in rhel6_file_whitelist:
|
||||
@ -190,10 +194,7 @@ class vmmCreateVolume(vmmGObjectUI):
|
||||
model.append([f, f])
|
||||
|
||||
def populate_vol_suffix(self):
|
||||
suffix = self.default_suffix()
|
||||
if self.vol_class == Storage.FileVolume:
|
||||
suffix = ".img"
|
||||
self.widget("vol-name-suffix").set_text(suffix)
|
||||
self.widget("vol-name-suffix").set_text(self.default_suffix())
|
||||
|
||||
def vol_name_changed(self, src):
|
||||
text = src.get_text()
|
||||
@ -275,13 +276,14 @@ class vmmCreateVolume(vmmGObjectUI):
|
||||
cap = self.widget("vol-capacity").get_value()
|
||||
|
||||
try:
|
||||
self.vol = self.vol_class(self.conn,
|
||||
name=volname,
|
||||
allocation=(alloc * 1024 * 1024),
|
||||
capacity=(cap * 1024 * 1024),
|
||||
pool=self.parent_pool.get_backend())
|
||||
self._make_stub_vol()
|
||||
self.vol.capacity = cap
|
||||
self.vol.name = volname
|
||||
self.vol.allocation = (alloc * 1024 * 1024)
|
||||
self.vol.capacity = (cap * 1024 * 1024)
|
||||
if fmt:
|
||||
self.vol.format = fmt
|
||||
self.vol.validate()
|
||||
except ValueError, e:
|
||||
return self.val_err(_("Volume Parameter Error"), e)
|
||||
return True
|
||||
|
@ -342,8 +342,8 @@ def can_delete(conn, vol, path):
|
||||
|
||||
if vol:
|
||||
# Managed storage
|
||||
if (vol.get_pool().get_type() ==
|
||||
virtinst.Storage.StoragePool.TYPE_ISCSI):
|
||||
if (vol.get_parent_pool().get_type() ==
|
||||
virtinst.StoragePool.TYPE_ISCSI):
|
||||
msg = _("Cannot delete iscsi share.")
|
||||
else:
|
||||
if conn.is_remote():
|
||||
|
@ -27,7 +27,7 @@ from gi.repository import Gdk
|
||||
# pylint: enable=E0611
|
||||
|
||||
from virtinst import VirtualDisk
|
||||
from virtinst import Storage
|
||||
from virtinst import StoragePool
|
||||
from virtinst import Interface
|
||||
|
||||
from virtManager import uihelpers
|
||||
@ -889,7 +889,7 @@ class vmmHost(vmmGObjectUI):
|
||||
"""<span size="large">%s Free</span> / <i>%s In Use</i>""" %
|
||||
(pool.get_pretty_available(), pool.get_pretty_allocation()))
|
||||
self.widget("pool-type").set_text(
|
||||
Storage.StoragePool.get_pool_type_desc(pool.get_type()))
|
||||
StoragePool.get_pool_type_desc(pool.get_type()))
|
||||
self.widget("pool-location").set_text(
|
||||
pool.get_target_path())
|
||||
self.widget("pool-state-icon").set_from_icon_name(
|
||||
@ -908,14 +908,13 @@ class vmmHost(vmmGObjectUI):
|
||||
self.widget("pool-stop").set_sensitive(active)
|
||||
self.widget("pool-start").set_sensitive(not active)
|
||||
self.widget("vol-add").set_sensitive(active)
|
||||
self.widget("vol-add").set_tooltip_text(_("Create new volume"))
|
||||
self.widget("vol-delete").set_sensitive(False)
|
||||
|
||||
if active:
|
||||
try:
|
||||
Storage.StoragePool.get_volume_for_pool(pool.get_type())
|
||||
except Exception, e:
|
||||
self.widget("vol-add").set_sensitive(False)
|
||||
self.widget("vol-add").set_tooltip_text(str(e))
|
||||
if active and not pool.supports_volume_creation():
|
||||
self.widget("vol-add").set_sensitive(False)
|
||||
self.widget("vol-add").set_tooltip_text(
|
||||
_("Pool does not support volume creation"))
|
||||
|
||||
def refresh_storage_pool(self, src_ignore, uuid):
|
||||
refresh_pool_in_list(self.widget("pool-list"), self.conn, uuid)
|
||||
@ -1312,7 +1311,7 @@ def populate_storage_pools(pool_list, conn):
|
||||
pool = conn.get_pool(uuid)
|
||||
|
||||
name = pool.get_name()
|
||||
typ = Storage.StoragePool.get_pool_type_desc(pool.get_type())
|
||||
typ = StoragePool.get_pool_type_desc(pool.get_type())
|
||||
label = "%s\n<span size='small'>%s</span>" % (name, typ)
|
||||
|
||||
model.append([uuid, label, pool.is_active(), per])
|
||||
|
@ -319,7 +319,7 @@ class vmmStorageBrowser(vmmGObjectUI):
|
||||
|
||||
def _do_finish(self, path=None):
|
||||
if not path:
|
||||
path = self.current_vol().get_path()
|
||||
path = self.current_vol().get_target_path()
|
||||
self.emit("storage-browse-finish", path)
|
||||
self.close()
|
||||
|
||||
|
@ -22,11 +22,58 @@
|
||||
from gi.repository import GObject
|
||||
# pylint: enable=E0611
|
||||
|
||||
from virtinst import Storage
|
||||
from virtinst import StoragePool, StorageVolume
|
||||
from virtinst import util
|
||||
|
||||
from virtManager.libvirtobject import vmmLibvirtObject
|
||||
from virtManager.storagevol import vmmStorageVolume
|
||||
|
||||
|
||||
class vmmStorageVolume(vmmLibvirtObject):
|
||||
def __init__(self, conn, backend, key):
|
||||
vmmLibvirtObject.__init__(self, conn, backend, key,
|
||||
parseclass=StorageVolume)
|
||||
|
||||
|
||||
##########################
|
||||
# Required class methods #
|
||||
##########################
|
||||
|
||||
def get_name(self):
|
||||
return self._get_xmlobj().name
|
||||
def _XMLDesc(self, flags):
|
||||
return self._backend.XMLDesc(flags)
|
||||
|
||||
|
||||
###########
|
||||
# Actions #
|
||||
###########
|
||||
|
||||
def get_parent_pool(self):
|
||||
pobj = self._backend.storagePoolLookupByVolume()
|
||||
return self.conn.get_pool_by_name(pobj.name())
|
||||
|
||||
def delete(self):
|
||||
self._backend.delete(0)
|
||||
self._backend = None
|
||||
|
||||
|
||||
#################
|
||||
# XML accessors #
|
||||
#################
|
||||
|
||||
def get_target_path(self):
|
||||
return self._get_xmlobj().target_path or ""
|
||||
def get_format(self):
|
||||
return self._get_xmlobj().format
|
||||
def get_capacity(self):
|
||||
return self._get_xmlobj().capacity
|
||||
def get_allocation(self):
|
||||
return self._get_xmlobj().allocation
|
||||
|
||||
def get_pretty_capacity(self):
|
||||
return util.pretty_bytes(self.get_capacity())
|
||||
def get_pretty_allocation(self):
|
||||
return util.pretty_bytes(self.get_allocation())
|
||||
|
||||
|
||||
class vmmStoragePool(vmmLibvirtObject):
|
||||
@ -35,26 +82,46 @@ class vmmStoragePool(vmmLibvirtObject):
|
||||
}
|
||||
|
||||
def __init__(self, conn, backend, key):
|
||||
vmmLibvirtObject.__init__(self, conn, backend, key)
|
||||
vmmLibvirtObject.__init__(self, conn, backend, key,
|
||||
parseclass=StoragePool)
|
||||
|
||||
self._uuid = key
|
||||
self._active = True
|
||||
self._support_isactive = None
|
||||
|
||||
self._volumes = {}
|
||||
self._support_isactive = None
|
||||
|
||||
self.tick()
|
||||
self.refresh()
|
||||
|
||||
# Required class methods
|
||||
|
||||
##########################
|
||||
# Required class methods #
|
||||
##########################
|
||||
|
||||
def get_name(self):
|
||||
return self._backend.name()
|
||||
return self._get_xmlobj().name
|
||||
def _XMLDesc(self, flags):
|
||||
return self._backend.XMLDesc(flags)
|
||||
def _define(self, xml):
|
||||
return self.conn.define_pool(xml)
|
||||
|
||||
|
||||
###########
|
||||
# Actions #
|
||||
###########
|
||||
|
||||
def is_active(self):
|
||||
return self._active
|
||||
def _backend_get_active(self):
|
||||
if self._support_isactive is None:
|
||||
self._support_isactive = self.conn.check_pool_support(
|
||||
self._backend,
|
||||
self.conn.SUPPORT_STORAGE_ISACTIVE)
|
||||
|
||||
if not self._support_isactive:
|
||||
return True
|
||||
return bool(self._backend.isActive())
|
||||
|
||||
def _set_active(self, state):
|
||||
if state == self._active:
|
||||
return
|
||||
@ -62,18 +129,21 @@ class vmmStoragePool(vmmLibvirtObject):
|
||||
self._active = state
|
||||
self.refresh_xml()
|
||||
|
||||
def is_active(self):
|
||||
return self._active
|
||||
def _kick_conn(self):
|
||||
self.conn.schedule_priority_tick(pollpool=True)
|
||||
def tick(self):
|
||||
self._set_active(self._backend_get_active())
|
||||
|
||||
def set_autostart(self, value):
|
||||
self._backend.setAutostart(value)
|
||||
def get_autostart(self):
|
||||
return self._backend.autostart()
|
||||
|
||||
def can_change_alloc(self):
|
||||
typ = self.get_type()
|
||||
return (typ in [Storage.StoragePool.TYPE_LOGICAL])
|
||||
|
||||
def get_uuid(self):
|
||||
return self._uuid
|
||||
|
||||
def _kick_conn(self):
|
||||
self.conn.schedule_priority_tick(pollpool=True)
|
||||
return (typ in [StoragePool.TYPE_LOGICAL])
|
||||
def supports_volume_creation(self):
|
||||
return self._get_xmlobj().supports_volume_creation()
|
||||
|
||||
def start(self):
|
||||
self._backend.create(0)
|
||||
@ -93,52 +163,6 @@ class vmmStoragePool(vmmLibvirtObject):
|
||||
self._backend = None
|
||||
self._kick_conn()
|
||||
|
||||
def set_autostart(self, value):
|
||||
self._backend.setAutostart(value)
|
||||
|
||||
def get_autostart(self):
|
||||
return self._backend.autostart()
|
||||
|
||||
def get_target_path(self):
|
||||
return util.xpath(self.get_xml(), "/pool/target/path") or ""
|
||||
|
||||
def get_allocation(self):
|
||||
return long(util.xpath(self.get_xml(), "/pool/allocation"))
|
||||
def get_available(self):
|
||||
return long(util.xpath(self.get_xml(), "/pool/available"))
|
||||
def get_capacity(self):
|
||||
return long(util.xpath(self.get_xml(), "/pool/capacity"))
|
||||
|
||||
def get_pretty_allocation(self):
|
||||
return util.pretty_bytes(self.get_allocation())
|
||||
def get_pretty_available(self):
|
||||
return util.pretty_bytes(self.get_available())
|
||||
def get_pretty_capacity(self):
|
||||
return util.pretty_bytes(self.get_capacity())
|
||||
|
||||
def get_type(self):
|
||||
return util.xpath(self.get_xml(), "/pool/@type")
|
||||
|
||||
def get_volumes(self):
|
||||
self.update_volumes()
|
||||
return self._volumes
|
||||
|
||||
def get_volume(self, uuid):
|
||||
return self._volumes[uuid]
|
||||
|
||||
def _backend_get_active(self):
|
||||
if self._support_isactive is None:
|
||||
self._support_isactive = self.conn.check_pool_support(
|
||||
self._backend,
|
||||
self.conn.SUPPORT_STORAGE_ISACTIVE)
|
||||
|
||||
if not self._support_isactive:
|
||||
return True
|
||||
return bool(self._backend.isActive())
|
||||
|
||||
def tick(self):
|
||||
self._set_active(self._backend_get_active())
|
||||
|
||||
def refresh(self):
|
||||
if not self.is_active():
|
||||
return
|
||||
@ -151,6 +175,18 @@ class vmmStoragePool(vmmLibvirtObject):
|
||||
self._backend.refresh(0)
|
||||
self.idle_add(cb)
|
||||
|
||||
|
||||
###################
|
||||
# Volume handling #
|
||||
###################
|
||||
|
||||
def get_volumes(self):
|
||||
self.update_volumes()
|
||||
return self._volumes
|
||||
|
||||
def get_volume(self, uuid):
|
||||
return self._volumes[uuid]
|
||||
|
||||
def update_volumes(self, refresh=False):
|
||||
if not self.is_active():
|
||||
self._volumes = {}
|
||||
@ -169,3 +205,29 @@ class vmmStoragePool(vmmLibvirtObject):
|
||||
self._backend.storageVolLookupByName(volname),
|
||||
volname)
|
||||
self._volumes = new_vol_list
|
||||
|
||||
|
||||
#################
|
||||
# XML accessors #
|
||||
#################
|
||||
|
||||
def get_type(self):
|
||||
return self._get_xmlobj().type
|
||||
def get_uuid(self):
|
||||
return self._get_xmlobj().uuid
|
||||
def get_target_path(self):
|
||||
return self._get_xmlobj().target_path or ""
|
||||
|
||||
def get_allocation(self):
|
||||
return self._get_xmlobj().allocation
|
||||
def get_available(self):
|
||||
return self._get_xmlobj().available
|
||||
def get_capacity(self):
|
||||
return self._get_xmlobj().capacity
|
||||
|
||||
def get_pretty_allocation(self):
|
||||
return util.pretty_bytes(self.get_allocation())
|
||||
def get_pretty_available(self):
|
||||
return util.pretty_bytes(self.get_available())
|
||||
def get_pretty_capacity(self):
|
||||
return util.pretty_bytes(self.get_capacity())
|
||||
|
@ -1,66 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2008 Red Hat, Inc.
|
||||
# Copyright (C) 2008 Cole Robinson <crobinso@redhat.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
from virtinst import util
|
||||
|
||||
from virtManager.libvirtobject import vmmLibvirtObject
|
||||
|
||||
|
||||
class vmmStorageVolume(vmmLibvirtObject):
|
||||
def __init__(self, conn, backend, key):
|
||||
vmmLibvirtObject.__init__(self, conn, backend, key)
|
||||
|
||||
self._name = key
|
||||
|
||||
# Required class methods
|
||||
def get_name(self):
|
||||
return self._name
|
||||
def _XMLDesc(self, flags):
|
||||
return self._backend.XMLDesc(flags)
|
||||
|
||||
def get_path(self):
|
||||
return self._backend.path()
|
||||
|
||||
def get_pool(self):
|
||||
pobj = self._backend.storagePoolLookupByVolume()
|
||||
return self.conn.get_pool_by_name(pobj.name())
|
||||
|
||||
def delete(self):
|
||||
self._backend.delete(0)
|
||||
self._backend = None
|
||||
|
||||
def get_target_path(self):
|
||||
return util.xpath(self.get_xml(), "/volume/target/path")
|
||||
|
||||
def get_format(self):
|
||||
return util.xpath(self.get_xml(), "/volume/target/format/@type")
|
||||
|
||||
def get_allocation(self):
|
||||
return long(util.xpath(self.get_xml(), "/volume/allocation"))
|
||||
def get_capacity(self):
|
||||
return long(util.xpath(self.get_xml(), "/volume/capacity"))
|
||||
|
||||
def get_pretty_capacity(self):
|
||||
return util.pretty_bytes(self.get_capacity())
|
||||
def get_pretty_allocation(self):
|
||||
return util.pretty_bytes(self.get_allocation())
|
||||
|
||||
def get_type(self):
|
||||
return util.xpath(self.get_xml(), "/volume/format/@type")
|
@ -1073,48 +1073,6 @@ def spin_get_helper(widget):
|
||||
return ret
|
||||
|
||||
|
||||
|
||||
def get_default_pool_path(conn):
|
||||
if conn.is_session_uri():
|
||||
return os.path.expanduser("~/VirtualMachines")
|
||||
return "/var/lib/libvirt/images"
|
||||
|
||||
|
||||
def get_default_pool_name(conn):
|
||||
ignore = conn
|
||||
return "default"
|
||||
|
||||
|
||||
def build_default_pool(vmmconn):
|
||||
"""
|
||||
Helper to build the 'default' storage pool
|
||||
"""
|
||||
conn = vmmconn.get_backend()
|
||||
|
||||
path = get_default_pool_path(vmmconn)
|
||||
name = get_default_pool_name(vmmconn)
|
||||
pool = None
|
||||
try:
|
||||
pool = conn.storagePoolLookupByName(name)
|
||||
except libvirt.libvirtError:
|
||||
pass
|
||||
|
||||
if pool:
|
||||
return
|
||||
|
||||
try:
|
||||
logging.debug("Attempting to build default pool with target '%s'",
|
||||
path)
|
||||
defpool = virtinst.Storage.DirectoryPool(conn=conn,
|
||||
name=name,
|
||||
target_path=path)
|
||||
newpool = defpool.install(build=True, create=True)
|
||||
newpool.setAutostart(True)
|
||||
except Exception, e:
|
||||
raise RuntimeError(_("Couldn't create default storage pool '%s': %s") %
|
||||
(path, str(e)))
|
||||
|
||||
|
||||
def get_ideal_path_info(conn, name):
|
||||
path = get_default_dir(conn)
|
||||
suffix = ".img"
|
||||
@ -1128,10 +1086,9 @@ def get_ideal_path(conn, name):
|
||||
|
||||
def get_default_pool(conn):
|
||||
pool = None
|
||||
default_name = get_default_pool_name(conn)
|
||||
for uuid in conn.list_pool_uuids():
|
||||
p = conn.get_pool(uuid)
|
||||
if p.get_name() == default_name:
|
||||
if p.get_name() == "default":
|
||||
pool = p
|
||||
|
||||
return pool
|
||||
@ -1179,7 +1136,7 @@ def get_default_path(conn, name, collidelist=None):
|
||||
if c and os.path.dirname(c) == pool.get_target_path():
|
||||
newcollidelist.append(os.path.basename(c))
|
||||
|
||||
path = virtinst.Storage.StorageVolume.find_free_name(name,
|
||||
path = virtinst.StorageVolume.find_free_name(name,
|
||||
pool_object=pool.get_backend(), suffix=suffix,
|
||||
collidelist=newcollidelist)
|
||||
|
||||
|
@ -29,9 +29,9 @@ from virtinst.clock import Clock
|
||||
from virtinst.cpu import CPU, CPUFeature
|
||||
from virtinst.seclabel import Seclabel
|
||||
|
||||
import virtinst.storage as Storage
|
||||
import virtinst.nodedev as NodeDeviceParser
|
||||
import virtinst.capabilities as CapabilitiesParser
|
||||
from virtinst.storage import StoragePool, StorageVolume
|
||||
from virtinst.interface import Interface, InterfaceProtocol
|
||||
|
||||
from virtinst.device import VirtualDevice
|
||||
|
@ -43,9 +43,6 @@ from virtinst import VirtualAudio
|
||||
from virtinst import VirtualDisk
|
||||
|
||||
|
||||
DEFAULT_POOL_PATH = "/var/lib/libvirt/images"
|
||||
DEFAULT_POOL_NAME = "default"
|
||||
|
||||
MIN_RAM = 64
|
||||
force = False
|
||||
quiet = False
|
||||
@ -312,33 +309,6 @@ def install_fail(guest):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def build_default_pool(guest):
|
||||
if not guest.conn.check_conn_support(guest.conn.SUPPORT_CONN_STORAGE):
|
||||
# VirtualDisk will raise an error for us
|
||||
return
|
||||
|
||||
pool = None
|
||||
try:
|
||||
pool = guest.conn.storagePoolLookupByName(DEFAULT_POOL_NAME)
|
||||
except libvirt.libvirtError:
|
||||
pass
|
||||
|
||||
if pool:
|
||||
return
|
||||
|
||||
try:
|
||||
logging.debug("Attempting to build default pool with target '%s'",
|
||||
DEFAULT_POOL_PATH)
|
||||
defpool = virtinst.Storage.DirectoryPool(conn=guest.conn,
|
||||
name=DEFAULT_POOL_NAME,
|
||||
target_path=DEFAULT_POOL_PATH)
|
||||
defpool.install(build=True, create=True, autostart=True)
|
||||
guest.conn.clear_cache()
|
||||
except Exception, e:
|
||||
raise RuntimeError(_("Couldn't create default storage pool '%s': %s") %
|
||||
(DEFAULT_POOL_PATH, str(e)))
|
||||
|
||||
|
||||
def partition(string, sep):
|
||||
if not string:
|
||||
return (None, None, None)
|
||||
@ -1413,18 +1383,18 @@ def _parse_disk_source(guest, path, pool, vol, size, fmt, sparse):
|
||||
|
||||
if path:
|
||||
abspath = os.path.abspath(path)
|
||||
if os.path.dirname(abspath) == DEFAULT_POOL_PATH:
|
||||
build_default_pool(guest)
|
||||
if os.path.dirname(abspath) == "/var/lib/libvirt/images":
|
||||
virtinst.StoragePool.build_default_pool(guest.conn)
|
||||
|
||||
elif pool:
|
||||
if not size:
|
||||
raise ValueError(_("Size must be specified with all 'pool='"))
|
||||
if pool == DEFAULT_POOL_NAME:
|
||||
build_default_pool(guest)
|
||||
if pool == "default":
|
||||
virtinst.StoragePool.build_default_pool(guest.conn)
|
||||
|
||||
|
||||
poolobj = guest.conn.storagePoolLookupByName(pool)
|
||||
vname = virtinst.Storage.StorageVolume.find_free_name(conn=guest.conn,
|
||||
vname = virtinst.StorageVolume.find_free_name(conn=guest.conn,
|
||||
pool_object=poolobj,
|
||||
name=guest.name,
|
||||
suffix=".img",
|
||||
@ -1433,10 +1403,10 @@ def _parse_disk_source(guest, path, pool, vol, size, fmt, sparse):
|
||||
volinst = virtinst.VirtualDisk.build_vol_install(
|
||||
guest.conn, vname, poolobj, size, sparse)
|
||||
if fmt:
|
||||
if not hasattr(volinst, "format"):
|
||||
if not volinst.supports_property("format"):
|
||||
raise ValueError(_("Format attribute not supported for this "
|
||||
"volume type"))
|
||||
setattr(volinst, "format", fmt)
|
||||
volinst.format = fmt
|
||||
|
||||
elif vol:
|
||||
if not vol.count("/"):
|
||||
@ -1446,8 +1416,8 @@ def _parse_disk_source(guest, path, pool, vol, size, fmt, sparse):
|
||||
voltuple = (vollist[0], vollist[1])
|
||||
logging.debug("Parsed volume: as pool='%s' vol='%s'",
|
||||
voltuple[0], voltuple[1])
|
||||
if voltuple[0] == DEFAULT_POOL_NAME:
|
||||
build_default_pool(guest)
|
||||
if voltuple[0] == "default":
|
||||
virtinst.StoragePool.build_default_pool(guest.conn)
|
||||
|
||||
volobj = virtinst.VirtualDisk.lookup_vol_object(guest.conn, voltuple)
|
||||
|
||||
|
@ -29,7 +29,7 @@ import libvirt
|
||||
from virtinst import Guest
|
||||
from virtinst import VirtualNetworkInterface
|
||||
from virtinst import VirtualDisk
|
||||
from virtinst import Storage
|
||||
from virtinst import StorageVolume
|
||||
from virtinst import util
|
||||
|
||||
|
||||
@ -333,12 +333,13 @@ class Cloner(object):
|
||||
# simply set input_vol on the dest vol_install
|
||||
if (clone_vol_install.pool.name() ==
|
||||
orig_disk.get_vol_object().storagePoolLookupByVolume().name()):
|
||||
newname = clone_vol_install.name
|
||||
vol_install = Storage.CloneVolume(self.conn,
|
||||
newname,
|
||||
orig_disk.get_vol_object())
|
||||
|
||||
vol_install = StorageVolume(self.conn)
|
||||
vol_install.input_vol = orig_disk.get_vol_object()
|
||||
vol_install.sync_input_vol()
|
||||
vol_install.name = clone_vol_install.name
|
||||
else:
|
||||
# Cross pool cloning
|
||||
# Deliberately don't sync input_vol params here
|
||||
clone_vol_install.input_vol = orig_disk.get_vol_object()
|
||||
vol_install = clone_vol_install
|
||||
else:
|
||||
|
@ -24,7 +24,7 @@ import statvfs
|
||||
|
||||
import libvirt
|
||||
|
||||
from virtinst import Storage
|
||||
from virtinst import StorageVolume
|
||||
from virtinst import util
|
||||
|
||||
|
||||
@ -146,15 +146,17 @@ def build_vol_install(conn, path, pool, size, sparse):
|
||||
os.path.dirname(path), pool.name(),
|
||||
os.path.basename(path))
|
||||
|
||||
volclass = Storage.StorageVolume.get_volume_for_pool(pool_object=pool)
|
||||
cap = (size * 1024 * 1024 * 1024)
|
||||
if sparse:
|
||||
alloc = 0
|
||||
else:
|
||||
alloc = cap
|
||||
|
||||
volinst = volclass(conn, name=os.path.basename(path),
|
||||
capacity=cap, allocation=alloc, pool=pool)
|
||||
volinst = StorageVolume(conn)
|
||||
volinst.pool = pool
|
||||
volinst.name = os.path.basename(path)
|
||||
volinst.capacity = cap
|
||||
volinst.allocation = alloc
|
||||
return volinst
|
||||
|
||||
|
||||
@ -206,11 +208,11 @@ class StorageCreator(_StorageBase):
|
||||
return
|
||||
|
||||
if self._vol_install:
|
||||
if not hasattr(self._vol_install, "format"):
|
||||
if not self._vol_install.supports_property("format"):
|
||||
raise ValueError(_("Storage type does not support format "
|
||||
"parameter."))
|
||||
if getattr(self._vol_install, "format", None) != val:
|
||||
setattr(self._vol_install, "format", val)
|
||||
if self._vol_install.format != val:
|
||||
self._vol_install.format = val
|
||||
|
||||
elif val != "raw":
|
||||
raise RuntimeError(_("Format cannot be specified for "
|
||||
@ -253,7 +255,7 @@ class StorageCreator(_StorageBase):
|
||||
|
||||
def get_driver_type(self):
|
||||
if self._vol_install:
|
||||
if hasattr(self._vol_install, "format"):
|
||||
if self._vol_install.supports_property("format"):
|
||||
return self._vol_install.format
|
||||
return "raw"
|
||||
|
||||
@ -266,7 +268,7 @@ class StorageCreator(_StorageBase):
|
||||
device)
|
||||
|
||||
if self.is_managed():
|
||||
return
|
||||
return self._vol_install.validate()
|
||||
|
||||
if devtype == "block":
|
||||
raise ValueError(_("Local block device path '%s' must "
|
||||
|
@ -26,7 +26,7 @@ import tempfile
|
||||
import urlgrabber
|
||||
|
||||
from virtinst import support
|
||||
from virtinst import Storage
|
||||
from virtinst import StoragePool, StorageVolume
|
||||
from virtinst import util
|
||||
from virtinst import Installer
|
||||
from virtinst import VirtualDisk
|
||||
@ -77,8 +77,10 @@ def _build_pool(conn, meter, path):
|
||||
name = util.generate_name("boot-scratch",
|
||||
conn.storagePoolLookupByName)
|
||||
logging.debug("Building storage pool: path=%s name=%s", path, name)
|
||||
poolbuild = Storage.DirectoryPool(conn, name=name,
|
||||
target_path=path)
|
||||
poolbuild = StoragePool(conn)
|
||||
poolbuild.type = poolbuild.TYPE_DIR
|
||||
poolbuild.name = name
|
||||
poolbuild.target_path = path
|
||||
|
||||
# Explicitly don't build? since if we are creating this directory
|
||||
# we probably don't have correct perms
|
||||
@ -105,8 +107,7 @@ def _upload_file(conn, meter, destpool, src):
|
||||
size = os.path.getsize(src)
|
||||
basename = os.path.basename(src)
|
||||
poolpath = util.xpath(destpool.XMLDesc(0), "/pool/target/path")
|
||||
name = Storage.StorageVolume.find_free_name(basename,
|
||||
pool_object=destpool)
|
||||
name = StorageVolume.find_free_name(basename, pool_object=destpool)
|
||||
if name != basename:
|
||||
logging.debug("Generated non-colliding volume name %s", name)
|
||||
|
||||
|
1460
virtinst/storage.py
1460
virtinst/storage.py
File diff suppressed because it is too large
Load Diff
@ -37,6 +37,15 @@ def listify(l):
|
||||
return l
|
||||
|
||||
|
||||
def xml_indent(xmlstr, level):
|
||||
xml = ""
|
||||
if not xmlstr:
|
||||
return xml
|
||||
if not level:
|
||||
return xmlstr
|
||||
return "\n".join((" " * level + l) for l in xmlstr.splitlines())
|
||||
|
||||
|
||||
def stat_disk(path):
|
||||
"""Returns the tuple (isreg, size)."""
|
||||
if not os.path.exists(path):
|
||||
|
@ -54,15 +54,6 @@ class _CtxCleanupWrapper(object):
|
||||
return getattr(self._ctx, attrname)
|
||||
|
||||
|
||||
def _indent(xmlstr, level):
|
||||
xml = ""
|
||||
if not xmlstr:
|
||||
return xml
|
||||
if not level:
|
||||
return xmlstr
|
||||
return "\n".join((" " * level + l) for l in xmlstr.splitlines())
|
||||
|
||||
|
||||
def _make_xml_context(node):
|
||||
doc = node.doc
|
||||
ctx = _CtxCleanupWrapper(doc.xpathNewContext())
|
||||
@ -956,7 +947,7 @@ class XMLBuilder(object):
|
||||
if not obj._xmlstate.is_build:
|
||||
use_xpath = obj.get_root_xpath().rsplit("/", 1)[0]
|
||||
indent = 2 * obj.get_root_xpath().count("/")
|
||||
newnode = libxml2.parseDoc(_indent(xml, indent)).children
|
||||
newnode = libxml2.parseDoc(util.xml_indent(xml, indent)).children
|
||||
_build_xpath_node(self._xmlstate.xml_ctx, use_xpath, newnode)
|
||||
obj._xmlstate._parse(None, self._xmlstate.xml_node)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user