Use XMLBuilder for Storage object handling

Simplify the API a bunch while we are at it, add tests, etc.
This commit is contained in:
Cole Robinson 2013-09-19 20:18:12 -04:00
parent 3db5cb5f06
commit aff0ddb259
53 changed files with 892 additions and 1573 deletions

View File

@ -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

View File

@ -3,7 +3,7 @@
<capacity>10737418240</capacity>
<allocation>5368709120</allocation>
<target>
<format type='raw'/>
<format type="raw"/>
<permissions>
<mode>0700</mode>
<owner>10736</owner>

View File

@ -1,4 +1,3 @@
<?xml version="1.0"?>
<volume>
<name>pool-dir-volclone</name>
<key>/some/target/path/pool-dir-vol</key>

View File

@ -3,7 +3,7 @@
<capacity>10737418240</capacity>
<allocation>5368709120</allocation>
<target>
<format type='raw'/>
<format type="raw"/>
<permissions>
<mode>0700</mode>
<owner>10736</owner>

View File

@ -1,4 +1,4 @@
<pool type='dir'>
<pool type="dir">
<name>pool-dir</name>
<uuid>10010511-4100-1051-1410-010511410010</uuid>
<target>

View File

@ -1,4 +1,3 @@
<?xml version="1.0"?>
<volume>
<name>pool-disk-volclone</name>
<key>/some/target/path/pool-disk-vol</key>

View File

@ -3,6 +3,7 @@
<capacity>10737418240</capacity>
<allocation>5368709120</allocation>
<target>
<format type="none"/>
<permissions>
<mode>0700</mode>
<owner>10736</owner>

View File

@ -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>

View File

@ -3,7 +3,7 @@
<capacity>10737418240</capacity>
<allocation>5368709120</allocation>
<target>
<format type='raw'/>
<format type="raw"/>
<permissions>
<mode>0700</mode>
<owner>10736</owner>

View File

@ -1,4 +1,3 @@
<?xml version="1.0"?>
<volume>
<name>pool-fs-volclone</name>
<key>/some/target/path/pool-fs-vol</key>

View File

@ -3,7 +3,7 @@
<capacity>10737418240</capacity>
<allocation>5368709120</allocation>
<target>
<format type='raw'/>
<format type="raw"/>
<permissions>
<mode>0700</mode>
<owner>10736</owner>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -1,4 +1,3 @@
<?xml version="1.0"?>
<volume>
<name>pool-logical-volclone</name>
<key>/dev/pool-logical/pool-logical-vol</key>

View File

@ -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>

View File

@ -1,4 +1,4 @@
<pool type='mpath'>
<pool type="mpath">
<name>pool-mpath</name>
<uuid>10911297-1161-0410-9112-971161041091</uuid>
<target>

View File

@ -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>

View File

@ -3,7 +3,7 @@
<capacity>10737418240</capacity>
<allocation>5368709120</allocation>
<target>
<format type='raw'/>
<format type="raw"/>
<permissions>
<mode>0700</mode>
<owner>10736</owner>

View File

@ -1,4 +1,3 @@
<?xml version="1.0"?>
<volume>
<name>pool-netfs-volclone</name>
<key>/some/target/path/pool-netfs-vol</key>

View File

@ -3,7 +3,7 @@
<capacity>10737418240</capacity>
<allocation>5368709120</allocation>
<target>
<format type='raw'/>
<format type="raw"/>
<permissions>
<mode>0700</mode>
<owner>10736</owner>

View File

@ -1,4 +1,4 @@
<pool type='netfs'>
<pool type="netfs">
<name>pool-netfs</name>
<uuid>11010111-6102-1151-1010-111610211511</uuid>
<source>

View File

@ -1,4 +1,4 @@
<pool type='scsi'>
<pool type="scsi">
<name>pool-scsi</name>
<uuid>11599115-1051-1599-1151-051159911510</uuid>
<source>

View File

@ -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)

View 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>

View 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>

View 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>

View 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>

View File

@ -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 #
##############

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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():

View File

@ -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])

View File

@ -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()

View File

@ -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())

View File

@ -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")

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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 "

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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):

View File

@ -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)