virt-install: Add --install OSNAME

Replace the unreleased --os-variant OSNAME,install=location with just

  --install OSNAME

Unwind the --unattended dependency on upfront --os-variant while
we are at it, since they are all intertwined. Now we can just do:

  virt-install --install OSNAME
and
  virt-install --install OSNAME --unattended
This commit is contained in:
Cole Robinson 2019-06-13 20:26:26 -04:00
parent 839eea3587
commit 21723706f5
5 changed files with 51 additions and 53 deletions

View File

@ -811,7 +811,7 @@ 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("--connect %(URI-KVM)s --os-variant fedora26,install=location", "osinfo-url") # getting URL from osinfo
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
c.add_invalid("--livecd") # LiveCD with no media
@ -820,11 +820,11 @@ c.add_invalid("--pxe --boot menu=foobar")
c.add_invalid("--cdrom %(EXISTIMG1)s --extra-args console=ttyS0") # cdrom fail w/ extra-args
c.add_invalid("--hvm --boot kernel=%(TREEDIR)s/pxeboot/vmlinuz,initrd=%(TREEDIR)s/pxeboot/initrd.img,kernel_args='foo bar' --initrd-inject virt-install") # initrd-inject with manual kernel/initrd
c.add_invalid("--disk none --location kernel=/dev/null,initrd=/dev/null") # --location with manual kernel/initrd, but not URL
c.add_invalid("--os-variant winxp,install=location", grep="does not have a URL location") # no URL for winxp
c.add_invalid("--os-variant fedora28,install=fribber", grep="Unknown --os-variant install value") # unknown install= value
c.add_invalid("--arch i686 --os-variant fedora26,install=location", grep="does not have a URL location for the i686") # there's no URL for i686
c.add_invalid("--install winxp", grep="does not have a URL location") # no URL for winxp
c.add_invalid("--arch i686 --install fedora26", grep="does not have a URL location for the i686") # there's no URL for i686
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 = vinst.add_category("single-disk-install", "--nographics --noautoconsole --disk %(EXISTIMG1)s")
c.add_valid("--hvm --import") # FV Import install
@ -859,11 +859,11 @@ c.add_valid("--connect %s --pxe --disk size=1" % utils.URIs.test_defaultpool_col
####################
c = vinst.add_category("unattended-install", "--connect %(URI-KVM)s --nographics --noautoconsole --disk none", prerun_check=no_osinfo_unattend_cb)
c.add_compare("--os-variant fedora26 --unattended profile=desktop,admin-password=foobar,user-password=blah,product-key=1234", "osinfo-url-unattended") # unattended install for fedora, using initrd injection
c.add_compare("--os-variant win7 --cdrom %(ISO-WIN7)s --unattended profile=desktop,admin-password=foobar", "osinfo-win7-unattended") # unattended install for win7
c.add_compare("--os-variant fedora26 --unattended profile=jeos,admin-password=123456 --cdrom %(ISO-F26-NETINST)s", "osinfo-netinst-unattended") # triggering the special netinst checking code
c.add_compare("--install fedora26 --unattended profile=desktop,admin-password=foobar,user-password=blah,product-key=1234", "osinfo-url-unattended") # unattended install for fedora, using initrd injection
c.add_compare("--cdrom %(ISO-WIN7)s --unattended profile=desktop,admin-password=foobar", "osinfo-win7-unattended") # unattended install for win7
c.add_compare("--os-variant fedora26 --unattended profile=jeos,admin-password=123456 --location %(ISO-F26-NETINST)s", "osinfo-netinst-unattended") # triggering the special netinst checking code
c.add_compare("--os-variant silverblue29 --location http://example.com", "network-install-resources") # triggering network-install resources override
c.add_valid("--os-variant fedora26 --unattended", grep="Using unattended profile 'desktop'") # filling in default 'desktop' profile
c.add_valid("--pxe --os-variant fedora26 --unattended", grep="Using unattended profile 'desktop'") # filling in default 'desktop' profile
c.add_invalid("--os-variant fedora26 --unattended profile=jeos --location http://example.foo", grep="admin-password") # will trigger admin-password required error
c.add_invalid("--os-variant fedora26 --unattended profile=jeos --location http://example.foo", grep="admin-password") # will trigger admin-password required error
c.add_invalid("--os-variant debian9 --unattended profile=desktop,admin-password=foobar --location http://example.foo", grep="user-password") # will trigger user-password required error

View File

@ -140,14 +140,8 @@ def convert_old_disks(options):
def convert_old_os_options(options):
# Default to distro autodetection
distkey = "auto"
if options.os_variant:
distkey = options.os_variant
elif options.old_os_type:
distkey = options.old_os_type
options.os_variant = distkey
if not options.os_variant and options.old_os_type:
options.os_variant = options.old_os_type
del(options.old_os_type)
@ -366,6 +360,17 @@ def show_warnings(options, guest, installer, osdata):
# Guest building helpers #
##########################
def get_location_for_os(guest, osname, osdata):
osinfo = virtinst.OSDB.lookup_os(osname, raise_error=True)
location = osinfo.get_location(guest.os.arch)
print_stdout(_("Using {osname} --location {url}").format(
osname=osname, url=location))
if osdata.default_auto:
osdata.default_auto = False
osdata.name = osname
return location
def build_installer(options, guest, osdata):
cdrom = None
location = None
@ -376,37 +381,18 @@ def build_installer(options, guest, osdata):
install_kernel = None
install_initrd = None
install_kernel_args = None
install_os = None
if options.install:
installdata = cli.parse_install(options.install)
if options.unattended:
if osdata.is_none or osdata.is_auto:
fail(_("--unattended requires an explicit --os-variant"))
if not guest.osinfo.is_windows():
if options.cdrom:
options.location = options.cdrom
options.cdrom = None
osdata.install = "location"
INSTALL_VALUES = ["location"]
if osdata.install not in INSTALL_VALUES + [None]:
fail(_("Unknown --os-variant install value '%s'. Must be one of: %s") %
(osdata.install, ", ".join(INSTALL_VALUES)))
if osdata.install == "location":
if not options.location:
location = guest.osinfo.get_location(guest.os.arch)
logging.debug(
"Generated default libosinfo '--location %s'", location)
options.location = location
extra_args = options.extra_args
if installdata:
install_bootdev = installdata.bootdev
install_kernel = installdata.kernel
install_initrd = installdata.initrd
install_kernel_args = installdata.kernel_args
install_os = installdata.os
if installdata.kernel_args:
if installdata.kernel_args_overwrite:
install_kernel_args = installdata.kernel_args
@ -414,7 +400,9 @@ def build_installer(options, guest, osdata):
extra_args = [installdata.kernel_args]
no_install = None
if options.location:
if install_os:
location = get_location_for_os(guest, install_os, osdata)
elif options.location:
(location,
location_kernel,
location_initrd) = cli.parse_location(options.location)
@ -542,13 +530,12 @@ def build_guest_instance(conn, options):
# we are operating on any arch/os/type values passed in with --boot
guest.set_capabilities_defaults()
# If explicit os-variant requested, set it early since it will
# provide more defaults in the future
osdata = cli.parse_os_variant(options.os_variant)
installer = build_installer(options, guest, osdata)
# Set osname after
guest.set_default_os_name()
osdata.set_os_name(guest)
installer = build_installer(options, guest, osdata)
installer_detect_distro(guest, installer, osdata)
set_cli_defaults(options, guest)

View File

@ -1564,6 +1564,7 @@ def parse_check(checks):
class ParserInstall(VirtCLIParser):
cli_arg_name = "install"
remove_first = "os"
@classmethod
def _init_class(cls, **kwargs):
@ -1574,6 +1575,7 @@ class ParserInstall(VirtCLIParser):
cls.add_arg("kernel_args", "kernel_args", can_comma=True)
cls.add_arg("kernel_args_overwrite", "kernel_args_overwrite",
is_onoff=True)
cls.add_arg("os", "os")
class InstallData:
@ -1583,6 +1585,7 @@ class InstallData:
self.initrd = None
self.kernel_args = None
self.kernel_args_overwrite = None
self.os = None
def parse_install(optstr):
@ -1630,12 +1633,12 @@ class OSVariantData(object):
self._name = None
self.full_id = None
self.is_none = False
self.is_auto = False
self.install = None
self._explicit_auto = False
self.default_auto = False
def _set_name(self, val):
if val == "auto":
self.is_auto = True
self._explicit_auto = True
elif val == "none":
self.is_none = True
else:
@ -1644,6 +1647,12 @@ class OSVariantData(object):
return self._name
name = property(_get_name, _set_name)
@property
def is_auto(self):
if self._name:
return False
return self._explicit_auto or self.default_auto
def set_os_name(self, guest):
if self.full_id:
guest.set_os_full_id(self.full_id)
@ -1660,7 +1669,6 @@ class ParserOSVariant(VirtCLIParser):
VirtCLIParser._init_class(**kwargs)
cls.add_arg("name", "name")
cls.add_arg("full_id", "full_id")
cls.add_arg("install", "install")
def parse_os_variant(optstr):
@ -1668,6 +1676,8 @@ def parse_os_variant(optstr):
if optstr:
parser = ParserOSVariant(optstr)
parser.parse(parsedata)
else:
parsedata.default_auto = True
return parsedata

View File

@ -458,11 +458,7 @@ class Guest(XMLBuilder):
self._metadata.libosinfo.os_id = obj.full_id
def set_os_name(self, name):
obj = OSDB.lookup_os(name)
if obj is None:
raise ValueError(_("Unknown OS name '%s'. "
"See `osinfo-query os` for valid values.") % name)
obj = OSDB.lookup_os(name, raise_error=True)
logging.debug("Setting Guest osinfo name %s", obj)
self._set_os_obj(obj)

View File

@ -215,7 +215,7 @@ class _OSDB(object):
if osobj.full_id == full_id:
return osobj
def lookup_os(self, key):
def lookup_os(self, key, raise_error=False):
if key in self._aliases:
alias = self._aliases[key]
# Added 2018-10-02. Maybe remove aliases in a year
@ -223,7 +223,12 @@ class _OSDB(object):
_("OS name '%s' is deprecated, using '%s' instead. "
"This alias will be removed in the future."), key, alias)
key = alias
return self._all_variants.get(key)
ret = self._all_variants.get(key)
if ret is None and raise_error:
raise ValueError(_("Unknown OS name '%s'. "
"See `osinfo-query os` for valid values.") % key)
return ret
def guess_os_by_iso(self, location):
try: