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