virtinst: Combine ImageInstaller and ImageParser code
They aren't touched much these days, so unify the files for clarity.
This commit is contained in:
parent
accff84ecc
commit
01629d3f2c
|
@ -14,11 +14,11 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA.
|
||||
|
||||
import unittest
|
||||
import virtinst
|
||||
import virtinst.cli
|
||||
import virtinst.ImageParser
|
||||
import os
|
||||
import unittest
|
||||
|
||||
import virtinst.cli
|
||||
from virtinst import virtimage
|
||||
|
||||
from tests import utils
|
||||
|
||||
|
@ -39,7 +39,7 @@ class TestImageParser(unittest.TestCase):
|
|||
xml = f.read()
|
||||
f.close()
|
||||
|
||||
img = virtinst.ImageParser.parse(xml, ".")
|
||||
img = virtimage.parse(xml, ".")
|
||||
self.assertEqual("test-image", img.name)
|
||||
self.assertTrue(img.domain)
|
||||
self.assertEqual(5, len(img.storage))
|
||||
|
@ -53,14 +53,14 @@ class TestImageParser(unittest.TestCase):
|
|||
xml = f.read()
|
||||
f.close()
|
||||
|
||||
img = virtinst.ImageParser.parse(xml, ".")
|
||||
img = virtimage.parse(xml, ".")
|
||||
self.assertEqual(2, img.domain.interface)
|
||||
|
||||
def testBadArch(self):
|
||||
"""Makes sure we sanitize i386->i686"""
|
||||
image = virtinst.ImageParser.parse_file(self.basedir +
|
||||
image = virtimage.parse_file(self.basedir +
|
||||
"image-bad-arch.xml")
|
||||
virtinst.ImageInstaller(self.conn, image, 0)
|
||||
virtimage.ImageInstaller(self.conn, image, 0)
|
||||
self.assertTrue(True)
|
||||
|
||||
def testStorageFormat(self):
|
||||
|
@ -69,7 +69,7 @@ class TestImageParser(unittest.TestCase):
|
|||
|
||||
def _image2XMLhelper(self, image_xml, output_xmls, qemu=False):
|
||||
image2guestdir = self.basedir + "image2guest/"
|
||||
image = virtinst.ImageParser.parse_file(self.basedir + image_xml)
|
||||
image = virtimage.parse_file(self.basedir + image_xml)
|
||||
if type(output_xmls) is not list:
|
||||
output_xmls = [output_xmls]
|
||||
|
||||
|
@ -78,7 +78,7 @@ class TestImageParser(unittest.TestCase):
|
|||
|
||||
for idx in range(len(output_xmls)):
|
||||
fname = output_xmls[idx]
|
||||
inst = virtinst.ImageInstaller(conn, image, boot_index=idx)
|
||||
inst = virtimage.ImageInstaller(conn, image, boot_index=idx)
|
||||
capsguest, capsdomain = inst.get_caps_guest()
|
||||
if capsguest.os_type == "hvm":
|
||||
g = utils.get_basic_fullyvirt_guest(typ=gtype)
|
||||
|
|
|
@ -23,10 +23,9 @@
|
|||
import sys
|
||||
import urlgrabber.progress as progress
|
||||
|
||||
import virtinst
|
||||
import virtinst.ImageParser
|
||||
import virtinst.cli as cli
|
||||
from virtinst.cli import fail, print_stdout, print_stderr
|
||||
from virtinst import virtimage
|
||||
|
||||
import optparse
|
||||
from optparse import OptionGroup
|
||||
|
@ -138,7 +137,7 @@ def main(conn=None):
|
|||
conn = cli.getConnection(options.connect)
|
||||
|
||||
try:
|
||||
image = virtinst.ImageParser.parse_file(options.image)
|
||||
image = virtimage.parse_file(options.image)
|
||||
except RuntimeError, msg:
|
||||
fail("%s '%s': %s" % (_("Cannot parse"), options.image, msg))
|
||||
|
||||
|
@ -150,7 +149,7 @@ def main(conn=None):
|
|||
|
||||
|
||||
# Build the Installer instance
|
||||
installer = virtinst.ImageInstaller(conn, image, boot_index=options.boot)
|
||||
installer = virtimage.ImageInstaller(conn, image, boot_index=options.boot)
|
||||
guest = conn.caps.build_virtinst_guest(conn, *installer.get_caps_guest())
|
||||
guest.installer = installer
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import virtconv.vmcfg as vmcfg
|
|||
import virtconv.diskcfg as diskcfg
|
||||
import virtconv.netdevcfg as netdevcfg
|
||||
from virtinst import Guest
|
||||
from virtinst import ImageParser
|
||||
from virtinst import virtimage
|
||||
|
||||
from xml.sax.saxutils import escape
|
||||
import re
|
||||
|
@ -85,8 +85,6 @@ def export_os_params(vm):
|
|||
ostype = None
|
||||
osvariant = None
|
||||
|
||||
# TODO: Shouldn't be directly using _OS_TYPES here. virt-image libs (
|
||||
# ImageParser?) should handle this info
|
||||
ostype = Guest._OS_TYPES.get(vm.os_type) # pylint: disable=W0212
|
||||
if ostype:
|
||||
osvariant = ostype.get('variants').get(vm.os_variant)
|
||||
|
@ -204,7 +202,7 @@ class virtimage_parser(formats.parser):
|
|||
output = f.read()
|
||||
f.close()
|
||||
|
||||
ImageParser.parse(output, input_file)
|
||||
virtimage.parse(output, input_file)
|
||||
except RuntimeError:
|
||||
return False
|
||||
return True
|
||||
|
@ -222,7 +220,7 @@ class virtimage_parser(formats.parser):
|
|||
f.close()
|
||||
|
||||
logging.debug("Importing virt-image XML:\n%s", output)
|
||||
config = ImageParser.parse(output, input_file)
|
||||
config = virtimage.parse(output, input_file)
|
||||
except Exception, e:
|
||||
raise ValueError(_("Couldn't import file '%s': %s") %
|
||||
(input_file, e))
|
||||
|
@ -245,11 +243,11 @@ class virtimage_parser(formats.parser):
|
|||
for d in boot.drives:
|
||||
disk = d.disk
|
||||
format_mappings = {
|
||||
ImageParser.Disk.FORMAT_RAW: diskcfg.DISK_FORMAT_RAW,
|
||||
ImageParser.Disk.FORMAT_VMDK: diskcfg.DISK_FORMAT_VMDK,
|
||||
ImageParser.Disk.FORMAT_QCOW: diskcfg.DISK_FORMAT_QCOW,
|
||||
ImageParser.Disk.FORMAT_QCOW2: diskcfg.DISK_FORMAT_QCOW2,
|
||||
ImageParser.Disk.FORMAT_VDI: diskcfg.DISK_FORMAT_VDI,
|
||||
virtimage.Disk.FORMAT_RAW: diskcfg.DISK_FORMAT_RAW,
|
||||
virtimage.Disk.FORMAT_VMDK: diskcfg.DISK_FORMAT_VMDK,
|
||||
virtimage.Disk.FORMAT_QCOW: diskcfg.DISK_FORMAT_QCOW,
|
||||
virtimage.Disk.FORMAT_QCOW2: diskcfg.DISK_FORMAT_QCOW2,
|
||||
virtimage.Disk.FORMAT_VDI: diskcfg.DISK_FORMAT_VDI,
|
||||
}
|
||||
|
||||
fmt = None
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
# Installer for images
|
||||
#
|
||||
# Copyright 2007 Red Hat, Inc.
|
||||
# David Lutterkort <dlutter@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.
|
||||
|
||||
import os
|
||||
|
||||
from virtinst import Installer
|
||||
from virtinst import ImageParser
|
||||
from virtinst import CapabilitiesParser
|
||||
from virtinst import VirtualDisk
|
||||
|
||||
|
||||
class ImageInstaller(Installer):
|
||||
"""
|
||||
Installer for virt-image-based guests
|
||||
"""
|
||||
_has_install_phase = False
|
||||
|
||||
def __init__(self, conn, image, boot_index=None):
|
||||
Installer.__init__(self, conn)
|
||||
|
||||
self._image = image
|
||||
|
||||
# Set boot _boot_caps/_boot_parameters
|
||||
if boot_index is None:
|
||||
self._boot_caps = match_boots(self.conn.caps,
|
||||
self.image.domain.boots)
|
||||
if self._boot_caps is None:
|
||||
raise RuntimeError(_("Could not find suitable boot "
|
||||
"descriptor for this host"))
|
||||
else:
|
||||
if (boot_index < 0 or
|
||||
(boot_index + 1) > len(image.domain.boots)):
|
||||
raise ValueError(_("boot_index out of range."))
|
||||
self._boot_caps = image.domain.boots[boot_index]
|
||||
|
||||
# Set up internal caps.guest object
|
||||
self._guest = self.conn.caps.guestForOSType(self.boot_caps.type,
|
||||
self.boot_caps.arch)
|
||||
if self._guest is None:
|
||||
raise RuntimeError(_("Unsupported virtualization type: %s %s" %
|
||||
(self.boot_caps.type, self.boot_caps.arch)))
|
||||
self._domain = self._guest.bestDomainType()
|
||||
|
||||
|
||||
|
||||
# Custom ImageInstaller methods
|
||||
def get_caps_guest(self):
|
||||
return self._guest, self._domain
|
||||
|
||||
def get_image(self):
|
||||
return self._image
|
||||
image = property(get_image)
|
||||
|
||||
def get_boot_caps(self):
|
||||
return self._boot_caps
|
||||
boot_caps = property(get_boot_caps)
|
||||
|
||||
|
||||
# General Installer methods
|
||||
def _prepare(self, guest, meter, scratchdir):
|
||||
ignore = scratchdir
|
||||
ignore = meter
|
||||
|
||||
self._make_disks()
|
||||
|
||||
for f in ['pae', 'acpi', 'apic']:
|
||||
if self.boot_caps.features[f] & CapabilitiesParser.FEATURE_ON:
|
||||
guest.features[f] = True
|
||||
elif self.boot_caps.features[f] & CapabilitiesParser.FEATURE_OFF:
|
||||
guest.features[f] = False
|
||||
|
||||
guest.os.kernel = self.boot_caps.kernel
|
||||
guest.os.initrd = self.boot_caps.initrd
|
||||
guest.os.kernel_args = self.boot_caps.cmdline
|
||||
|
||||
# Private methods
|
||||
def _get_bootdev(self, isinstall, guest):
|
||||
return self.boot_caps.bootdev
|
||||
|
||||
def _make_disks(self):
|
||||
for drive in self.boot_caps.drives:
|
||||
path = self._abspath(drive.disk.file)
|
||||
size = None
|
||||
if drive.disk.size is not None:
|
||||
size = float(drive.disk.size) / 1024
|
||||
|
||||
# FIXME: This is awkward; the image should be able to express
|
||||
# whether the disk is expected to be there or not independently
|
||||
# of its classification, especially for user disks
|
||||
# FIXME: We ignore the target for the mapping in m.target
|
||||
if (drive.disk.use == ImageParser.Disk.USE_SYSTEM and
|
||||
not os.path.exists(path)):
|
||||
raise RuntimeError(_("System disk %s does not exist") % path)
|
||||
|
||||
device = VirtualDisk.DEVICE_DISK
|
||||
if drive.disk.format == ImageParser.Disk.FORMAT_ISO:
|
||||
device = VirtualDisk.DEVICE_CDROM
|
||||
|
||||
disk = VirtualDisk(self.conn)
|
||||
disk.path = path
|
||||
disk.device = device
|
||||
disk.target = drive.target
|
||||
|
||||
disk.set_create_storage(size=size, fmt=drive.disk.format)
|
||||
disk.validate()
|
||||
self.install_devices.append(disk)
|
||||
|
||||
def _abspath(self, p):
|
||||
return self.image.abspath(p)
|
||||
|
||||
|
||||
def match_boots(capabilities, boots):
|
||||
for b in boots:
|
||||
for g in capabilities.guests:
|
||||
if b.type == g.os_type and b.arch == g.arch:
|
||||
found = True
|
||||
for bf in b.features.names():
|
||||
if not b.features[bf] & g.features[bf]:
|
||||
found = False
|
||||
break
|
||||
if found:
|
||||
return b
|
||||
return None
|
|
@ -53,7 +53,6 @@ from virtinst.Installer import (ContainerInstaller, ImportInstaller,
|
|||
LiveCDInstaller, PXEInstaller, Installer)
|
||||
|
||||
from virtinst.DistroInstaller import DistroInstaller
|
||||
from virtinst.ImageInstaller import ImageInstaller
|
||||
|
||||
from virtinst.Guest import Guest
|
||||
from virtinst.CloneManager import Cloner
|
||||
|
|
|
@ -25,6 +25,8 @@ import os
|
|||
import urlgrabber
|
||||
|
||||
from virtinst import CapabilitiesParser
|
||||
from virtinst import Installer
|
||||
from virtinst import VirtualDisk
|
||||
from virtinst import util
|
||||
|
||||
|
||||
|
@ -319,3 +321,117 @@ def parse_file(filename):
|
|||
xml = f.read()
|
||||
f.close()
|
||||
return parse(xml, filename=filename)
|
||||
|
||||
|
||||
class ImageInstaller(Installer):
|
||||
"""
|
||||
Installer for virt-image-based guests
|
||||
"""
|
||||
_has_install_phase = False
|
||||
|
||||
def __init__(self, conn, image, boot_index=None):
|
||||
Installer.__init__(self, conn)
|
||||
|
||||
self._image = image
|
||||
|
||||
# Set boot _boot_caps/_boot_parameters
|
||||
if boot_index is None:
|
||||
self._boot_caps = match_boots(self.conn.caps,
|
||||
self.image.domain.boots)
|
||||
if self._boot_caps is None:
|
||||
raise RuntimeError(_("Could not find suitable boot "
|
||||
"descriptor for this host"))
|
||||
else:
|
||||
if (boot_index < 0 or
|
||||
(boot_index + 1) > len(image.domain.boots)):
|
||||
raise ValueError(_("boot_index out of range."))
|
||||
self._boot_caps = image.domain.boots[boot_index]
|
||||
|
||||
# Set up internal caps.guest object
|
||||
self._guest = self.conn.caps.guestForOSType(self.boot_caps.type,
|
||||
self.boot_caps.arch)
|
||||
if self._guest is None:
|
||||
raise RuntimeError(_("Unsupported virtualization type: %s %s" %
|
||||
(self.boot_caps.type, self.boot_caps.arch)))
|
||||
self._domain = self._guest.bestDomainType()
|
||||
|
||||
|
||||
|
||||
# Custom ImageInstaller methods
|
||||
def get_caps_guest(self):
|
||||
return self._guest, self._domain
|
||||
|
||||
def get_image(self):
|
||||
return self._image
|
||||
image = property(get_image)
|
||||
|
||||
def get_boot_caps(self):
|
||||
return self._boot_caps
|
||||
boot_caps = property(get_boot_caps)
|
||||
|
||||
|
||||
# General Installer methods
|
||||
def _prepare(self, guest, meter, scratchdir):
|
||||
ignore = scratchdir
|
||||
ignore = meter
|
||||
|
||||
self._make_disks()
|
||||
|
||||
for f in ['pae', 'acpi', 'apic']:
|
||||
if self.boot_caps.features[f] & CapabilitiesParser.FEATURE_ON:
|
||||
guest.features[f] = True
|
||||
elif self.boot_caps.features[f] & CapabilitiesParser.FEATURE_OFF:
|
||||
guest.features[f] = False
|
||||
|
||||
guest.os.kernel = self.boot_caps.kernel
|
||||
guest.os.initrd = self.boot_caps.initrd
|
||||
guest.os.kernel_args = self.boot_caps.cmdline
|
||||
|
||||
# Private methods
|
||||
def _get_bootdev(self, isinstall, guest):
|
||||
return self.boot_caps.bootdev
|
||||
|
||||
def _make_disks(self):
|
||||
for drive in self.boot_caps.drives:
|
||||
path = self._abspath(drive.disk.file)
|
||||
size = None
|
||||
if drive.disk.size is not None:
|
||||
size = float(drive.disk.size) / 1024
|
||||
|
||||
# FIXME: This is awkward; the image should be able to express
|
||||
# whether the disk is expected to be there or not independently
|
||||
# of its classification, especially for user disks
|
||||
# FIXME: We ignore the target for the mapping in m.target
|
||||
if (drive.disk.use == Disk.USE_SYSTEM and
|
||||
not os.path.exists(path)):
|
||||
raise RuntimeError(_("System disk %s does not exist") % path)
|
||||
|
||||
device = VirtualDisk.DEVICE_DISK
|
||||
if drive.disk.format == Disk.FORMAT_ISO:
|
||||
device = VirtualDisk.DEVICE_CDROM
|
||||
|
||||
disk = VirtualDisk(self.conn)
|
||||
disk.path = path
|
||||
disk.device = device
|
||||
disk.target = drive.target
|
||||
|
||||
disk.set_create_storage(size=size, fmt=drive.disk.format)
|
||||
disk.validate()
|
||||
self.install_devices.append(disk)
|
||||
|
||||
def _abspath(self, p):
|
||||
return self.image.abspath(p)
|
||||
|
||||
|
||||
def match_boots(capabilities, boots):
|
||||
for b in boots:
|
||||
for g in capabilities.guests:
|
||||
if b.type == g.os_type and b.arch == g.arch:
|
||||
found = True
|
||||
for bf in b.features.names():
|
||||
if not b.features[bf] & g.features[bf]:
|
||||
found = False
|
||||
break
|
||||
if found:
|
||||
return b
|
||||
return None
|
Loading…
Reference in New Issue