virt-install: support network --disk's

Handle type=network in devicedisk.py, and wire up all the network fields
for virt-install --disk. Right now it requires manually spelling out
all the protocol, name, host/port etc fields.

The one 'magic' bit is that VirtualDisk.path will be a pretty URL when
all those network fields are specified. This is keeps things mostly
working in various parts of the code where we expect 'path' to be an
identifier for a VirtualDisk.
This commit is contained in:
Cole Robinson 2014-12-06 18:33:11 -05:00
parent c5f5827499
commit cd305da3f8
8 changed files with 159 additions and 11 deletions

View File

@ -77,6 +77,18 @@
<source volume="some-rbd-vol" pool="rbd-ceph"/>
<target dev="hdd" bus="ide"/>
</disk>
<disk type="network" device="disk">
<source protocol="http" name="/path/to/my/file">
<host name="example.com" port="8000"/>
</source>
<target dev="sdb" bus="scsi"/>
</disk>
<disk type="network" device="disk">
<source protocol="nbd">
<host transport="unix" socket="/tmp/socket"/>
</source>
<target dev="sdc" bus="scsi"/>
</disk>
<controller type="usb" index="0" model="ich9-ehci1">
<address type="pci" domain="0" bus="0" slot="4" function="7"/>
</controller>
@ -226,6 +238,18 @@
<source volume="some-rbd-vol" pool="rbd-ceph"/>
<target dev="hdd" bus="ide"/>
</disk>
<disk type="network" device="disk">
<source protocol="http" name="/path/to/my/file">
<host name="example.com" port="8000"/>
</source>
<target dev="sdb" bus="scsi"/>
</disk>
<disk type="network" device="disk">
<source protocol="nbd">
<host transport="unix" socket="/tmp/socket"/>
</source>
<target dev="sdc" bus="scsi"/>
</disk>
<controller type="usb" index="0" model="ich9-ehci1">
<address type="pci" domain="0" bus="0" slot="4" function="7"/>
</controller>

View File

@ -562,6 +562,8 @@ c.add_compare("""--hvm --pxe \
--disk device=cdrom,bus=sata,read_bytes_sec=1,read_iops_sec=2,total_bytes_sec=10,total_iops_sec=20,write_bytes_sec=5,write_iops_sec=6 \
--disk size=1 \
--disk source_pool=rbd-ceph,source_volume=some-rbd-vol \
--disk source_protocol=http,source_host_name=example.com,source_host_port=8000,source_name=/path/to/my/file,bus=scsi \
--disk source_protocol=nbd,source_host_transport=unix,source_host_socket=/tmp/socket,bus=scsi \
--serial tcp,host=:2222,mode=bind,protocol=telnet \
--filesystem /source,/target,mode=squash \
--network user,mac=12:34:56:78:11:22,portgroup=foo \

View File

@ -68,6 +68,22 @@
<target dev='vdb' bus='virtio'/>
<readonly/>
</disk>
<disk type='network' device='disk'>
<driver name='qemu' type='raw'/>
<source protocol='rbd' name='pool/image'>
<host name='mon1.example.org' port='6321'/>
<host name='mon2.example.org' port='6322'/>
<host name='mon3.example.org' port='6322'/>
</source>
<target dev='vdc' bus='virtio'/>
</disk>
<disk type='network' device='disk'>
<driver name='qemu' type='raw'/>
<source protocol='nbd'>
<host transport='unix' socket='/var/run/nbdsock'/>
</source>
<target dev='vdd' bus='virtio'/>
</disk>
<input type="mouse" bus="ps2"/>
<graphics type="vnc" display=":3.4" xauth="/tmp/.Xauthority"/>
<console type="pty"/>

View File

@ -36,9 +36,12 @@
<source dev="/dev/null"/>
<target dev="hdd" bus="ide"/>
</disk>
<disk type="block" device="cdrom">
<disk type="network" device="cdrom">
<target dev="sda" bus="scsi"/>
<readonly/>
<source protocol="http" name="/my/file">
<host name="exaaaaample.com"/>
</source>
</disk>
<disk type="file" device="floppy">
<target dev="fda" bus="fdc"/>
@ -66,10 +69,26 @@
</disk>
<disk type="volume" device="disk">
<driver name="qemu"/>
<source pool="anotherPool" volume="foobar"/>
<source pool="anotherPool" volume="newvol"/>
<target dev="vdb" bus="virtio"/>
<readonly/>
</disk>
<disk type="network" device="disk">
<driver name="qemu" type="raw"/>
<source protocol="gluster" name="new-val/vol">
<host name="diff.example.org" port="1234"/>
<host name="mon2.example.org" port="6322"/>
<host name="mon3.example.org" port="6322"/>
</source>
<target dev="vdc" bus="virtio"/>
</disk>
<disk type="network" device="disk">
<driver name="qemu" type="raw"/>
<source protocol="nbd">
<host transport="unix" socket="/var/run/nbdsock"/>
</source>
<target dev="vdd" bus="virtio"/>
</disk>
<input type="mouse" bus="ps2"/>
<graphics type="vnc" display=":3.4" xauth="/tmp/.Xauthority"/>
<console type="pty"/>

View File

@ -347,6 +347,14 @@ class XMLParseTest(unittest.TestCase):
check("bus", "ide", "fdc")
check("error_policy", "stop", None)
disk = _get_disk("sda")
check = self._make_checker(disk)
check("source_protocol", None, "http")
check("source_name", None, "/my/file")
check("source_host_name", None, "exaaaaample.com")
disk.sync_path_props()
check("path", "http://exaaaaample.com/my/file")
disk = _get_disk("fda")
check = self._make_checker(disk)
check("path", None, "/dev/default-pool/default-vol")
@ -369,6 +377,22 @@ class XMLParseTest(unittest.TestCase):
disk = _get_disk("vdb")
check = self._make_checker(disk)
check("source_pool", "defaultPool", "anotherPool")
check("source_volume", "foobar", "newvol")
disk = _get_disk("vdc")
check = self._make_checker(disk)
check("source_protocol", "rbd", "gluster")
check("source_name", "pool/image", "new-val/vol")
check("source_host_name", "mon1.example.org", "diff.example.org")
check("source_host_port", 6321, 1234)
check("path", "gluster://diff.example.org:1234/new-val/vol")
disk = _get_disk("vdd")
check = self._make_checker(disk)
check("source_protocol", "nbd")
check("source_host_transport", "unix")
check("source_host_socket", "/var/run/nbdsock")
check("path", "nbd+unix:///var/run/nbdsock")
self._alter_compare(guest.get_xml_config(), outfile)

View File

@ -1486,6 +1486,13 @@ class ParserDisk(VirtCLIParser):
self.set_param("source_pool", "source_pool")
self.set_param("source_volume", "source_volume")
self.set_param("source_name", "source_name")
self.set_param("source_protocol", "source_protocol")
self.set_param("source_host_name", "source_host_name")
self.set_param("source_host_port", "source_host_port")
self.set_param("source_host_socket", "source_host_socket")
self.set_param("source_host_transport", "source_host_transport")
self.set_param("path", "path")
self.set_param("device", "device")
self.set_param("bus", "bus")

View File

@ -139,7 +139,8 @@ class VirtualDisk(VirtualDevice):
TYPE_BLOCK = "block"
TYPE_DIR = "dir"
TYPE_VOLUME = "volume"
types = [TYPE_FILE, TYPE_BLOCK, TYPE_DIR, TYPE_VOLUME]
TYPE_NETWORK = "network"
types = [TYPE_FILE, TYPE_BLOCK, TYPE_DIR, TYPE_NETWORK]
IO_MODE_NATIVE = "native"
IO_MODE_THREADS = "threads"
@ -490,7 +491,9 @@ class VirtualDisk(VirtualDevice):
"driver_name", "driver_type",
"driver_cache", "driver_discard", "driver_io", "error_policy",
"_source_file", "_source_dev", "_source_dir",
"source_volume", "source_pool",
"source_volume", "source_pool", "source_protocol", "source_name",
"source_host_name", "source_host_port",
"source_host_transport", "source_host_socket",
"target", "bus",
]
@ -506,6 +509,10 @@ class VirtualDisk(VirtualDevice):
#############################
def _get_path(self):
if self.type == VirtualDisk.TYPE_NETWORK:
# Fill in a completed URL for virt-manager UI, path comparison, etc
return self._url_from_network_source()
if self._storage_creator:
return self._storage_creator.path
return self._storage_backend.path
@ -585,11 +592,42 @@ class VirtualDisk(VirtualDevice):
source_pool = XMLProperty("./source/@pool")
source_volume = XMLProperty("./source/@volume")
def _get_default_type(self):
source_name = XMLProperty("./source/@name")
source_protocol = XMLProperty("./source/@protocol")
# Technically multiple host lines can be listed
source_host_name = XMLProperty("./source/host/@name")
source_host_port = XMLProperty("./source/host/@port", is_int=True)
source_host_transport = XMLProperty("./source/host/@transport")
source_host_socket = XMLProperty("./source/host/@socket")
def _url_from_network_source(self):
ret = self.source_protocol
if self.source_host_transport:
ret += "+%s" % self.source_host_transport
ret += "://"
if self.source_host_name:
ret += self.source_host_name
if self.source_host_port:
ret += ":" + str(self.source_host_port)
if self.source_name:
if not self.source_name.startswith("/"):
ret += "/"
ret += self.source_name
elif self.source_host_socket:
if not self.source_host_socket.startswith("/"):
ret += "/"
ret += self.source_host_socket
return ret
def _get_default_type(self, skip_backend=False):
if self.source_pool or self.source_volume:
return VirtualDisk.TYPE_VOLUME
if self.source_protocol:
return VirtualDisk.TYPE_NETWORK
if self._storage_creator:
return self._storage_creator.get_dev_type()
if not self.__storage_backend and skip_backend:
return self.TYPE_FILE
return self._storage_backend.get_dev_type()
type = XMLProperty("./@type", default_cb=_get_default_type)
@ -602,6 +640,12 @@ class VirtualDisk(VirtualDevice):
self._source_dir = None
self.source_volume = None
self.source_pool = None
self.source_name = None
self.source_protocol = None
self.source_host_name = None
self.source_host_port = None
self.source_host_transport = None
self.source_host_socket = None
def _disk_type_to_object_prop_name(self):
disk_type = self.type
@ -673,8 +717,11 @@ class VirtualDisk(VirtualDevice):
path = None
vol_object = None
parent_pool = None
is_network = False
typ = self._get_default_type(skip_backend=True)
is_network = (typ == VirtualDisk.TYPE_NETWORK)
if self.source_pool and self.source_volume:
if typ == VirtualDisk.TYPE_VOLUME:
conn = self.conn
is_weak = "weakref" in str(type(conn))
if is_weak:
@ -695,7 +742,7 @@ class VirtualDisk(VirtualDevice):
path = self._get_xmlpath()
return diskbackend.StorageBackend(self.conn, path,
vol_object, parent_pool)
vol_object, parent_pool, is_network=is_network)
def _get_storage_backend(self):
if self.__storage_backend is None:
@ -747,7 +794,8 @@ class VirtualDisk(VirtualDevice):
self.driver_type = self._get_default_driver_type()
# Need to retrigger this if self.type changed
self._set_xmlpath(path)
if path:
self._set_xmlpath(path)
def wants_storage_creation(self):
"""

View File

@ -373,12 +373,14 @@ class StorageBackend(_StorageBase):
Class that carries all the info about any existing storage that
the disk references
"""
def __init__(self, conn, path, vol_object, parent_pool):
def __init__(self, conn, path, vol_object, parent_pool,
is_network=False):
_StorageBase.__init__(self, conn)
self._vol_object = vol_object
self._parent_pool = parent_pool
self._path = path
self._is_network = is_network
if self._vol_object is not None:
self._path = None
@ -437,10 +439,14 @@ class StorageBackend(_StorageBase):
self._exists = True
elif self._vol_object:
self._exists = True
elif not self._conn.is_remote() and os.path.exists(self._path):
elif (not self._is_network and
not self._conn.is_remote() and
os.path.exists(self._path)):
self._exists = True
elif self._parent_pool:
self._exists = False
elif self._is_network:
self._exists = True
elif (self._conn.is_remote() and
not _can_auto_manage(self._path)):
# This allows users to pass /dev/sdX and we don't try to
@ -466,7 +472,9 @@ class StorageBackend(_StorageBase):
else:
self._dev_type = "file"
elif self._path and not self._conn.is_remote():
elif (not self._is_network and
self._path and
not self._conn.is_remote()):
if os.path.isdir(self._path):
self._dev_type = "dir"
elif util.stat_disk(self._path)[0]: