This code was using the API equivalent of the virt-image tool,
however it's really unnecessary here, all we are doing is importing
an existing disk image which is an install option long provided by
virt-install. Merge the functionality into the virtinstall module
and convert it.
This code has actually been broken for about 6 months, since the
start_install signature was never updated for the qemu_net_type
change.
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
koan/imagecreate.py | 171 ++-------------------------------------------
koan/virtinstall.py | 47 +++++++++++--
tests/koan/virtinstall.py | 21 ++++++
3 files changed, 67 insertions(+), 172 deletions(-)
diff --git a/koan/imagecreate.py b/koan/imagecreate.py
index c336dcb..cf4db36 100644
--- a/koan/imagecreate.py
+++ b/koan/imagecreate.py
@@ -23,170 +23,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
"""
-import os, sys, time, stat
-import shutil
-import random
-import exceptions
-import errno
-import virtinst
-try:
- from virtinst import ImageParser, Guest, CapabilitiesParser, VirtualNetworkInterface
-except:
- # if this fails, this is ok, the user just won't be able to use image objects...
- # keeping this dynamic allows this to work on older EL.
- pass
-import libvirt
+import utils
+import virtinstall
-import app as koan
-
-#FIXME this was copied
-def random_mac():
- """
- from xend/server/netif.py
- Generate a random MAC address.
- Uses OUI 00-16-3E, allocated to
- Xensource, Inc. Last 3 fields are random.
- return: MAC address string
- """
- mac = [ 0x00, 0x16, 0x3e,
- random.randint(0x00, 0x7f),
- random.randint(0x00, 0xff),
- random.randint(0x00, 0xff) ]
- return ':'.join(map(lambda x: "%02x" % x, mac))
-
-
-def transform_arch(arch):
- if arch == "i386":
- return "i686"
- else:
- return arch
-
-def copy_image(original_file, new_location):
- shutil.copyfile(original_file, new_location)
- return new_location
-
-
-def process_disk(image, boot, file, location, target):
- image_location = copy_image(file, location)
- # Create the disk
- disk = ImageParser.Disk()
- disk.format = "raw"
- disk.file = image_location
- disk.use = "user"
- disk.id = image_location
- image.storage[disk.id] = disk
-
- #Create the drive
- drive = ImageParser.Drive()
- drive.id = image_location
- drive.target = target
- drive.disk = disk
- boot.disks.append(drive)
- #dev api
- #boot.drives.append(drive)
-
-
-def process_networks(domain, guest, profile_data, bridge):
- # Create a bridge or default network for every requested nic. If there are more
- # bridges then nics discard the last one.
- domain.interface = int(profile_data["network_count"])
- bridges = []
- #use the provided bridge first
- guest_bridge = bridge
- if guest_bridge is None:
- guest_bridge = profile_data["virt_bridge"]
-
- # Look for commas
- if (guest_bridge is not None) and (len(guest_bridge.strip()) > 0):
- if guest_bridge.find(",") == -1:
- bridges.append(guest_bridge)
- else:
- bridges == guest_bridge.split(",")
-
- for cnt in range(0,domain.interface):
- if cnt < len(bridges):
- nic = VirtualNetworkInterface(random_mac(), type="bridge", bridge =
bridges[cnt])
- #dev api
- #nic = VirtualNetworkInterface(random_mac(), type="bridge", bridge
= bridge, conn=guest.conn)
- else:
- default_network = virtinst.util.default_network()
- #dev api
- #default_network = virtinst.util.default_network(guest.conn)
- nic = VirtualNetworkInterface(random_mac(), type=default_network[0],
network=default_network[1])
- guest.nics.append(nic)
-
-def start_install(name=None,
- ram=None,
- disks=None,
- uuid=None,
- extra=None,
- vcpus=None,
- profile_data=None,
- arch=None,
- no_gfx=False,
- fullvirt=False,
- bridge=None,
- virt_type=None,
- virt_auto_boot=False,
- qemu_driver_type=None):
-
- #FIXME how to do a non-default connection
- #Can we drive off of virt-type?
- connection = None
-
- if (virt_type is None ) or (virt_type == "auto"):
- connection = virtinst.util.default_connection()
- elif virt_type.lower()[0:3] == "xen":
- connection = "xen"
- else:
- connection = "qemu:///system"
-
- connection = libvirt.open(connection)
- capabilities = virtinst.CapabilitiesParser.parse(connection.getCapabilities())
- image_arch = transform_arch(arch)
-
- image = ImageParser.Image()
- #dev api
- #image = ImageParser.Image(filename="") #FIXME, ImageParser should take in
None
- image.name = name
-
- domain = ImageParser.Domain()
- domain.vcpu = vcpus
- domain.memory = ram
- image.domain = domain
-
- boot = ImageParser.Boot()
- boot.type = "hvm" #FIXME HARDCODED
- boot.loader = "hd" #FIXME HARDCODED
- boot.arch = image_arch
- domain.boots.append(boot)
-
- #FIXME Several issues. Single Disk, type is hardcoded
- #And there is no way to provision with access to "file"
- process_disk(image, boot, profile_data["file"], disks[0][0],
"hda")
-
- #FIXME boot_index??
- installer = virtinst.ImageInstaller(boot_index = 0, image=image,
capabilities=capabilities)
- guest = virtinst.FullVirtGuest(connection = connection, installer=installer,
arch=image_arch)
-
- extra = extra.replace("&","&")
-
- guest.extraargs = extra
- guest.set_name(name)
- guest.set_memory(ram)
- guest.set_vcpus(vcpus)
-
- if not no_gfx:
- guest.set_graphics("vnc")
- else:
- guest.set_graphics(False)
-
- if uuid is not None:
- guest.set_uuid(uuid)
-
- process_networks(domain, guest, profile_data, bridge)
-
- guest.start_install()
-
- return "use virt-manager or reconnect with virsh console %s" % name
-
+def start_install(*args, **kwargs):
+ cmd = virtinstall.build_commandline("import", *args, **kwargs)
+ utils.subprocess_call(cmd)
diff --git a/koan/virtinstall.py b/koan/virtinstall.py
index a716d10..f7267a6 100755
--- a/koan/virtinstall.py
+++ b/koan/virtinstall.py
@@ -46,9 +46,19 @@ def _sanitize_disks(disks):
return ret
-def _sanitize_nics(nics, bridge, profile_bridge):
+def _sanitize_nics(nics, bridge, profile_bridge, network_count):
ret = []
+ if network_count is not None and not nics:
+ # Fill in some stub nics so we can take advantage of the loop logic
+ nics = {}
+ for i in range(int(network_count)):
+ nics["foo%s" % i] = {
+ "interface_type" : "na",
+ "mac_address": None,
+ "virt_bridge": None,
+ }
+
if not nics:
return ret
@@ -103,6 +113,14 @@ def build_commandline(uri,
qemu_driver_type=None,
qemu_net_type=None):
+ is_import = uri.startswith("import")
+ if is_import:
+ # We use the special value 'import' for imagecreate.py. Since
+ # it is connection agnostic, just let virt-install choose the
+ # best hypervisor.
+ uri = ""
+ fullvirt = None
+
is_xen = uri.startswith("xen")
is_qemu = uri.startswith("qemu")
if is_qemu:
@@ -111,8 +129,15 @@ def build_commandline(uri,
floppy = None
cdrom = None
location = None
+ importpath = None
- if profile_data.has_key("file"):
+ if is_import:
+ importpath = profile_data.get("file")
+ if not importpath:
+ raise koan.InfoException("Profile 'file' required for image
"
+ "install")
+
+ elif profile_data.has_key("file"):
if is_xen:
raise koan.InfoException("Xen does not work with --image yet")
@@ -146,7 +171,8 @@ def build_commandline(uri,
disks = _sanitize_disks(disks)
nics = _sanitize_nics(profile_data.get("interfaces"),
bridge,
- profile_data.get("virt_bridge"))
+ profile_data.get("virt_bridge"),
+ profile_data.get("network_count"))
if not nics:
# for --profile you get one NIC, go define a system if you want more.
# FIXME: can mac still be sent on command line in this case?
@@ -172,7 +198,9 @@ def build_commandline(uri,
net_model = qemu_net_type
disk_bus = qemu_driver_type
- cmd = "virt-install --connect %s " % uri
+ cmd = "virt-install "
+ if uri:
+ cmd += "--connect %s " % uri
cmd += "--name %s " % name
cmd += "--ram %s " % ram
@@ -192,8 +220,9 @@ def build_commandline(uri,
if is_qemu and virt_type:
cmd += "--virt-type %s " % virt_type
- if fullvirt or is_qemu:
- cmd += "--hvm "
+ if fullvirt or is_qemu or is_import:
+ if fullvirt is not None:
+ cmd += "--hvm "
if is_xen:
cmd += "--pxe "
@@ -201,6 +230,8 @@ def build_commandline(uri,
cmd += "--cdrom %s " % cdrom
elif location:
cmd += "--location %s " % location
+ elif importpath:
+ cmd += "--import "
if arch:
cmd += "--arch %s " % arch
@@ -221,6 +252,10 @@ def build_commandline(uri,
cmd += "--os-type %s " % distro
+ if importpath:
+ # This needs to be the first disk for import to work
+ cmd += "--disk path=%s " % importpath
+
for path, size, driver_type in disks:
print ("- adding disk: %s of size %s (driver type=%s)" %
(path, size, driver_type))
diff --git a/tests/koan/virtinstall.py b/tests/koan/virtinstall.py
index c57de1a..6898a10 100644
--- a/tests/koan/virtinstall.py
+++ b/tests/koan/virtinstall.py
@@ -105,3 +105,24 @@ class KoanVirtInstallTest(unittest.TestCase):
"--disk path=/dev/foo1,bus=virtio "
"--network bridge=br0,model=virtio --wait 0 --noautoconsole ")
)
+
+ def testImage(self):
+ cmd = build_commandline("import",
+ name="foo",
+ ram=256,
+ vcpus=1,
+ fullvirt=True,
+ bridge="br0,br2",
+ disks=[],
+ qemu_driver_type="virtio",
+ qemu_net_type="virtio",
+ profile_data = {
+ "file" : "/some/install/image.img",
+ "network_count" : 2,
+ })
+
+ self.assertEquals(cmd,
+ ("virt-install --name foo --ram 256 --vcpus 1 --vnc --import "
+ "--disk path=/some/install/image.img --network bridge=br0 "
+ "--network bridge=br2 --wait 0 --noautoconsole ")
+ )
--
1.7.7.5