diff --git a/man/virt-install.rst b/man/virt-install.rst
index f2741f654..9cc433605 100644
--- a/man/virt-install.rst
+++ b/man/virt-install.rst
@@ -969,20 +969,33 @@ GUEST OS OPTIONS
``--os-variant``, ``--osinfo``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-**Syntax:** ``--os-variant`` OS_VARIANT
+**Syntax:** ``--os-variant`` [OS_VARIANT|OPT1=VAL1,...]
Optimize the guest configuration for a specific operating system (ex.
'fedora29', 'rhel7', 'win10'). While not required, specifying this
options is HIGHLY RECOMMENDED, as it can greatly increase performance
by specifying virtio among other guest tweaks.
-By default, virt-install will attempt to auto detect this value from
-the install media (currently only supported for URL installs). Autodetection
-can be disabled with the special value 'none'. Autodetection can be
-forced with the special value 'auto'.
+The simplest usage is ``--os-variant OS-NAME``, for example
+``--os-variant fedora32``. ``--os-variant`` supports explicit suboption
+syntax as well:
+
+``name=``, ``short-id=``
+ The OS name/short-id from libosinfo. Examples: ``fedora32``, ``win10``
+
+``id=``
+ The full URL style libosinfo ID. For example, ``name=win10`` is
+ the same as ``id=http://microsoft.com/win/10``
+
+``detect=on|off``
+ Whether virt-install should attempt OS detection from the specified
+ install media. Detection is presently only attempted for URL and
+ CDROM installs, and is not 100% reliable.
+
+By default, virt-install will use ``--os-variant detect=on``.
Use the command "osinfo-query os" to get the list of the accepted OS
-variants.
+variant names.
diff --git a/man/virt-xml.rst b/man/virt-xml.rst
index bb521cd42..7ff7ceca7 100644
--- a/man/virt-xml.rst
+++ b/man/virt-xml.rst
@@ -194,6 +194,8 @@ GUEST OS OPTIONS
Use the command "osinfo-query os" to get the list of the accepted OS
variants.
+ See virt-install(1) documentation for more details about ``--os-variant``
+
XML OPTIONS
===========
diff --git a/tests/data/cli/compare/virt-install-fake-http.xml b/tests/data/cli/compare/virt-install-fake-http.xml
index 8292e63ab..13928dbda 100644
--- a/tests/data/cli/compare/virt-install-fake-http.xml
+++ b/tests/data/cli/compare/virt-install-fake-http.xml
@@ -1,14 +1,9 @@
- rhel6.0
+ vm1
00000000-1111-2222-3333-444444444444
-
-
-
-
-
65536
65536
- 2
+ 1
hvm
/VIRTINST-TESTSUITE/vmlinuz
@@ -44,16 +39,11 @@
- rhel6.0
+ vm1
00000000-1111-2222-3333-444444444444
-
-
-
-
-
65536
65536
- 2
+ 1
hvm
diff --git a/tests/data/cli/compare/virt-install-osinfo-url-with-disk.xml b/tests/data/cli/compare/virt-install-osinfo-url-with-disk.xml
index 37b7e575e..28ebf6530 100644
--- a/tests/data/cli/compare/virt-install-osinfo-url-with-disk.xml
+++ b/tests/data/cli/compare/virt-install-osinfo-url-with-disk.xml
@@ -1,9 +1,9 @@
- fedora26
+ fedora27
00000000-1111-2222-3333-444444444444
-
+
65536
@@ -60,11 +60,11 @@
- fedora26
+ fedora27
00000000-1111-2222-3333-444444444444
-
+
65536
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 8a7ddff5d..76bf684e9 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -861,15 +861,14 @@ c.add_valid("--location location=%(TREEDIR)s") # Directory tree URL install
c.add_valid("--location %(TREEDIR)s --initrd-inject virt-install --extra-args ks=file:/virt-install") # initrd-inject
c.add_valid("--hvm --location %(TREEDIR)s --extra-args console=ttyS0") # Directory tree URL install with extra-args
c.add_valid("--paravirt --location %(TREEDIR)s") # Paravirt location
-c.add_valid("--paravirt --location %(TREEDIR)s --os-variant none") # Paravirt location with --os-variant none
c.add_valid("--location %(TREEDIR)s --os-variant fedora12") # URL install with manual os-variant
c.add_valid("--cdrom %(EXISTIMG2)s --os-variant win2k3") # HVM windows install with disk
c.add_valid("--cdrom %(EXISTIMG2)s --os-variant win2k3 --print-step 2") # HVM windows install, print 3rd stage XML
c.add_valid("--pxe --autostart") # --autostart flag
c.add_compare("--cdrom http://example.com/path/to/some.iso", "cdrom-url")
-c.add_compare("--pxe --print-step all", "simple-pxe") # Diskless PXE install
-c.add_compare("--location ftp://example.com", "fake-ftp") # fake ftp:// install using urlfetcher.py mocking
-c.add_compare("--location https://foobar.com", "fake-http") # fake https:// install using urlfetcher.py mocking
+c.add_compare("--pxe --print-step all --os-variant none", "simple-pxe") # Diskless PXE install
+c.add_compare("--location ftp://example.com --os-variant auto", "fake-ftp") # fake ftp:// install using urlfetcher.py mocking
+c.add_compare("--location https://foobar.com --os-variant detect=no", "fake-http") # fake https:// install using urlfetcher.py mocking, but also hit --os-variant detect=no
c.add_compare("--connect %(URI-KVM)s --install fedora26", "osinfo-url") # getting URL from osinfo
c.add_invalid("--pxe --virt-type bogus") # Bogus virt-type
c.add_invalid("--pxe --arch bogus") # Bogus arch
@@ -884,7 +883,7 @@ c.add_invalid("--arch i686 --install fedora26", grep="does not have a URL locati
c.add_invalid("-c foo --cdrom bar", grep="Cannot specify both -c") # check for ambiguous -c and --cdrom collision
c.add_invalid("-c qemu:///system", grep="looks like a libvirt URI") # error for the ambiguous -c vs --connect
c.add_invalid("--location /", grep="Error validating install location") # detect_distro failure
-c.add_invalid("--os-variant foo://bar", grep="Unknown libosinfo ID") # bad full id
+c.add_invalid("--os-variant id=foo://bar", grep="Unknown libosinfo ID") # bad full id
c.add_invalid("--location http://testsuitefail.com", grep="installable distribution") # will trigger a particular mock failure
@@ -897,8 +896,8 @@ c.add_valid("--paravirt --import") # PV Import install
c.add_valid("--paravirt --print-xml 1") # print single XML, implied import install
c.add_valid("--hvm --import --wait 0", grep="Treating --wait 0 as --noautoconsole") # --wait 0 is the same as --noautoconsole
c.add_compare("-c %(EXISTIMG2)s --osinfo win2k3 --vcpus cores=4 --controller usb,model=none", "w2k3-cdrom") # HVM windows install with disk
-c.add_compare("--connect %(URI-KVM)s --install fedora26 --disk size=20", "osinfo-url-with-disk") # filling in defaults, but with disk specified
-c.add_compare("--connect %(URI-KVM)s --pxe --os-variant debianbuster --disk none", "osinfo-multiple-short-id", prerun_check=lambda: not OSDB.lookup_os("debianbuster")) # test plumbing for multiple short ids
+c.add_compare("--connect %(URI-KVM)s --install fedora26 --os-variant fedora27 --disk size=20", "osinfo-url-with-disk") # filling in defaults, but with disk specified, and making sure we don't overwrite --os-variant
+c.add_compare("--connect %(URI-KVM)s --pxe --os-variant short-id=debianbuster --disk none", "osinfo-multiple-short-id", prerun_check=lambda: not OSDB.lookup_os("debianbuster")) # test plumbing for multiple short ids
c.add_invalid("--hvm --import --wait 2", grep="exceeded specified time limit") # --wait positive number, but test suite hack
c.add_invalid("--hvm --import --wait -1", grep="exceeded specified time limit") # --wait -1, but test suite hack
c.add_invalid("--hvm --import --wait", grep="exceeded specified time limit") # --wait aka --wait -1, but test suite hack
@@ -979,7 +978,7 @@ c.add_compare("--os-variant fedora-unknown --file %(EXISTIMG1)s --location %(TRE
c.add_compare("--test-media-detection %(TREEDIR)s --arch x86_64 --hvm", "test-url-detection") # --test-media-detection
c.add_compare("--os-variant http://fedoraproject.org/fedora/20 --disk %(EXISTIMG1)s,device=floppy --disk %(NEWIMG1)s,size=.01,format=vmdk --location %(TREEDIR)s --extra-args console=ttyS0 --quiet", "quiet-url", prerun_check=has_old_osinfo) # Quiet URL install should make no noise
c.add_compare("--cdrom %(EXISTIMG2)s --file %(EXISTIMG1)s --os-variant win2k3 --sound --controller usb", "kvm-win2k3-cdrom") # HVM windows install with disk
-c.add_compare("--os-variant ubuntusaucy --nodisks --boot cdrom --virt-type qemu --cpu Penryn --input tablet --boot uefi --graphics vnc", "qemu-plain") # plain qemu
+c.add_compare("--os-variant name=ubuntusaucy --nodisks --boot cdrom --virt-type qemu --cpu Penryn --input tablet --boot uefi --graphics vnc", "qemu-plain") # plain qemu
c.add_compare("--os-variant fedora20 --nodisks --boot network --graphics default --arch i686 --rng none", "qemu-32-on-64", prerun_check=has_old_osinfo) # 32 on 64
# ppc64 tests
diff --git a/virtinst/cli.py b/virtinst/cli.py
index 2c07a959e..5a707301a 100644
--- a/virtinst/cli.py
+++ b/virtinst/cli.py
@@ -480,7 +480,8 @@ def get_domain_and_guest(conn, domstr):
def _get_completer_parsers():
return VIRT_PARSERS + [ParserCheck, ParserLocation,
- ParserUnattended, ParserInstall, ParserCloudInit, ParserXML]
+ ParserUnattended, ParserInstall, ParserCloudInit, ParserXML,
+ ParserOSVariant]
def _virtparser_completer(prefix, **kwargs):
@@ -1790,42 +1791,66 @@ def parse_location(optstr):
########################
class OSVariantData(object):
- def __init__(self, os_variant):
- self._rawstr = os_variant
- self._default_auto = True
+ def __init__(self):
self._name = None
- if not self._rawstr:
+ self._id = None
+ self._detect = False
+
+ def set_compat_str(self, rawstr):
+ if rawstr is None or rawstr == "auto":
+ # The default behavior
+ self._detect = True
return
- self._default_auto = False
- if self.is_none or self.is_auto:
- return
- if "://" in self._rawstr:
- osobj = OSDB.lookup_os_by_full_id(self._rawstr, raise_error=True)
+ if rawstr == "none":
+ self._name = "generic"
+ elif "://" in rawstr:
+ self._id = rawstr
else:
- osobj = OSDB.lookup_os(self._rawstr, raise_error=True)
- self._name = osobj.name
+ self._name = rawstr
- def set_installdata_name(self, name):
- # osname set via --install os=X, but if --os-variant also
- # explicitly set, we don't want to overwrite it
- if self._default_auto:
- self._default_auto = False
- self._name = name
+ def validate(self):
+ osobj = None
+ if self._id:
+ osobj = OSDB.lookup_os_by_full_id(self._id, raise_error=True)
+ elif self._name:
+ osobj = OSDB.lookup_os(self._name, raise_error=True)
+ if osobj:
+ self._name = osobj.name
- @property
- def is_none(self):
- return self._rawstr == "none"
- @property
- def is_auto(self):
- return self._rawstr == "auto" or self._default_auto
- @property
- def name(self):
+ def is_generic_requested(self):
+ return self._detect is False or self._name == "generic"
+ def is_detect(self):
+ return self._detect
+ def get_name(self):
return self._name
+class ParserOSVariant(VirtCLIParser):
+ cli_arg_name = "os-variant"
+ supports_clearxml = False
+
+ @classmethod
+ def _init_class(cls, **kwargs):
+ VirtCLIParser._init_class(**kwargs)
+ cls.add_arg("name", "_name")
+ cls.add_arg("short-id", "_name")
+ cls.add_arg("id", "_id")
+ cls.add_arg("detect", "_detect", is_onoff=True)
+
+ def parse(self, inst):
+ if "=" not in str(self.optstr):
+ inst.set_compat_str(self.optstr)
+ return
+ return super().parse(inst)
+
+
def parse_os_variant(optstr):
- return OSVariantData(optstr)
+ data = OSVariantData()
+ parser = ParserOSVariant(optstr)
+ parser.parse(data)
+ data.validate()
+ return data
###########################
diff --git a/virtinst/virtinstall.py b/virtinst/virtinstall.py
index a73da352c..0e29cc689 100644
--- a/virtinst/virtinstall.py
+++ b/virtinst/virtinstall.py
@@ -361,8 +361,7 @@ def show_guest_warnings(options, guest, osdata):
# Limit it to hvm x86 guests which presently our defaults
# only really matter for
if (guest.osinfo.name == "generic" and
- not osdata.is_none and
- not osdata.name == "generic" and
+ not osdata.is_generic_requested() and
guest.os.is_x86() and guest.os.is_hvm()):
log.warning(_("No operating system detected, VM performance may "
"suffer. Specify an OS with --os-variant for optimal results."))
@@ -535,12 +534,12 @@ def installer_detect_distro(guest, installer, osdata):
# OS name has to be set firstly whenever --os-variant is passed,
# otherwise it won't be respected when the installer creates the
# Distro Store.
- if osdata.name:
- guest.set_os_name(osdata.name)
+ if osdata.get_name():
+ guest.set_os_name(osdata.get_name())
# This also validates the install location
autodistro = installer.detect_distro(guest)
- if osdata.is_auto and autodistro:
+ if osdata.is_detect() and autodistro:
guest.set_os_name(autodistro)
except ValueError as e:
fail(_("Error validating install location: %s") % str(e))
@@ -566,9 +565,7 @@ def _build_options_guest(conn, options):
def build_guest_instance(conn, options):
installdata = cli.parse_install(options.install)
- osdata = cli.parse_os_variant(options.os_variant)
- if installdata.os:
- osdata.set_installdata_name(installdata.os)
+ osdata = cli.parse_os_variant(options.os_variant or installdata.os)
if options.reinstall:
dummy1, guest, dummy2 = cli.get_domain_and_guest(conn, options.reinstall)
diff --git a/virtinst/virtxml.py b/virtinst/virtxml.py
index 4cb542e28..0fe94c47b 100644
--- a/virtinst/virtxml.py
+++ b/virtinst/virtxml.py
@@ -51,8 +51,8 @@ def set_os_variant(options, guest):
return
osdata = cli.parse_os_variant(options.os_variant)
- if osdata.name:
- guest.set_os_name(osdata.name)
+ if osdata.get_name():
+ guest.set_os_name(osdata.get_name())
def defined_xml_is_unchanged(conn, domain, original_xml):