1#
2# Common code for all guests
3#
4# Copyright 2006-2009, 2013, 2014, 2015 Red Hat, Inc.
5#
6# This work is licensed under the GNU GPLv2 or later.
7# See the COPYING file in the top-level directory.
8
9import random
10
11from . import generatename
12from . import xmlutil
13from .buildconfig import BuildConfig
14from .devices import *  # pylint: disable=wildcard-import
15from .domain import *  # pylint: disable=wildcard-import
16from .domcapabilities import DomainCapabilities
17from .logger import log
18from .osdict import OSDB
19from .xmlbuilder import XMLBuilder, XMLProperty, XMLChildProperty
20
21_ignore = Device
22
23
24class _DomainDevices(XMLBuilder):
25    XML_NAME = "devices"
26    _XML_PROP_ORDER = ['disk', 'controller', 'filesystem', 'interface',
27            'smartcard', 'serial', 'parallel', 'console', 'channel',
28            'input', 'tpm', 'graphics', 'sound', 'video', 'hostdev',
29            'redirdev', 'watchdog', 'memballoon', 'rng', 'panic',
30            'memory', 'vsock', 'iommu']
31
32
33    disk = XMLChildProperty(DeviceDisk)
34    controller = XMLChildProperty(DeviceController)
35    filesystem = XMLChildProperty(DeviceFilesystem)
36    interface = XMLChildProperty(DeviceInterface)
37    smartcard = XMLChildProperty(DeviceSmartcard)
38    serial = XMLChildProperty(DeviceSerial)
39    parallel = XMLChildProperty(DeviceParallel)
40    console = XMLChildProperty(DeviceConsole)
41    channel = XMLChildProperty(DeviceChannel)
42    input = XMLChildProperty(DeviceInput)
43    tpm = XMLChildProperty(DeviceTpm)
44    graphics = XMLChildProperty(DeviceGraphics)
45    sound = XMLChildProperty(DeviceSound)
46    video = XMLChildProperty(DeviceVideo)
47    hostdev = XMLChildProperty(DeviceHostdev)
48    redirdev = XMLChildProperty(DeviceRedirdev)
49    watchdog = XMLChildProperty(DeviceWatchdog)
50    memballoon = XMLChildProperty(DeviceMemballoon)
51    rng = XMLChildProperty(DeviceRng)
52    panic = XMLChildProperty(DevicePanic)
53    memory = XMLChildProperty(DeviceMemory)
54    vsock = XMLChildProperty(DeviceVsock)
55    iommu = XMLChildProperty(DeviceIommu)
56
57    def get_all(self):
58        retlist = []
59        # pylint: disable=protected-access
60        devtypes = _DomainDevices._XML_PROP_ORDER
61        for devtype in devtypes:
62            retlist.extend(getattr(self, devtype))
63        return retlist
64
65
66class _IOThreadID(XMLBuilder):
67    XML_NAME = "iothread"
68    _XML_PROP_ORDER = ["id"]
69
70    id = XMLProperty("./@id", is_int=True)
71
72
73class Guest(XMLBuilder):
74    @staticmethod
75    def validate_name(conn, name, check_collision=True, validate=True):
76        if validate:
77            XMLBuilder.validate_generic_name(_("Guest"), name)
78        if not check_collision:
79            return
80
81        try:
82            conn.lookupByName(name)
83        except Exception:
84            return
85        raise ValueError(_("Guest name '%s' is already in use.") % name)
86
87    @staticmethod
88    def generate_uuid(conn):
89        def _randomUUID():
90            if conn.fake_conn_predictable():
91                # Testing hack
92                return "00000000-1111-2222-3333-444444444444"
93
94            u = [random.randint(0, 255) for ignore in range(0, 16)]
95            u[6] = (u[6] & 0x0F) | (4 << 4)
96            u[8] = (u[8] & 0x3F) | (2 << 6)
97
98            return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2,
99                             "%02x" * 6]) % tuple(u)
100
101        for ignore in range(256):
102            uuid = _randomUUID()
103            if not generatename.check_libvirt_collision(
104                    conn.lookupByUUID, uuid):
105                return uuid
106
107        log.error(  # pragma: no cover
108                "Failed to generate non-conflicting UUID")
109
110    @staticmethod
111    def generate_name(guest):
112        def _pretty_arch(_a):
113            if _a == "armv7l":
114                return "arm"
115            return _a
116
117        force_num = False
118        basename = guest.osinfo.name
119        if basename.endswith("-unknown"):
120            basename = basename.rsplit("-", 1)[0]
121
122        if guest.osinfo.name == "generic":
123            force_num = True
124            if guest.os.is_container():
125                basename = "container"
126            else:
127                basename = "vm"
128
129        if guest.os.arch != guest.conn.caps.host.cpu.arch:
130            basename += "-%s" % _pretty_arch(guest.os.arch)
131            force_num = False
132
133        def cb(n):
134            return generatename.check_libvirt_collision(
135                guest.conn.lookupByName, n)
136        return generatename.generate_name(basename, cb,
137            start_num=force_num and 1 or 2, force_num=force_num,
138            sep=not force_num and "-" or "")
139
140
141    @staticmethod
142    def get_recommended_machine(capsinfo):
143        """
144        Return the recommended machine type for the passed capsinfo.
145        We only return this for arch cases where there's a very clear
146        preference that's different from the default machine type
147        """
148        def _qemu_machine():
149            if (capsinfo.arch in ["ppc64", "ppc64le"] and
150                "pseries" in capsinfo.machines):
151                return "pseries"
152
153            if capsinfo.arch in ["armv7l", "aarch64"]:
154                if "virt" in capsinfo.machines:
155                    return "virt"
156                if "vexpress-a15" in capsinfo.machines:  # pragma: no cover
157                    return "vexpress-a15"
158
159            if capsinfo.arch in ["s390x"]:
160                if "s390-ccw-virtio" in capsinfo.machines:
161                    return "s390-ccw-virtio"
162
163            if capsinfo.arch in ["riscv64", "riscv32"]:
164                if "virt" in capsinfo.machines:
165                    return "virt"
166
167        if capsinfo.conn.is_qemu() or capsinfo.conn.is_test():
168            return _qemu_machine()
169        return None
170
171
172    #################
173    # init handling #
174    #################
175
176    XML_NAME = "domain"
177    _XML_PROP_ORDER = [
178        "type", "name", "uuid", "genid", "genid_enable",
179        "title", "description", "_metadata", "iothreads", "iothreadids",
180        "maxMemory", "maxMemorySlots", "memory", "_currentMemory",
181        "blkiotune", "memtune", "memoryBacking",
182        "_vcpus", "vcpu_current", "vcpu_placement",
183        "vcpu_cpuset", "vcpulist", "numatune", "resource", "sysinfo",
184        "bootloader", "os", "idmap", "features", "cpu", "clock",
185        "on_poweroff", "on_reboot", "on_crash",
186        "pm", "emulator", "devices", "launchSecurity", "seclabels", "keywrap"]
187
188    def __init__(self, *args, **kwargs):
189        XMLBuilder.__init__(self, *args, **kwargs)
190
191        # Allow virt-manager to override the default graphics type
192        self.default_graphics_type = BuildConfig.default_graphics
193
194        self.skip_default_console = False
195        self.skip_default_channel = False
196        self.skip_default_sound = False
197        self.skip_default_usbredir = False
198        self.skip_default_graphics = False
199        self.skip_default_rng = False
200        self.x86_cpu_default = self.cpu.SPECIAL_MODE_APP_DEFAULT
201
202        self.skip_default_osinfo = False
203        self.uefi_requested = False
204        self.__osinfo = None
205        self._capsinfo = None
206        self._domcaps = None
207        self._extra_drivers = None
208
209
210    ######################
211    # Property accessors #
212    ######################
213
214    name = XMLProperty("./name")
215
216    iothreads = XMLProperty("./iothreads", is_int=True)
217    iothreadids = XMLChildProperty(_IOThreadID, relative_xpath="./iothreadids")
218
219    def _set_currentMemory(self, val):
220        if val is not None:
221            val = int(val)
222            if self.memory is None or self.memory < val:
223                self.memory = val
224        self._currentMemory = val
225    def _get_currentMemory(self):
226        return self._currentMemory
227    currentMemory = property(_get_currentMemory, _set_currentMemory)
228
229    _currentMemory = XMLProperty("./currentMemory", is_int=True)
230    memory = XMLProperty("./memory", is_int=True)
231    maxMemory = XMLProperty("./maxMemory", is_int=True)
232    maxMemorySlots = XMLProperty("./maxMemory/@slots", is_int=True)
233
234    def _set_vcpus(self, val):
235        if val is not None:
236            val = int(val)
237            # Don't force set curvcpus unless already specified
238            if self.vcpu_current is not None and self.vcpu_current > val:
239                self.vcpu_current = val
240        self._vcpus = val
241    def _get_vcpus(self):
242        return self._vcpus
243    _vcpus = XMLProperty("./vcpu", is_int=True)
244    vcpus = property(_get_vcpus, _set_vcpus)
245
246    vcpu_current = XMLProperty("./vcpu/@current", is_int=True)
247    vcpu_placement = XMLProperty("./vcpu/@placement")
248    vcpu_cpuset = XMLProperty("./vcpu/@cpuset")
249
250    uuid = XMLProperty("./uuid")
251    genid = XMLProperty("./genid")
252    genid_enable = XMLProperty("./genid", is_bool=True)
253    id = XMLProperty("./@id", is_int=True)
254    type = XMLProperty("./@type")
255    bootloader = XMLProperty("./bootloader")
256    description = XMLProperty("./description")
257    title = XMLProperty("./title")
258    emulator = XMLProperty("./devices/emulator")
259
260    on_poweroff = XMLProperty("./on_poweroff")
261    on_reboot = XMLProperty("./on_reboot")
262    on_crash = XMLProperty("./on_crash")
263    on_lockfailure = XMLProperty("./on_lockfailure")
264
265    vcpulist = XMLChildProperty(DomainVCPUs, is_single=True)
266    seclabels = XMLChildProperty(DomainSeclabel)
267    keywrap = XMLChildProperty(DomainKeyWrap, is_single=True)
268    os = XMLChildProperty(DomainOs, is_single=True)
269    features = XMLChildProperty(DomainFeatures, is_single=True)
270    clock = XMLChildProperty(DomainClock, is_single=True)
271    cpu = XMLChildProperty(DomainCpu, is_single=True)
272    cputune = XMLChildProperty(DomainCputune, is_single=True)
273    numatune = XMLChildProperty(DomainNumatune, is_single=True)
274    pm = XMLChildProperty(DomainPm, is_single=True)
275    blkiotune = XMLChildProperty(DomainBlkiotune, is_single=True)
276    memtune = XMLChildProperty(DomainMemtune, is_single=True)
277    memoryBacking = XMLChildProperty(DomainMemoryBacking, is_single=True)
278    idmap = XMLChildProperty(DomainIdmap, is_single=True)
279    resource = XMLChildProperty(DomainResource, is_single=True)
280    sysinfo = XMLChildProperty(DomainSysinfo)
281    launchSecurity = XMLChildProperty(DomainLaunchSecurity, is_single=True)
282    _metadata = XMLChildProperty(DomainMetadata, is_single=True)
283
284    xmlns_qemu = XMLChildProperty(DomainXMLNSQemu, is_single=True)
285
286
287    ##############################
288    # osinfo related definitions #
289    ##############################
290
291    def _get_osinfo(self):
292        if self.__osinfo:
293            return self.__osinfo
294
295        os_id = self._metadata.libosinfo.os_id
296        if os_id:
297            self.__osinfo = OSDB.lookup_os_by_full_id(os_id)
298            if not self.__osinfo:
299                log.debug("XML had libosinfo os id=%s but we didn't "
300                        "find any libosinfo object matching that", os_id)
301
302        if not self.__osinfo:
303            # If you hit this error, it means some part of the cli
304            # tried to access osinfo before we can depend on it being
305            # available. Try moving whatever bits need osinfo to be
306            # triggered via set_defaults
307            if self.skip_default_osinfo:
308                raise xmlutil.DevError(
309                        "osinfo is accessed before it has been set.")
310            self.set_default_os_name()
311        return self.__osinfo
312    osinfo = property(_get_osinfo)
313
314    def _set_os_obj(self, obj):
315        self.__osinfo = obj
316        self._metadata.libosinfo.os_id = obj.full_id
317
318    def set_os_name(self, name):
319        obj = OSDB.lookup_os(name, raise_error=True)
320        log.debug("Setting Guest osinfo name %s", obj)
321        self._set_os_obj(obj)
322
323    def set_default_os_name(self):
324        self.set_os_name("generic")
325
326    def _supports_virtio(self, os_support):
327        if not self.conn.is_qemu():
328            return False
329
330        # These _only_ support virtio so don't check the OS
331        if (self.os.is_arm_machvirt() or
332            self.os.is_riscv_virt() or
333            self.os.is_s390x() or
334            self.os.is_pseries()):
335            return True
336
337        if not os_support:
338            return False
339
340        if self.os.is_x86():
341            return True
342
343        return False  # pragma: no cover
344
345    def supports_virtionet(self):
346        return self._supports_virtio(self.osinfo.supports_virtionet(self._extra_drivers))
347    def supports_virtiodisk(self):
348        return self._supports_virtio(self.osinfo.supports_virtiodisk(self._extra_drivers))
349    def supports_virtioscsi(self):
350        return self._supports_virtio(self.osinfo.supports_virtioscsi(self._extra_drivers))
351    def _supports_virtioserial(self):
352        return self._supports_virtio(self.osinfo.supports_virtioserial(self._extra_drivers))
353
354
355    #####################
356    # Bootorder helpers #
357    #####################
358
359    def _get_old_boot_order(self):
360        return self.os.bootorder
361
362    def _convert_old_boot_order(self):
363        """Converts the old boot order (e.g. <boot dev='hd'/>) into the
364        per-device boot order format.
365
366        """
367        boot_order = self._get_old_boot_order()
368        ret = []
369        disk = None
370        cdrom = None
371        floppy = None
372        net = None
373
374        for d in self.devices.disk:
375            if not cdrom and d.device == "cdrom":
376                cdrom = d
377            if not floppy and d.device == "floppy":
378                floppy = d
379            if not disk and d.device not in ["cdrom", "floppy"]:
380                disk = d
381            if cdrom and disk and floppy:
382                break
383
384        for n in self.devices.interface:
385            net = n
386            break
387
388        for b in boot_order:
389            if b == "network" and net:
390                ret.append(net.get_xml_id())
391            elif b == "hd" and disk:
392                ret.append(disk.get_xml_id())
393            elif b == "cdrom" and cdrom:
394                ret.append(cdrom.get_xml_id())
395            elif b == "fd" and floppy:
396                ret.append(floppy.get_xml_id())
397        return ret
398
399    def _get_device_boot_order(self):
400        order = []
401        for dev in self.get_bootable_devices():
402            if not dev.boot.order:
403                continue
404            order.append((dev.get_xml_id(), dev.boot.order))
405
406        if not order:
407            # No devices individually marked bootable, convert traditional
408            # boot XML to fine grained
409            return self._convert_old_boot_order()
410
411        order.sort(key=lambda p: p[1])
412        return [p[0] for p in order]
413
414    def get_boot_order(self, legacy=False):
415        if legacy:
416            return self._get_old_boot_order()
417        return self._get_device_boot_order()
418
419    def _set_device_boot_order(self, boot_order):
420        """Sets the new device boot order for the domain"""
421        # Unset the traditional boot order
422        self.os.bootorder = []
423
424        # Unset device boot order
425        for dev in self.devices.get_all():
426            dev.boot.order = None
427
428        dev_map = dict((dev.get_xml_id(), dev) for dev in
429                       self.get_bootable_devices())
430        for boot_idx, dev_xml_id in enumerate(boot_order, 1):
431            dev_map[dev_xml_id].boot.order = boot_idx
432
433    def set_boot_order(self, boot_order, legacy=False):
434        """Modifies the boot order"""
435        if legacy:
436            self.os.bootorder = boot_order
437        else:
438            self._set_device_boot_order(boot_order)
439
440    def reorder_boot_order(self, dev, boot_index):
441        """Sets boot order of `dev` to `boot_index`
442
443        Sets the boot order for device `dev` to value `boot_index` and
444        adjusts all other boot indices accordingly. Additionally the
445        boot order defined in the 'os' node of a domain definition is
446        disabled since they are mutually exclusive in libvirt.
447
448        """
449        # unset legacy boot order
450        self.os.bootorder = []
451
452        # Sort the bootable devices by boot order
453        devs_sorted = sorted([device for device in self.get_bootable_devices()
454                              if device.boot.order is not None],
455                             key=lambda device: device.boot.order)
456
457        # set new boot order
458        dev.boot.order = boot_index
459
460        next_boot_index = None
461        for device in devs_sorted:
462            if device is dev:
463                continue
464
465            if device.boot.order in [next_boot_index, boot_index]:
466                next_boot_index = device.boot.order + 1
467                device.boot.order = next_boot_index
468                continue
469
470            if next_boot_index is not None:
471                # we found a hole so we can stop here
472                break
473
474
475    ###############################
476    # Public XML APIs and helpers #
477    ###############################
478
479    def add_device(self, dev):
480        self.devices.add_child(dev)
481    def remove_device(self, dev):
482        self.devices.remove_child(dev)
483    devices = XMLChildProperty(_DomainDevices, is_single=True)
484
485    def find_device(self, origdev):
486        """
487        Try to find a child device that matches the content of
488        the passed @origdev.
489        """
490        devlist = getattr(self.devices, origdev.DEVICE_TYPE)
491        for idx, dev in enumerate(devlist):
492            if origdev.compare_device(dev, idx):
493                return dev
494        return None
495
496    def get_bootable_devices(self, exclude_redirdev=False):
497        """
498        Returns bootable devices of the guest definition. If
499        @exclude_redirdev is `True` redirected devices will be
500        skipped in the output.
501
502        """
503        devices = self.devices
504        devs = devices.disk + devices.interface + devices.hostdev
505        if not exclude_redirdev:
506            devs = devs + devices.redirdev
507        return devs
508
509    def prefers_uefi(self):
510        """
511        Return True if this config prefers UEFI. For example,
512        arm+machvirt prefers UEFI since it's required for traditional
513        install methods
514        """
515        return self.os.is_arm_machvirt()
516
517    def get_uefi_path(self):
518        """
519        If UEFI firmware path is found, return it, otherwise raise an error
520        """
521        domcaps = self.lookup_domcaps()
522
523        if not domcaps.supports_uefi_xml():
524            raise RuntimeError(_("Libvirt version does not support UEFI."))
525
526        if not domcaps.arch_can_uefi():
527            raise RuntimeError(
528                _("Don't know how to setup UEFI for arch '%s'") %
529                self.os.arch)
530
531        path = domcaps.find_uefi_path_for_arch()
532        if not path:  # pragma: no cover
533            raise RuntimeError(_("Did not find any UEFI binary path for "
534                "arch '%s'") % self.os.arch)
535
536        return path
537
538    def is_uefi(self):
539        if self.os.loader and self.os.loader_type == "pflash":
540            return True
541        return self.os.firmware == "efi"
542
543    def set_uefi_path(self, path):
544        """
545        Configure UEFI for the VM, but only if libvirt is advertising
546        a known UEFI binary path.
547        """
548        self.os.loader_ro = True
549        self.os.loader_type = "pflash"
550        self.os.loader = path
551
552        # If the firmware name contains "secboot" it is probably build
553        # with SMM feature required so we need to enable that feature,
554        # otherwise the firmware may fail to load.  True secure boot is
555        # currently supported only on x86 architecture and with q35 with
556        # SMM feature enabled so change the machine to q35 as well.
557        # To actually enforce the secure boot for the guest if Secure Boot
558        # Mode is configured we need to enable loader secure feature.
559        if (self.os.is_x86() and
560            "secboot" in self.os.loader):
561            self.features.smm = True
562            self.os.loader_secure = True
563            if self.os.machine and "q35" not in self.os.machine:
564                log.warning("Changing machine type from '%s' to 'q35' "
565                        "which is required for UEFI secure boot.",
566                        self.os.machine)
567                self.os.machine = "q35"
568
569    def disable_hyperv_for_uefi(self):
570        # UEFI doesn't work with hyperv bits for some OS
571        if not self.is_uefi():
572            return  # pragma: no cover
573        if not self.osinfo.broken_uefi_with_hyperv():
574            return  # pragma: no cover
575        self.features.hyperv_relaxed = None
576        self.features.hyperv_vapic = None
577        self.features.hyperv_spinlocks = None
578        self.features.hyperv_spinlocks_retries = None
579        for i in self.clock.timers:
580            if i.name == "hypervclock":
581                self.clock.timers.remove(i)
582
583    def has_spice(self):
584        for gfx in self.devices.graphics:
585            if gfx.type == gfx.TYPE_SPICE:
586                return True
587
588    def has_gl(self):
589        for gfx in self.devices.graphics:
590            if gfx.gl:
591                return True
592
593    def has_listen_none(self):
594        for gfx in self.devices.graphics:
595            listen = gfx.get_first_listen_type()
596            if listen and listen == "none":
597                return True
598        return False
599
600    def is_full_os_container(self):
601        if not self.os.is_container():
602            return False
603        for fs in self.devices.filesystem:
604            if fs.target == "/":
605                return True
606        return False
607
608    def can_default_virtioscsi(self):
609        """
610        Return True if the guest supports virtio-scsi, and there's
611        no other scsi controllers attached to the guest
612        """
613        has_any_scsi = any([d.type == "scsi" for d in self.devices.controller])
614        return not has_any_scsi and self.supports_virtioscsi()
615
616    def hyperv_supported(self):
617        if not self.osinfo.is_windows():
618            return False
619        if (self.is_uefi() and
620            self.osinfo.broken_uefi_with_hyperv()):
621            return False
622        return True
623
624    def lookup_domcaps(self):
625        # We need to regenerate domcaps cache if any of these values change
626        def _compare(domcaps):  # pragma: no cover
627            if self.type == "test":
628                # Test driver doesn't support domcaps. We kinda fake it in
629                # some cases, but it screws up the checking here for parsed XML
630                return True
631            if self.os.machine and self.os.machine != domcaps.machine:
632                return False
633            if self.type and self.type != domcaps.domain:
634                return False
635            if self.os.arch and self.os.arch != domcaps.arch:
636                return False
637            if self.emulator and self.emulator != domcaps.path:
638                return False
639            return True
640
641        if not self._domcaps or not _compare(self._domcaps):
642            self._domcaps = DomainCapabilities.build_from_guest(self)
643        return self._domcaps
644
645    def lookup_capsinfo(self):
646        # We need to regenerate capsinfo cache if any of these values change
647        def _compare(capsinfo):  # pragma: no cover
648            if self.type and self.type != capsinfo.hypervisor_type:
649                return False
650            if self.os.os_type and self.os.os_type != capsinfo.os_type:
651                return False
652            if self.os.arch and self.os.arch != capsinfo.arch:
653                return False
654            if self.os.machine and self.os.machine not in capsinfo.machines:
655                return False
656            return True
657
658        if not self._capsinfo or not _compare(self._capsinfo):
659            self._capsinfo = self.conn.caps.guest_lookup(
660                os_type=self.os.os_type,
661                arch=self.os.arch,
662                typ=self.type,
663                machine=self.os.machine)
664        return self._capsinfo
665
666    def set_capabilities_defaults(self, capsinfo=None):
667        if capsinfo:  # pragma: no cover
668            self._capsinfo = capsinfo
669        else:
670            capsinfo = self.lookup_capsinfo()
671        wants_default_type = not self.type and not self.os.os_type
672
673        self.type = capsinfo.hypervisor_type
674        self.os.os_type = capsinfo.os_type
675        self.os.arch = capsinfo.arch
676        if not self.os.loader:
677            self.os.loader = capsinfo.loader
678        if (not self.emulator and
679            not self.os.is_xenpv() and
680            self.type != "vz"):
681            self.emulator = capsinfo.emulator
682        if not self.os.machine:
683            self.os.machine = Guest.get_recommended_machine(capsinfo)
684
685        if (wants_default_type and
686            self.conn.is_qemu() and
687            self.os.is_x86() and
688            self.type != "kvm"):
689            log.warning(  # pragma: no cover
690                    "KVM acceleration not available, using '%s'", self.type)
691
692    def sync_vcpus_topology(self):
693        """
694        <cpu> topology count and <vcpus> always need to match. Handle
695        the syncing here since we are less constrained then doing it
696        in CPU set_defaults
697        """
698        if not self.cpu.has_topology():
699            return
700        if not self.vcpus:
701            self.vcpus = self.cpu.vcpus_from_topology()
702        self.cpu.set_topology_defaults(self.vcpus)
703
704    def set_defaults(self, _guest):
705        self.set_capabilities_defaults()
706
707        if not self.uuid:
708            self.uuid = Guest.generate_uuid(self.conn)
709
710        self.sync_vcpus_topology()
711        if not self.vcpus:
712            # Typically if omitted libvirt will fill this value in for us
713            # However if user specified cpuset= or placement=, libvirt
714            # will error if <vcpus>X is also unset. So keep this for safety
715            self.vcpus = 1
716
717        self._set_default_machine()
718        self._set_default_uefi()
719
720        self._add_default_graphics()
721        self._add_default_video_device()
722        self._add_default_input_device()
723        self._add_default_console_device()
724        self._add_default_usb_controller()
725        self._add_default_channels()
726        self._add_default_rng()
727        self._add_default_memballoon()
728
729        self.clock.set_defaults(self)
730        self.cpu.set_defaults(self)
731        self.features.set_defaults(self)
732        for seclabel in self.seclabels:
733            seclabel.set_defaults(self)
734        self.pm.set_defaults(self)
735        self.os.set_defaults(self)
736        self.launchSecurity.set_defaults(self)
737
738        for dev in self.devices.get_all():
739            dev.set_defaults(self)
740
741        self._add_implied_controllers()
742        self._add_spice_devices()
743
744    def add_extra_drivers(self, extra_drivers):
745        self._extra_drivers = extra_drivers
746
747
748    ########################
749    # Private xml routines #
750    ########################
751
752    def _set_default_machine(self):
753        if self.os.machine:
754            return
755
756        capsinfo = self.lookup_capsinfo()
757
758        if (self.os.is_x86() and
759            self.conn.is_qemu() and
760            "q35" in capsinfo.machines and
761            self.conn.support.qemu_q35_default() and
762            self.osinfo.supports_chipset_q35()):
763            self.os.machine = "q35"
764            return
765
766        default = capsinfo.machines and capsinfo.machines[0] or None
767        self.os.machine = default
768
769
770    def _set_default_uefi(self):
771        use_default_uefi = (self.prefers_uefi() and
772            not self.os.kernel and
773            not self.os.loader and
774            self.os.loader_ro is None and
775            self.os.nvram is None and
776            self.os.firmware is None)
777
778        if use_default_uefi or self.uefi_requested:
779            try:
780                path = self.get_uefi_path()
781                log.debug("Setting UEFI path=%s", path)
782                self.set_uefi_path(path)
783            except RuntimeError as e:
784                if self.uefi_requested:
785                    raise
786                log.debug("Error setting UEFI default",
787                    exc_info=True)
788                log.warning("Couldn't configure UEFI: %s", e)
789                log.warning("Your VM may not boot successfully.")
790
791    def _usb_disabled(self):
792        controllers = [c for c in self.devices.controller if
793            c.type == "usb"]
794        if not controllers:
795            return False
796        return all([c.model == "none" for c in controllers])
797
798    def _add_default_input_device(self):
799        if self.os.is_container():
800            return
801        if self.devices.input:
802            return
803        if not self.devices.graphics:
804            return
805        if self._usb_disabled():
806            return
807
808        usb_tablet = False
809        usb_keyboard = False
810        if self.os.is_x86() and not self.os.is_xenpv():
811            usb_tablet = self.osinfo.supports_usbtablet()
812        if (self.os.is_arm_machvirt() or
813            self.os.is_riscv_virt() or
814            self.os.is_pseries()):
815            usb_tablet = True
816            usb_keyboard = True
817
818        if usb_tablet:
819            dev = DeviceInput(self.conn)
820            dev.type = "tablet"
821            dev.bus = "usb"
822            self.add_device(dev)
823        if usb_keyboard:
824            dev = DeviceInput(self.conn)
825            dev.type = "keyboard"
826            dev.bus = "usb"
827            self.add_device(dev)
828
829        # s390x guests need VirtIO input devices
830        if self.os.is_s390x() and self.osinfo.supports_virtioinput(self._extra_drivers):
831            dev = DeviceInput(self.conn)
832            dev.type = "tablet"
833            dev.bus = "virtio"
834            self.add_device(dev)
835            dev = DeviceInput(self.conn)
836            dev.type = "keyboard"
837            dev.bus = "virtio"
838            self.add_device(dev)
839
840    def _add_default_console_device(self):
841        if self.skip_default_console:
842            return
843        if self.devices.console or self.devices.serial:
844            return
845
846        dev = DeviceConsole(self.conn)
847        dev.type = dev.TYPE_PTY
848        if self.os.is_s390x():
849            dev.target_type = "sclp"
850        self.add_device(dev)
851
852    def _add_default_video_device(self):
853        if self.os.is_container():
854            return
855        if self.devices.video:
856            return
857        if not self.devices.graphics:
858            return
859        self.add_device(DeviceVideo(self.conn))
860
861    def _add_default_usb_controller(self):
862        if any([d.type == "usb" for d in self.devices.controller]):
863            return
864        if not self.conn.is_qemu() and not self.conn.is_test():
865            return
866
867        qemu_usb3 = self.conn.support.conn_qemu_xhci()
868        usb2 = False
869        usb3 = False
870        if self.os.is_x86():
871            usb3 = bool(self.osinfo.supports_usb3() and qemu_usb3)
872            usb2 = not usb3
873        elif self.os.is_arm_machvirt():
874            # For machvirt, we always assume OS supports usb3
875            if (qemu_usb3 and
876                self.conn.support.conn_machvirt_pci_default()):
877                usb3 = True
878        elif self.os.is_riscv_virt():
879            # For RISC-V we can assume the guest OS supports USB3, but we
880            # have to make sure libvirt and QEMU are new enough to be using
881            # PCI by default
882            if (qemu_usb3 and
883                self.conn.support.conn_riscv_virt_pci_default()):
884                usb3 = True
885        elif self.os.is_pseries():
886            # For pseries, we always assume OS supports usb3
887            if qemu_usb3:
888                usb3 = True
889
890
891        if usb2:
892            for dev in DeviceController.get_usb2_controllers(self.conn):
893                self.add_device(dev)
894        elif usb3:
895            self.add_device(
896                DeviceController.get_usb3_controller(self.conn, self))
897
898    def _add_default_channels(self):
899        if self.skip_default_channel:
900            return
901        if self.devices.channel:
902            return
903
904        if (self.conn.is_qemu() and
905            self._supports_virtioserial() and
906            self.conn.support.conn_autosocket()):
907            dev = DeviceChannel(self.conn)
908            dev.type = "unix"
909            dev.target_type = "virtio"
910            dev.target_name = dev.CHANNEL_NAME_QEMUGA
911            self.add_device(dev)
912
913    def _add_default_graphics(self):
914        if self.skip_default_graphics:
915            return
916        if self.devices.graphics:
917            return
918        if self.os.is_container() and not self.conn.is_vz():
919            return
920        if self.os.arch not in ["x86_64", "i686", "ppc64", "ppc64le"]:
921            return
922        self.add_device(DeviceGraphics(self.conn))
923
924    def _add_default_rng(self):
925        if self.skip_default_rng:
926            return
927        if self.devices.rng:
928            return
929        if not (self.os.is_x86() or
930                self.os.is_arm_machvirt() or
931                self.os.is_riscv_virt() or
932                self.os.is_s390x() or
933                self.os.is_pseries()):
934            return
935
936        if (self.conn.is_qemu() and
937            self.osinfo.supports_virtiorng(self._extra_drivers) and
938            self.conn.support.conn_rng_urandom()):
939            dev = DeviceRng(self.conn)
940            dev.type = "random"
941            dev.device = "/dev/urandom"
942            self.add_device(dev)
943
944    def _add_default_memballoon(self):
945        if self.devices.memballoon:
946            return
947        if not self.conn.is_qemu():
948            return
949
950        # We know for certain that a memballoon is good to have with these
951        # machine types; for other machine types, we leave the decision up
952        # to libvirt
953        if not (self.os.is_x86() or
954                self.os.is_arm_machvirt() or
955                self.os.is_riscv_virt() or
956                self.os.is_s390x() or
957                self.os.is_pseries()):
958            return
959
960        if self.osinfo.supports_virtioballoon(self._extra_drivers):
961            dev = DeviceMemballoon(self.conn)
962            dev.model = "virtio"
963            self.add_device(dev)
964
965    def _add_implied_controllers(self):
966        # Add virtio-scsi controller if needed
967        if self.can_default_virtioscsi():
968            for dev in self.devices.disk:
969                if dev.bus == "scsi":
970                    ctrl = DeviceController(self.conn)
971                    ctrl.type = "scsi"
972                    ctrl.model = "virtio-scsi"
973                    ctrl.set_defaults(self)
974                    self.add_device(ctrl)
975                    break
976
977    def _add_spice_channels(self):
978        if self.skip_default_channel:
979            return
980        for chn in self.devices.channel:
981            if chn.type == chn.TYPE_SPICEVMC:
982                return
983
984        # We explicitly don't check for virtioserial support here.
985        # We did that for a while, which excluded windows, and
986        # we received some complaints.
987        # https://bugzilla.redhat.com/show_bug.cgi?id=1660123
988        dev = DeviceChannel(self.conn)
989        dev.type = DeviceChannel.TYPE_SPICEVMC
990        dev.set_defaults(self)
991        self.add_device(dev)
992
993    def _add_spice_sound(self):
994        if self.skip_default_sound:
995            return
996        if self.devices.sound:
997            return
998        if not self.os.is_hvm():
999            return  # pragma: no cover
1000
1001        dev = DeviceSound(self.conn)
1002        dev.set_defaults(self)
1003        self.add_device(dev)
1004
1005    def _add_spice_usbredir(self):
1006        if self.skip_default_usbredir:
1007            return
1008        if self.devices.redirdev:
1009            return
1010        if self._usb_disabled():
1011            return
1012        if not self.os.is_x86():
1013            return
1014
1015        # If we use 4 devices here, we fill up all the emulated USB2 slots,
1016        # and directly assigned devices are forced to fall back to USB1
1017        # https://bugzilla.redhat.com/show_bug.cgi?id=1135488
1018        for ignore in range(2):
1019            dev = DeviceRedirdev(self.conn)
1020            dev.bus = "usb"
1021            dev.type = "spicevmc"
1022            dev.set_defaults(self)
1023            self.add_device(dev)
1024
1025    def _add_spice_devices(self):
1026        if not self.has_spice():
1027            return
1028
1029        if (self.features.vmport is None and
1030            self.os.is_x86() and
1031            self.conn.support.conn_vmport()):
1032            self.features.vmport = False
1033
1034        self._add_spice_channels()
1035        self._add_spice_sound()
1036        self._add_spice_usbredir()
1037