mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-04-25 10:50:13 +03:00
Compare commits
No commits in common. "master" and "v11.2.0-rc2" have entirely different histories.
master
...
v11.2.0-rc
95
NEWS.rst
95
NEWS.rst
@ -8,71 +8,11 @@ the changes introduced by each of them.
|
||||
For a more fine-grained view, use the `git log`_.
|
||||
|
||||
|
||||
v11.3.0 (unreleased)
|
||||
v11.2.0 (unreleased)
|
||||
====================
|
||||
|
||||
* **Security**
|
||||
|
||||
* **Removed features**
|
||||
|
||||
* Support for AppArmor versions prior to 3.0.0 has been dropped.
|
||||
|
||||
* **New features**
|
||||
|
||||
* xen: Support configuration of ``<hyperv/>`` flags for Xen domains.
|
||||
|
||||
The following flags are now configurable for Xen: ``vapic``, ``synic``,
|
||||
``stimer``, ``frequencies``, ``tlbflush`` and ``ipi``.
|
||||
|
||||
* bhyve: Support virtio random number generator devices
|
||||
|
||||
Domain XMLs can now include virtio random number generator devices.
|
||||
They are configured with::
|
||||
|
||||
<rng model='virtio'>
|
||||
<backend model='random'/>
|
||||
</rng>
|
||||
|
||||
* bhyve: Support ``<interface type='network'>``
|
||||
|
||||
At the moment it doesn't provide any new features compared to
|
||||
``<interface type='bridge'>``, but allows a more flexible configuration.
|
||||
|
||||
* **Improvements**
|
||||
|
||||
* **Bug fixes**
|
||||
|
||||
* cpu_map: Install Ampere-1 ARM CPU models
|
||||
|
||||
The Ampere-1 CPU models added in the previous release were not properly
|
||||
installed and thus every attempt to start an ARM domain with custom
|
||||
CPU definition would fail.
|
||||
|
||||
* storage: Fix new volume creation
|
||||
|
||||
No more errors occur when new storage volume is being created using ``virsh
|
||||
vol-create`` with ``--validate`` option and/or ``virStorageVolCreateXML()``
|
||||
with ``VIR_VOL_XML_PARSE_VALIDATE`` flag.
|
||||
|
||||
* Don't spam logs with error about ``qemu-rdp`` when starting a qemu VM
|
||||
|
||||
On hosts where the ``qemu-rdp`` binary is not installed a start of a VM
|
||||
would cause an error such as ::
|
||||
|
||||
error : qemuRdpNewForHelper:103 : 'qemu-rdp' is not a suitable qemu-rdp helper name: No such file or directory
|
||||
|
||||
to be logged in the system log. It is safe to ignore the error. The code
|
||||
was fixed to avoid the message when probing for support.
|
||||
|
||||
* Fix libvirt daemon crash on failure to hotplug a disk into a ``qemu`` VM
|
||||
|
||||
Some failures of disk hotplug could cause the libvirt daemon to crash due
|
||||
to a bug when rolling back disk throttling filters.
|
||||
|
||||
|
||||
v11.2.0 (2025-04-01)
|
||||
====================
|
||||
|
||||
* **Removed features**
|
||||
|
||||
* Remove support for qemu-6.1 and older
|
||||
@ -140,26 +80,6 @@ v11.2.0 (2025-04-01)
|
||||
system are printed. A user may specify ``--all`` to also print models which
|
||||
are not supported on the host.
|
||||
|
||||
* qemu: Introduce os/shim element
|
||||
|
||||
For secure boot environments where ``<loader/>`` is signed, it may be
|
||||
unfeasible to keep the binary up to date (esp. when revoking certificates
|
||||
contained within). To address that, new ``<shim/>`` element is introduced
|
||||
which allows hypervisor to side load another UEFI binary, which can then
|
||||
contain new certification authorities and/or list of revocations.
|
||||
|
||||
* ch: Enable SEV SNP support
|
||||
|
||||
Cloud Hypervisor guests can be now started with SEV SNP enabled.
|
||||
|
||||
* qemu: Support for Block Disk Along with Throttle Filters
|
||||
|
||||
Introduce support for multiple throttle groups per block disk in QEMU,
|
||||
enhancing I/O control and performance optimization. This update builds
|
||||
on the existing throttling functionality by allowing more granular control
|
||||
with the ability to assign different throttle groups to multiple block
|
||||
devices, improving shared throttling across devices.
|
||||
|
||||
* **Improvements**
|
||||
|
||||
* qemu: Improved guest agent corner case error reporting
|
||||
@ -186,14 +106,6 @@ v11.2.0 (2025-04-01)
|
||||
``virConnectGetAllDomainStats``, ``virDomainListGetStats``, and
|
||||
``virDomainGetGuestInfo``.
|
||||
|
||||
* qemu: Reflect MAC address change in live domain XML
|
||||
|
||||
When a guest changes MAC address on one of its vNICs the new MAC address is
|
||||
now visible in the live XML under ``currentAddress`` attribute of
|
||||
``<mac/>`` element. At the same time,
|
||||
``VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE`` event is emitted so that management
|
||||
applications can update their internal state.
|
||||
|
||||
* **Bug fixes**
|
||||
|
||||
* qemu: attach virtio-mem with CCW address
|
||||
@ -202,11 +114,6 @@ v11.2.0 (2025-04-01)
|
||||
default type CCW address assigned. A specified CCW address is now used for
|
||||
the virtio-mem device instead of getting overwritten by a PCI address.
|
||||
|
||||
* ch: Various memory leak fixes
|
||||
|
||||
There were some memory leaks identified in the Cloud Hypervisor driver.
|
||||
They are fixed now.
|
||||
|
||||
|
||||
v11.1.0 (2025-03-03)
|
||||
====================
|
||||
|
@ -123,17 +123,6 @@ img.diagram {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#documentation #application-development ul li p {
|
||||
padding-bottom: 0px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
#documentation #application-development ul {
|
||||
margin-left: 2em;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.removedhv {
|
||||
color: darkred;
|
||||
}
|
||||
|
@ -60,46 +60,24 @@ Application development
|
||||
-----------------------
|
||||
|
||||
`API reference <html/index.html>`__
|
||||
Reference manual for the C public API, split in:
|
||||
|
||||
* `common <html/libvirt-libvirt-common.html>`__
|
||||
* `domain <html/libvirt-libvirt-domain.html>`__
|
||||
* `domain checkpoint <html/libvirt-libvirt-domain-checkpoint.html>`__
|
||||
* `domain snapshot <html/libvirt-libvirt-domain-snapshot.html>`__
|
||||
* `error <html/libvirt-virterror.html>`__
|
||||
* `event <html/libvirt-libvirt-event.html>`__
|
||||
* `host <html/libvirt-libvirt-host.html>`__
|
||||
* `interface <html/libvirt-libvirt-interface.html>`__
|
||||
* `network <html/libvirt-libvirt-network.html>`__
|
||||
* `node device <html/libvirt-libvirt-nodedev.html>`__
|
||||
* `network filter <html/libvirt-libvirt-nwfilter.html>`__
|
||||
* `secret <html/libvirt-libvirt-secret.html>`__
|
||||
* `storage <html/libvirt-libvirt-storage.html>`__
|
||||
* `stream <html/libvirt-libvirt-stream.html>`__
|
||||
|
||||
and the documentation for the API of the additional libs:
|
||||
|
||||
* `admin <html/libvirt-libvirt-admin.html>`__
|
||||
* `QEMU <html/libvirt-libvirt-qemu.html>`__
|
||||
* `LXC <html/libvirt-libvirt-lxc.html>`__
|
||||
|
||||
`XML schemas <format.html>`__
|
||||
Description of the XML schemas for
|
||||
|
||||
* `domains <formatdomain.html>`__
|
||||
* `networks <formatnetwork.html>`__
|
||||
* `network ports <formatnetworkport.html>`__
|
||||
* `network filtering <formatnwfilter.html>`__
|
||||
* `storage <formatstorage.html>`__
|
||||
* `storage encryption <formatstorageencryption.html>`__
|
||||
* `capabilities <formatcaps.html>`__
|
||||
* `domain capabilities <formatdomaincaps.html>`__
|
||||
* `storage pool capabilities <formatstoragecaps.html>`__
|
||||
* `node devices <formatnode.html>`__
|
||||
* `secrets <formatsecret.html>`__
|
||||
* `snapshots <formatsnapshot.html>`__
|
||||
* `checkpoints <formatcheckpoint.html>`__
|
||||
* `backup jobs <formatbackup.html>`__
|
||||
Reference manual for the C public API, split in
|
||||
`common <html/libvirt-libvirt-common.html>`__,
|
||||
`domain <html/libvirt-libvirt-domain.html>`__,
|
||||
`domain checkpoint <html/libvirt-libvirt-domain-checkpoint.html>`__,
|
||||
`domain snapshot <html/libvirt-libvirt-domain-snapshot.html>`__,
|
||||
`error <html/libvirt-virterror.html>`__,
|
||||
`event <html/libvirt-libvirt-event.html>`__,
|
||||
`host <html/libvirt-libvirt-host.html>`__,
|
||||
`interface <html/libvirt-libvirt-interface.html>`__,
|
||||
`network <html/libvirt-libvirt-network.html>`__,
|
||||
`node device <html/libvirt-libvirt-nodedev.html>`__,
|
||||
`network filter <html/libvirt-libvirt-nwfilter.html>`__,
|
||||
`secret <html/libvirt-libvirt-secret.html>`__,
|
||||
`storage <html/libvirt-libvirt-storage.html>`__,
|
||||
`stream <html/libvirt-libvirt-stream.html>`__ and
|
||||
`admin <html/libvirt-libvirt-admin.html>`__,
|
||||
`QEMU <html/libvirt-libvirt-qemu.html>`__,
|
||||
`LXC <html/libvirt-libvirt-lxc.html>`__ libs
|
||||
|
||||
`Language bindings and API modules <bindings.html>`__
|
||||
Bindings of the libvirt API for
|
||||
@ -114,6 +92,23 @@ Application development
|
||||
and integration API modules for
|
||||
`D-Bus <dbus.html>`__
|
||||
|
||||
`XML schemas <format.html>`__
|
||||
Description of the XML schemas for
|
||||
`domains <formatdomain.html>`__,
|
||||
`networks <formatnetwork.html>`__,
|
||||
`network ports <formatnetworkport.html>`__,
|
||||
`network filtering <formatnwfilter.html>`__,
|
||||
`storage <formatstorage.html>`__,
|
||||
`storage encryption <formatstorageencryption.html>`__,
|
||||
`capabilities <formatcaps.html>`__,
|
||||
`domain capabilities <formatdomaincaps.html>`__,
|
||||
`storage pool capabilities <formatstoragecaps.html>`__,
|
||||
`node devices <formatnode.html>`__,
|
||||
`secrets <formatsecret.html>`__,
|
||||
`snapshots <formatsnapshot.html>`__,
|
||||
`checkpoints <formatcheckpoint.html>`__,
|
||||
`backup jobs <formatbackup.html>`__
|
||||
|
||||
`URI format <uri.html>`__
|
||||
The URI formats used for connecting to libvirt
|
||||
|
||||
|
@ -7,10 +7,8 @@ Bhyve driver
|
||||
.. contents::
|
||||
|
||||
Bhyve is a FreeBSD hypervisor. It first appeared in FreeBSD 10.0. However, it's
|
||||
recommended to use the
|
||||
`latest supported release <https://www.freebsd.org/releases/>`__
|
||||
to make sure all new features of bhyve are supported.
|
||||
In order to enable bhyve on your FreeBSD host, you'll need
|
||||
recommended to keep tracking FreeBSD 10-STABLE to make sure all new features of
|
||||
bhyve are supported. In order to enable bhyve on your FreeBSD host, you'll need
|
||||
to load the ``vmm`` kernel module. Additionally, ``if_tap`` and ``if_bridge``
|
||||
modules should be loaded for networking support. Also, :since:`since 3.2.0` the
|
||||
``virt-host-validate(1)`` supports the bhyve host validation and could be used
|
||||
@ -584,18 +582,3 @@ Note that these extensions are for testing and development purposes only. They
|
||||
are **unsupported**, using them may result in inconsistent state, and upgrading
|
||||
either bhyve or libvirtd maybe break behavior of a domain that was relying on a
|
||||
specific commands pass-through.
|
||||
|
||||
Random number generator device
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:since:`Since 11.3.0` it's possible to use the virtio random number generator devices.
|
||||
|
||||
Example:
|
||||
|
||||
::
|
||||
|
||||
...
|
||||
<rng model='virtio'>
|
||||
<backend model='random'/>
|
||||
</rng>
|
||||
...
|
||||
|
@ -5,7 +5,7 @@
|
||||
QEMU/KVM/HVF hypervisor driver
|
||||
==============================
|
||||
|
||||
The libvirt KVM/QEMU driver can manage any QEMU emulator from version 6.2.0 or
|
||||
The libvirt KVM/QEMU driver can manage any QEMU emulator from version 4.2.0 or
|
||||
later.
|
||||
|
||||
It supports multiple QEMU accelerators: software
|
||||
|
@ -1,5 +1,3 @@
|
||||
.. role:: since
|
||||
|
||||
Backup XML format
|
||||
=================
|
||||
|
||||
@ -44,25 +42,6 @@ were supplied). The following child elements and attributes are supported:
|
||||
necessary to set up an NBD server that exposes the content of each disk at
|
||||
the time the backup is started.
|
||||
|
||||
In addition to the above the NBD server used for backups allows using
|
||||
``transport='fd' fdgroup='NAME'`` where ``NAME`` is the name used with
|
||||
``virDomainFDAssociate()`` to pass a pre-opened server socket file descriptor
|
||||
to qemu. :since:`Since 11.3.0`
|
||||
|
||||
Example code to pass a socket with libvirt-python bindings::
|
||||
|
||||
import socket
|
||||
import libvirt
|
||||
|
||||
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
s.bind("/path/to/socket")
|
||||
|
||||
fdlist = [ s.fileno() ]
|
||||
|
||||
conn = libvirt.open()
|
||||
dom = conn.lookupByName("VMNAME")
|
||||
dom.FDAssociate("NAME", fdlist)
|
||||
|
||||
Note that for the QEMU hypervisor the TLS environment in controlled using
|
||||
``backup_tls_x509_cert_dir``, ``backup_tls_x509_verify``, and
|
||||
``backup_tls_x509_secret_uuid`` properties in ``/etc/libvirt/qemu.conf``.
|
||||
|
@ -2132,34 +2132,32 @@ are:
|
||||
based virtualization drivers, such as LXC.
|
||||
``hyperv``
|
||||
Enable various features improving behavior of guests running Microsoft
|
||||
Windows. :since:`Since 11.3.0` some of these flags are also available for
|
||||
Xen domains running Microsoft Windows.
|
||||
Windows.
|
||||
|
||||
=============== ====================================================================== ============================================ ========================================================================
|
||||
Feature Description Value Since
|
||||
=============== ====================================================================== ============================================ ========================================================================
|
||||
relaxed Relax constraints on timers on, off :since:`1.0.0 (QEMU 2.0), 11.3.0 (Xen, always on)`
|
||||
vapic Enable virtual APIC on, off :since:`1.1.0 (QEMU 2.0), 11.3.0 (Xen)`
|
||||
relaxed Relax constraints on timers on, off :since:`1.0.0 (QEMU 2.0)`
|
||||
vapic Enable virtual APIC on, off :since:`1.1.0 (QEMU 2.0)`
|
||||
spinlocks Enable spinlock support on, off; retries - at least 4095 :since:`1.1.0 (QEMU 2.0)`
|
||||
vpindex Virtual processor index on, off :since:`1.3.3 (QEMU 2.5), 11.3.0 (Xen, always on)`
|
||||
vpindex Virtual processor index on, off :since:`1.3.3 (QEMU 2.5)`
|
||||
runtime Processor time spent on running guest code and on behalf of guest code on, off :since:`1.3.3 (QEMU 2.5)`
|
||||
synic Enable Synthetic Interrupt Controller (SynIC) on, off :since:`1.3.3 (QEMU 2.6), 11.3.0 (Xen)`
|
||||
stimer Enable SynIC timers, optionally with Direct Mode support on, off; direct - on,off :since:`1.3.3 (QEMU 2.6), direct mode 5.7.0 (QEMU 4.1), 11.3.0 (Xen, on/off only)`
|
||||
synic Enable Synthetic Interrupt Controller (SynIC) on, off :since:`1.3.3 (QEMU 2.6)`
|
||||
stimer Enable SynIC timers, optionally with Direct Mode support on, off; direct - on,off :since:`1.3.3 (QEMU 2.6), direct mode 5.7.0 (QEMU 4.1)`
|
||||
reset Enable hypervisor reset on, off :since:`1.3.3 (QEMU 2.5)`
|
||||
vendor_id Set hypervisor vendor id on, off; value - string, up to 12 characters :since:`1.3.3 (QEMU 2.5)`
|
||||
frequencies Expose frequency MSRs on, off :since:`4.7.0 (QEMU 2.12), 11.3.0 (Xen)`
|
||||
frequencies Expose frequency MSRs on, off :since:`4.7.0 (QEMU 2.12)`
|
||||
reenlightenment Enable re-enlightenment notification on migration on, off :since:`4.7.0 (QEMU 3.0)`
|
||||
tlbflush Enable PV TLB flush support on, off; direct - on,off; extended - on,off :since:`4.7.0 (QEMU 3.0), direct and extended modes 11.0.0 (QEMU 7.1.0), 11.3.0 (Xen, on/off only)`
|
||||
ipi Enable PV IPI support on, off :since:`4.10.0 (QEMU 3.1), 11.3.0 (Xen)`
|
||||
tlbflush Enable PV TLB flush support on, off; direct - on,off; extended - on,off :since:`4.7.0 (QEMU 3.0), direct and extended modes 11.0.0 (QEMU 7.1.0)`
|
||||
ipi Enable PV IPI support on, off :since:`4.10.0 (QEMU 3.1)`
|
||||
evmcs Enable Enlightened VMCS on, off :since:`4.10.0 (QEMU 3.1)`
|
||||
avic Enable use Hyper-V SynIC with hardware APICv/AVIC on, off :since:`8.10.0 (QEMU 6.2)`
|
||||
emsr_bitmap Avoid unnecessary updates to L2 MSR Bitmap upon vmexits. on, off :since:`10.7.0 (QEMU 7.1)`
|
||||
xmm_input Enable XMM Fast Hypercall Input on, off :since:`10.7.0 (QEMU 7.1)`
|
||||
=============== ====================================================================== ============================================ ========================================================================
|
||||
|
||||
:since:`Since 8.0.0 (QEMU) Since 11.3.0 (Xen)`, the hypervisor can be
|
||||
configured further by setting the ``mode`` attribute to one of the following
|
||||
values:
|
||||
:since:`Since 8.0.0`, the hypervisor can be configured further by setting
|
||||
the ``mode`` attribute to one of the following values:
|
||||
|
||||
``custom``
|
||||
Set exactly the specified features.
|
||||
@ -5056,8 +5054,8 @@ MAC address is outside of the reserved VMWare ranges.
|
||||
|
||||
:since:`Since 11.2.0`, the ``<mac/>`` element can optionally contain
|
||||
``currentAddress`` attribute (output only), which contains new MAC address if the
|
||||
guest changed it. This is currently implemented only for the model type ``virtio``
|
||||
in QEMU/KVM and requires setting ``trustGuestRxFilters`` to ``yes``.
|
||||
guest changed it. This is currently implemented only for QEMU/KVM and requires
|
||||
setting ``trustGuestRxFilters`` to ``yes``.
|
||||
|
||||
:since:`Since 7.3.0`, one can set the ACPI index against network interfaces.
|
||||
With some operating systems (eg Linux with systemd), the ACPI index is used
|
||||
@ -5246,7 +5244,15 @@ network address by including an ``ip`` element specifying an IPv4
|
||||
address in its one mandatory attribute, ``address``. Optionally, a
|
||||
second ``ip`` element with a ``family`` attribute set to "ipv6" can be
|
||||
specified to add an IPv6 address to the interface. ``address``.
|
||||
Optionally, an address ``prefix`` can be specified.
|
||||
Optionally, an address ``prefix`` can be specified. These settings are
|
||||
surprisingly **not** used by SLIRP to set the exact IP address;
|
||||
instead they are used to determine what network/subnet the guest's IP
|
||||
address should be on, and the guest will be given an address in that
|
||||
subnet, but the host portion of the address will still be "2.15". In
|
||||
the example below, for example, the guest will be given the IP address
|
||||
172.17.2.15 (**note that the '1.1' in the host portion of the address
|
||||
has been ignored**), default route of 172.17.2.2, and DNS server
|
||||
172.17.2.3.
|
||||
|
||||
::
|
||||
|
||||
@ -5262,59 +5268,6 @@ Optionally, an address ``prefix`` can be specified.
|
||||
</devices>
|
||||
...
|
||||
|
||||
These settings are surprisingly **not** used by SLIRP to set the exact
|
||||
IP address; instead they are used to determine what **network/subnet**
|
||||
the guest's IP address should be on, and the guest will be given an
|
||||
address in that subnet, but the host portion of the address will still
|
||||
be the host portion of "10.0.2.15" (based on the configured prefix (or
|
||||
a prefix of 24 if no prefix is specified). The DNS and default gateway
|
||||
addresses given to the guest will be similarly based on the network
|
||||
portion of the configuration-provided <ip> combined with the host
|
||||
portion of SLIRPs default settings for DNS/gateway
|
||||
(10.0.2.3/10.0.2.2). To help resolve the confusion of the previous
|
||||
sentences, the table below shows examples of the settings that will be
|
||||
provided to the guest (via a DHCP response) to use for its interface
|
||||
config (ip/prefix, DNS, default gateway) for various settings of <ip>
|
||||
element address and prefix in libvirt's <interface type='user'>
|
||||
config:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - libvirt <ip> element
|
||||
- guest ip/prefix
|
||||
- guest DNS
|
||||
- guest default gateway
|
||||
|
||||
* - (unspecified)
|
||||
- 10.0.2.15/24
|
||||
- 10.0.2.3
|
||||
- 10.0.2.2
|
||||
|
||||
* - address='172.17.1.1'
|
||||
prefix='16'
|
||||
- 172.17.2.15/16
|
||||
- 172.17.2.3
|
||||
- 172.17.2.2
|
||||
|
||||
* - address='172.17.1.1'
|
||||
prefix='24'
|
||||
- 172.17.1.15/24
|
||||
- 172.17.1.3
|
||||
- 172.17.1.2
|
||||
|
||||
* - address='172.17.1.1'
|
||||
prefix='8'
|
||||
- 172.0.2.15/16
|
||||
- 172.0.2.3
|
||||
- 172.0.2.2
|
||||
|
||||
* - address='172.17.1.1'
|
||||
prefix='23'
|
||||
- 172.17.0.15/23
|
||||
- 172.17.0.3
|
||||
- 172.17.0.2
|
||||
|
||||
Userspace connection using passt
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -5356,10 +5309,8 @@ any conflict).
|
||||
Also different from SLIRP's behavior: if you do specify IP
|
||||
address(es), the exact address and netmask/prefix you specify will be
|
||||
provided to the guest (i.e. passt doesn't interpret the <ip> settings
|
||||
as a network address like SLIRP does, but as a host address). In the
|
||||
table of examples given above, the guest IP would be set to exactly
|
||||
172.17.1.1 in all cases (the DNS and default gateway will be set
|
||||
the same as they are on the host).
|
||||
as a network address like SLIRP does, but as a host address). In
|
||||
example given above, the guest IP would be set to exactly 172.17.1.1.
|
||||
|
||||
Just as with SLIRP, though, once traffic from the guest leaves the
|
||||
host towards the rest of the network, it will always appear as if it
|
||||
|
@ -427,25 +427,10 @@ nodeinfo
|
||||
nodeinfo
|
||||
|
||||
Returns basic information about the node, like number and type of CPU,
|
||||
and size of the physical memory.
|
||||
|
||||
Use of this command is strongly discouraged as the information provided
|
||||
is not guaranteed to be accurate on all hardware platforms.
|
||||
|
||||
The *CPU frequency* value merely reflects the speed that the first CPU in the
|
||||
machine is currently running at. This speed may vary across CPUs and changes
|
||||
continually as the host OS throttles.
|
||||
|
||||
The data structure used to fetch the data is not extensible thus only supports
|
||||
global nodes/sockets/cores/threads (sockets/cores/threads is per NUMA node)
|
||||
topology information. If the host CPU has any further groupings (e.g.
|
||||
dies, clusters, etc) or the NUMA topology is non-symmetrical the data structure
|
||||
can't faithfully represent the system. In such cases a fake topology
|
||||
(nodes = 1, sockets = 1, cores = number of host cpus, threads = 1) which
|
||||
only correctly represents the total host CPU count is reported.
|
||||
|
||||
Recommended replacement is to use the *capabilities* command which reports
|
||||
the data (except frequency) under ``/capabilities/host/topology`` XPath.
|
||||
and size of the physical memory. The output corresponds to virNodeInfo
|
||||
structure. Specifically, the "CPU socket(s)" field means number of CPU
|
||||
sockets per NUMA cell. The information libvirt displays is dependent
|
||||
upon what each architecture may provide.
|
||||
|
||||
|
||||
nodecpumap
|
||||
|
@ -8,9 +8,7 @@
|
||||
|
||||
%define arches_qemu_kvm %{ix86} x86_64 %{power64} %{arm} aarch64 s390x riscv64
|
||||
%if 0%{?rhel}
|
||||
%if 0%{?rhel} >= 10
|
||||
%define arches_qemu_kvm x86_64 aarch64 s390x riscv64
|
||||
%elif 0%{?rhel} >= 9
|
||||
%if 0%{?rhel} > 8
|
||||
%define arches_qemu_kvm x86_64 aarch64 s390x
|
||||
%else
|
||||
%define arches_qemu_kvm x86_64 %{power64} aarch64 s390x
|
||||
|
14
meson.build
14
meson.build
@ -1,6 +1,6 @@
|
||||
project(
|
||||
'libvirt', 'c',
|
||||
version: '11.3.0',
|
||||
version: '11.2.0',
|
||||
license: 'LGPLv2+',
|
||||
meson_version: '>= 0.56.0',
|
||||
default_options: [
|
||||
@ -258,6 +258,11 @@ alloc_max = run_command(
|
||||
|
||||
stack_frame_size = 2048
|
||||
|
||||
# clang without optimization enlarges stack frames in certain corner cases
|
||||
if cc.get_id() == 'clang' and get_option('optimization') == '0'
|
||||
stack_frame_size = 4096
|
||||
endif
|
||||
|
||||
# sanitizer instrumentation may enlarge stack frames
|
||||
if get_option('b_sanitize') != 'none'
|
||||
stack_frame_size = 32768
|
||||
@ -921,11 +926,12 @@ if acl_dep.found()
|
||||
conf.set('WITH_LIBACL', 1)
|
||||
endif
|
||||
|
||||
apparmor_version = '3.0.0'
|
||||
apparmor_dep = dependency('libapparmor', version: '>=' + apparmor_version,
|
||||
required: get_option('apparmor'))
|
||||
apparmor_dep = dependency('libapparmor', required: get_option('apparmor'))
|
||||
if apparmor_dep.found()
|
||||
conf.set('WITH_APPARMOR', 1)
|
||||
if apparmor_dep.version().version_compare('>=3.0.0')
|
||||
conf.set('WITH_APPARMOR_3', 1)
|
||||
endif
|
||||
conf.set_quoted('APPARMOR_DIR', sysconfdir / 'apparmor.d')
|
||||
conf.set_quoted('APPARMOR_PROFILES_PATH', '/sys/kernel/security/apparmor/profiles')
|
||||
endif
|
||||
|
@ -188,6 +188,7 @@ src/qemu/qemu_migration_cookie.c
|
||||
src/qemu/qemu_migration_params.c
|
||||
src/qemu/qemu_monitor.c
|
||||
src/qemu/qemu_monitor_json.c
|
||||
src/qemu/qemu_monitor_text.c
|
||||
src/qemu/qemu_namespace.c
|
||||
src/qemu/qemu_nbdkit.c
|
||||
src/qemu/qemu_passt.c
|
||||
|
22
po/en_GB.po
22
po/en_GB.po
@ -13,7 +13,7 @@ msgstr ""
|
||||
"Project-Id-Version: libvirt 6.0.0\n"
|
||||
"Report-Msgid-Bugs-To: https://libvirt.org/bugs.html\n"
|
||||
"POT-Creation-Date: 2025-03-25 10:52+0000\n"
|
||||
"PO-Revision-Date: 2025-03-29 02:07+0000\n"
|
||||
"PO-Revision-Date: 2025-03-17 18:31+0000\n"
|
||||
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
|
||||
"Language-Team: English (United Kingdom) <https://translate.fedoraproject.org/"
|
||||
"projects/libvirt/libvirt/en_GB/>\n"
|
||||
@ -22,7 +22,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.10.4\n"
|
||||
"X-Generator: Weblate 5.10.2\n"
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
@ -1255,7 +1255,7 @@ msgstr "'%1$s' is not a suitable pr helper"
|
||||
|
||||
#, c-format
|
||||
msgid "'%1$s' is not a suitable qemu-rdp helper name"
|
||||
msgstr "'%1$s' is not a suitable qemu-rdp helper name"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "'%1$s' is not supported in this QEMU binary"
|
||||
@ -1283,7 +1283,7 @@ msgstr "'%1$s' starting from %2$llu has only %3$zd bytes available"
|
||||
|
||||
#, c-format
|
||||
msgid "'%1$s' vanished unexpectedly"
|
||||
msgstr "'%1$s' vanished unexpectedly"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"'--copy-storage-synchronous-writes' requires one of '--copy-storage-all', '--"
|
||||
@ -1508,7 +1508,7 @@ msgid "'return' member missing"
|
||||
msgstr "'return' member missing"
|
||||
|
||||
msgid "'sheepdog' protocol is no longer supported by any hypervisor driver"
|
||||
msgstr "'sheepdog' protocol is no longer supported by any hypervisor driver"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
@ -1914,11 +1914,11 @@ msgstr "ACPI requires UEFI on this architecture"
|
||||
|
||||
#, c-format
|
||||
msgid "ACPI table type '%1$s' is not supported"
|
||||
msgstr "ACPI table type '%1$s' is not supported"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "ACPI table type '%1$s' may only appear once"
|
||||
msgstr "ACPI table type '%1$s' may only appear once"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "AES256CBC encryption invalid keylen=%1$zu"
|
||||
@ -2035,10 +2035,10 @@ msgid "Add or remove vcpus"
|
||||
msgstr "Add or remove vCPUs"
|
||||
|
||||
msgid "Add or update a throttling group."
|
||||
msgstr "Add or update a throttling group."
|
||||
msgstr ""
|
||||
|
||||
msgid "Add or updte a throttling group."
|
||||
msgstr "Add or update a throttling group."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr "Added"
|
||||
@ -2251,7 +2251,7 @@ msgid "Autostart"
|
||||
msgstr "Autostart"
|
||||
|
||||
msgid "Autostart Once:"
|
||||
msgstr "Autostart Once:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Autostart:"
|
||||
msgstr "Autostart:"
|
||||
@ -2767,7 +2767,7 @@ msgid "Can't create initial configuration"
|
||||
msgstr "Can't create initial configuration"
|
||||
|
||||
msgid "Can't define NWFilter bindings in session mode"
|
||||
msgstr "Can't define NWFilter bindings in session mode"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't define NWFilters in session mode"
|
||||
msgstr ""
|
||||
|
27
po/ko.po
27
po/ko.po
@ -18,7 +18,7 @@ msgstr ""
|
||||
"Project-Id-Version: libvirt 6.0.0\n"
|
||||
"Report-Msgid-Bugs-To: https://libvirt.org/bugs.html\n"
|
||||
"POT-Creation-Date: 2025-03-25 10:52+0000\n"
|
||||
"PO-Revision-Date: 2025-03-30 07:26+0000\n"
|
||||
"PO-Revision-Date: 2025-03-01 03:12+0000\n"
|
||||
"Last-Translator: 김인수 <simmon@nplob.com>\n"
|
||||
"Language-Team: Korean <https://translate.fedoraproject.org/projects/libvirt/"
|
||||
"libvirt/ko/>\n"
|
||||
@ -27,7 +27,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 5.10.4\n"
|
||||
"X-Generator: Weblate 5.10.2\n"
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
@ -1253,7 +1253,7 @@ msgstr "'%1$s' 는 알맞는 도우미가 아닙니다"
|
||||
|
||||
#, c-format
|
||||
msgid "'%1$s' is not a suitable qemu-rdp helper name"
|
||||
msgstr "'%1$s' 는 적합한 qemu-rdp helper 이름이 없습니다"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "'%1$s' is not supported in this QEMU binary"
|
||||
@ -1281,7 +1281,7 @@ msgstr "'%1$s' 시작은(%2$llu에서) 사용 가능한 %3$zd 바이트만을
|
||||
|
||||
#, c-format
|
||||
msgid "'%1$s' vanished unexpectedly"
|
||||
msgstr "'%1$s' 가 예상치 못하게 사라졌습니다"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"'--copy-storage-synchronous-writes' requires one of '--copy-storage-all', '--"
|
||||
@ -1485,8 +1485,6 @@ msgid ""
|
||||
"'reconnect' attribute is not supported when source mode='server' for "
|
||||
"<interface type='vhostuser'>"
|
||||
msgstr ""
|
||||
"'reconnect' 속성은 <interface type='vhostuser'> 를 위한 source mode='server' "
|
||||
"일 때에 지원되지 않습니다"
|
||||
|
||||
msgid ""
|
||||
"'restrictive' mode is required in memnode element when mode is 'restrictive' "
|
||||
@ -1503,11 +1501,10 @@ msgstr ""
|
||||
"니다"
|
||||
|
||||
msgid "'return' member missing"
|
||||
msgstr "'return' 구성이 누락됨"
|
||||
msgstr ""
|
||||
|
||||
msgid "'sheepdog' protocol is no longer supported by any hypervisor driver"
|
||||
msgstr "'sheepdog' 통신규약은 모든 하이퍼바이저 드라이버에서 더 이상 지원되지 "
|
||||
"않습니다"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
@ -1925,11 +1922,11 @@ msgstr "ACPI는 이 구조(아키텍쳐)에서 UEFI가 필요합니다"
|
||||
|
||||
#, c-format
|
||||
msgid "ACPI table type '%1$s' is not supported"
|
||||
msgstr "ACPI 테이블 유형 '%1$s'는 지원되지 않습니다"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "ACPI table type '%1$s' may only appear once"
|
||||
msgstr "ACPI 테이블 유형 '%1$s' 는 한 번만 나타날 것입니다"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "AES256CBC encryption invalid keylen=%1$zu"
|
||||
@ -2048,10 +2045,10 @@ msgid "Add or remove vcpus"
|
||||
msgstr "vcpus를 추가하거나 제거하기"
|
||||
|
||||
msgid "Add or update a throttling group."
|
||||
msgstr "제한 그룹을 추가하거나 최신화합니다."
|
||||
msgstr ""
|
||||
|
||||
msgid "Add or updte a throttling group."
|
||||
msgstr "제한 그룹을 추가하거나 최신화합니다."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr "추가됨"
|
||||
@ -2265,7 +2262,7 @@ msgid "Autostart"
|
||||
msgstr "자동 시작"
|
||||
|
||||
msgid "Autostart Once:"
|
||||
msgstr "한 번 자동시작:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Autostart:"
|
||||
msgstr "Autostart:"
|
||||
@ -3033,7 +3030,7 @@ msgid "Cannot create macvlan devices on this platform"
|
||||
msgstr "이 기술환경에서 macvlan 장치를 생성 할 수 없음"
|
||||
|
||||
msgid "Cannot create monitor FIFO"
|
||||
msgstr "monitor FIFO를 생성 할 수 없습니다"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Cannot create resctrl directory '%1$s'"
|
||||
|
197
po/uk.po
197
po/uk.po
@ -16,7 +16,7 @@ msgstr ""
|
||||
"Project-Id-Version: libvirt 6.0.0\n"
|
||||
"Report-Msgid-Bugs-To: https://libvirt.org/bugs.html\n"
|
||||
"POT-Creation-Date: 2025-03-25 10:52+0000\n"
|
||||
"PO-Revision-Date: 2025-04-03 11:20+0000\n"
|
||||
"PO-Revision-Date: 2025-02-25 14:49+0000\n"
|
||||
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
|
||||
"Language-Team: Ukrainian <https://translate.fedoraproject.org/projects/"
|
||||
"libvirt/libvirt/uk/>\n"
|
||||
@ -26,7 +26,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.10.4\n"
|
||||
"X-Generator: Weblate 5.10\n"
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
@ -1306,7 +1306,7 @@ msgstr "«%1$s» не є придатним допоміжним засобом
|
||||
|
||||
#, c-format
|
||||
msgid "'%1$s' is not a suitable qemu-rdp helper name"
|
||||
msgstr "«%1$s» не є придатним до використання допоміжним засобом qemu-rdp"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "'%1$s' is not supported in this QEMU binary"
|
||||
@ -1336,7 +1336,7 @@ msgstr "«%1$s» починаючи з %2$llu має лише %3$zd доступ
|
||||
|
||||
#, c-format
|
||||
msgid "'%1$s' vanished unexpectedly"
|
||||
msgstr "«%1$s» неочікувано зник"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"'--copy-storage-synchronous-writes' requires one of '--copy-storage-all', '--"
|
||||
@ -1574,8 +1574,6 @@ msgstr "пропущено член 'return'"
|
||||
|
||||
msgid "'sheepdog' protocol is no longer supported by any hypervisor driver"
|
||||
msgstr ""
|
||||
"Підтримки протоколу «sheepdog» більше не передбачено у жодному драйвері "
|
||||
"гіпервізора"
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
@ -1996,11 +1994,11 @@ msgstr "На цій архітектурі ACPI потребує UEFI"
|
||||
|
||||
#, c-format
|
||||
msgid "ACPI table type '%1$s' is not supported"
|
||||
msgstr "Підтримки таблиць ACPI типу «%1$s» не передбачено"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "ACPI table type '%1$s' may only appear once"
|
||||
msgstr "Таблиця ACPI типу «%1$s» може з'являтися лише раз"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "AES256CBC encryption invalid keylen=%1$zu"
|
||||
@ -2122,10 +2120,10 @@ msgid "Add or remove vcpus"
|
||||
msgstr "Додати або вилучити віртуальні процесори"
|
||||
|
||||
msgid "Add or update a throttling group."
|
||||
msgstr "Додати або оновити групу регулювання."
|
||||
msgstr ""
|
||||
|
||||
msgid "Add or updte a throttling group."
|
||||
msgstr "Додати або оновити групу регулювання."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr "Додано"
|
||||
@ -2350,7 +2348,7 @@ msgid "Autostart"
|
||||
msgstr "Автозапуск"
|
||||
|
||||
msgid "Autostart Once:"
|
||||
msgstr "Одноразовий автозапуск:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Autostart:"
|
||||
msgstr "Автозапуск:"
|
||||
@ -3263,8 +3261,6 @@ msgstr "Не вдалося знайти «iothread»: %1$u"
|
||||
#, c-format
|
||||
msgid "Cannot find CPU model with PVR 0x%1$03llx, vendor id 0x%2$02llx"
|
||||
msgstr ""
|
||||
"Не вдалося знайти модель процесора з PVR 0x%1$03llx, ідентифікатор виробника "
|
||||
"0x%2$02llx"
|
||||
|
||||
#, c-format
|
||||
msgid "Cannot find CPU model with PVR 0x%1$08x"
|
||||
@ -5764,7 +5760,7 @@ msgid "Delete a given vol."
|
||||
msgstr "Вилучити вказаний том."
|
||||
|
||||
msgid "Delete a throttling group."
|
||||
msgstr "Вилучити групу регулювання."
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete an IOThread from the guest domain."
|
||||
msgstr "Вилучити потік введення-виведення з гостьового домену."
|
||||
@ -6238,7 +6234,7 @@ msgstr "Домен «%1$s» позначений як домен з автоза
|
||||
|
||||
#, c-format
|
||||
msgid "Domain '%1$s' marked as autostarted on next boot\n"
|
||||
msgstr "Домен «%1$s» позначено на автозапуск при наступному завантаженні\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Domain '%1$s' resumed\n"
|
||||
@ -6270,7 +6266,7 @@ msgstr "Домен «%1$s» не позначений як домен з авт
|
||||
|
||||
#, c-format
|
||||
msgid "Domain '%1$s' unmarked as autostarted on next boot\n"
|
||||
msgstr "Позначення «%1$s» для автозапуску знято для наступного завантаження\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Domain '%1$s' was reset\n"
|
||||
@ -7411,7 +7407,7 @@ msgstr "Не вдалося з'єднати сокет з «%1$s»"
|
||||
|
||||
#, c-format
|
||||
msgid "Failed to connect to dbus-daemon: %1$s"
|
||||
msgstr "Не вдалося встановити з'єднання з dbus-daemon: %1$s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to connect to mon socket"
|
||||
msgstr "Не вдалося встановити з'єднання з сокетом mon"
|
||||
@ -7605,7 +7601,7 @@ msgstr "Не вдалося створити резервне сховище н
|
||||
|
||||
#, c-format
|
||||
msgid "Failed to create rdp state dir %1$s"
|
||||
msgstr "Не вдалося створити каталог стану rdp %1$s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to create reboot thread, killing domain"
|
||||
msgstr ""
|
||||
@ -8382,7 +8378,6 @@ msgstr "Помилка позначення домену «%1$s» як доме
|
||||
#, c-format
|
||||
msgid "Failed to mark domain '%1$s' as autostarted on next boot"
|
||||
msgstr ""
|
||||
"Не вдалося позначити домен «%1$s» для автозапуску при наступному завантаженні"
|
||||
|
||||
#, c-format
|
||||
msgid "Failed to mkdir %1$s"
|
||||
@ -9353,8 +9348,6 @@ msgstr "Помилка зняття позначки домену «%1$s» як
|
||||
#, c-format
|
||||
msgid "Failed to unmark domain '%1$s' as autostarted on next boot"
|
||||
msgstr ""
|
||||
"Не вдалося зняти позначення домену «%1$s» для автозапуску при наступному "
|
||||
"завантаженні"
|
||||
|
||||
#, c-format
|
||||
msgid "Failed to unmarshall reply: %1$s"
|
||||
@ -9745,7 +9738,7 @@ msgid "GNUTLS call error"
|
||||
msgstr "помилка виклику GNUTLS"
|
||||
|
||||
msgid "Get a throttling group."
|
||||
msgstr "Отримати групу регулювання."
|
||||
msgstr ""
|
||||
|
||||
msgid "Get block device size info for a domain."
|
||||
msgstr "Отримати дані щодо розміру блокового пристрою для домену."
|
||||
@ -9824,7 +9817,7 @@ msgid "Get the CPU models for an arch."
|
||||
msgstr "Отримати дані щодо моделей процесорів для архітектури."
|
||||
|
||||
msgid "Get the CPU models reported by the hypervisor."
|
||||
msgstr "Отримати моделі процесорів, про які повідомляє гіпервізор."
|
||||
msgstr ""
|
||||
|
||||
msgid "Get the launch security parameters for a guest domain"
|
||||
msgstr "Отримати параметри безпеки запуску для гостьового домену"
|
||||
@ -9847,7 +9840,7 @@ msgid "Get the summary of block devices for a domain."
|
||||
msgstr "Отримати резюме щодо блокових пристроїв для домену."
|
||||
|
||||
msgid "Get the summary of throttle groups for a domain."
|
||||
msgstr "Отримати резюме груп регулювання для домену."
|
||||
msgstr ""
|
||||
|
||||
msgid "Get the summary of virtual interfaces for a domain."
|
||||
msgstr "Отримати резюме щодо віртуальних інтерфейсів домену."
|
||||
@ -10108,7 +10101,7 @@ msgstr ""
|
||||
"машини «%2$s»"
|
||||
|
||||
msgid "Hypervisor reported CPU models"
|
||||
msgstr "Гіпервізор повідомив про моделі процесорів"
|
||||
msgstr ""
|
||||
|
||||
msgid "I/O Error"
|
||||
msgstr "Помилка в/в"
|
||||
@ -10233,8 +10226,6 @@ msgid ""
|
||||
"IOThread mapping for virtio-scsi controllers is not available with this QEMU "
|
||||
"binary"
|
||||
msgstr ""
|
||||
"Прив'язка IOThread для контролерів virtio-scsi є недоступною для цього "
|
||||
"виконуваного файла QEMU"
|
||||
|
||||
msgid "IOThread to be used by supported device"
|
||||
msgstr "IOThread, який буде використано підтримуваним пристроєм"
|
||||
@ -10888,7 +10879,7 @@ msgstr "Некоректний тип драйвера: %1$d"
|
||||
|
||||
#, c-format
|
||||
msgid "Invalid dump_image_format '%1$s'"
|
||||
msgstr "Некоректне значення dump_image_format «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid duration"
|
||||
msgstr "Неприпустиме значення тривалості"
|
||||
@ -10970,7 +10961,7 @@ msgstr "Некоректний метод перевірки ключів осн
|
||||
|
||||
#, c-format
|
||||
msgid "Invalid host_data provided. Expected '%1$ld' bytes"
|
||||
msgstr "Надано некоректне значення host_data. Мало бути «%1$ld» байтів"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Invalid hostdev protocol '%1$s'"
|
||||
@ -10978,7 +10969,7 @@ msgstr "Некоректний протокол пристрою основно
|
||||
|
||||
#, c-format
|
||||
msgid "Invalid image_format '%1$s'"
|
||||
msgstr "Некоректне значення image_format «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Invalid integer value '%1$s' in file '%2$s'"
|
||||
@ -11204,7 +11195,7 @@ msgstr "Некоректний засіб спостереження resctrl"
|
||||
|
||||
#, c-format
|
||||
msgid "Invalid save_image_format '%1$s'"
|
||||
msgstr "Некоректне значення save_image_format «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid secret"
|
||||
msgstr "Некоректний ключ"
|
||||
@ -11230,7 +11221,7 @@ msgstr "Некоректне значення для можливості pserie
|
||||
|
||||
#, c-format
|
||||
msgid "Invalid snapshot_image_format '%1$s'"
|
||||
msgstr "Некоректне значення snapshot_image_format «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Invalid source mode: %1$s"
|
||||
@ -11533,7 +11524,7 @@ msgid "Kernel image path in this domain is not defined"
|
||||
msgstr "Шлях до образу ядра у цьому домені не визначено"
|
||||
|
||||
msgid "Kernel image path is not defined. With sev_snp=on, pass an igvm path"
|
||||
msgstr "Шлях до образу ядра не визначено. З sev_snp=on передано шлях igvm"
|
||||
msgstr ""
|
||||
|
||||
msgid "Key file path must be provided for private key authentication"
|
||||
msgstr ""
|
||||
@ -12376,7 +12367,7 @@ msgstr "Не вказано типу можливості"
|
||||
|
||||
#, c-format
|
||||
msgid "Missing certificate file '%1$s'"
|
||||
msgstr "Не вистачає файла сертифіката «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Missing check/@partial in CPU model %1$s"
|
||||
@ -12457,7 +12448,7 @@ msgstr "У документі JSON не вистачає даних keepaliveInt
|
||||
|
||||
#, c-format
|
||||
msgid "Missing key file '%1$s'"
|
||||
msgstr "Не вистачає файла ключа «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing listen element"
|
||||
msgstr "Пропущено елемент listen"
|
||||
@ -12642,7 +12633,7 @@ msgid "Missing ownerUUID data in JSON document"
|
||||
msgstr "У документі JSON не вистачає даних щодо UUID власника (ownerUUID)"
|
||||
|
||||
msgid "Missing password"
|
||||
msgstr "Не вистачає пароля"
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing path or lockspace for lease resource"
|
||||
msgstr "Не вистачає шляху або простору блокування для ресурсу надання"
|
||||
@ -13878,7 +13869,7 @@ msgid "Only VNC supported"
|
||||
msgstr "Передбачено підтримку лише VNC"
|
||||
|
||||
msgid "Only a single ACPI table is supported"
|
||||
msgstr "Передбачено підтримку лише єдиної таблиці ACPI"
|
||||
msgstr ""
|
||||
|
||||
msgid "Only a single IDE controller is supported for this machine type"
|
||||
msgstr "Для цього типу архітектури передбачено лише один контролер IDE"
|
||||
@ -14338,8 +14329,6 @@ msgstr "Номер паралельного порту, %1$d, не лежить
|
||||
|
||||
msgid "Parallel save is only supported with the 'sparse' save image format"
|
||||
msgstr ""
|
||||
"Підтримку паралельного збереження передбачено лише для формату образів "
|
||||
"збереження «sparse»"
|
||||
|
||||
#, c-format
|
||||
msgid "Parameter '%1$s' is not a string"
|
||||
@ -14718,8 +14707,6 @@ msgstr "на сервері NBD QEMU не передбачено підтрим
|
||||
#, c-format
|
||||
msgid "QEMU agent command '%1$s' returned neither error nor success"
|
||||
msgstr ""
|
||||
"Команда агента QEMU «%1$s» не повернула ні повідомлення про помилку, ні "
|
||||
"повідомлення про успіх"
|
||||
|
||||
#, c-format
|
||||
msgid "QEMU binary %1$s is not executable"
|
||||
@ -14870,13 +14857,13 @@ msgstr ""
|
||||
"розширених можливостей і створення смуг"
|
||||
|
||||
msgid "RDP doesn't support 'multiUser'"
|
||||
msgstr "У RDP не передбачено підтримки «multiUser»"
|
||||
msgstr ""
|
||||
|
||||
msgid "RDP doesn't support 'replaceUser'"
|
||||
msgstr "У RDP не передбачено підтримки «replaceUser»"
|
||||
msgstr ""
|
||||
|
||||
msgid "RDP password expiration isn't supported"
|
||||
msgstr "Підтримки завершення строку дії пароля RDP не передбачено"
|
||||
msgstr ""
|
||||
|
||||
msgid "RDT Memory Bandwidth allocation unsupported"
|
||||
msgstr "Підтримки розподілу ширини каналу пам'яті RDT не передбачено"
|
||||
@ -17791,8 +17778,6 @@ msgid ""
|
||||
"The 'dev' attribute of the <source> element can only be used with "
|
||||
"<interface> type='user' or type='vhostuser' if the <backend> type='passt'"
|
||||
msgstr ""
|
||||
"Атрибут «dev» елемента <source> можна використовувати лише з <interface> "
|
||||
"type='user' або type='vhostuser', якщо для <backend> type='passt'"
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
@ -18370,10 +18355,10 @@ msgid "Thread(s) per core:"
|
||||
msgstr "Потоків на ядро:"
|
||||
|
||||
msgid "Throttle group deleted successfully\n"
|
||||
msgstr "Групу регулювання успішно вилучено\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "Throttle group set successfully\n"
|
||||
msgstr "Групу регулювання успішно встановлено\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Time '%1$lld' is too big for guest agent"
|
||||
@ -20251,7 +20236,7 @@ msgstr "Не вдалося прочитати файл pid «%1$s»"
|
||||
|
||||
#, c-format
|
||||
msgid "Unable to read qemu-rdp pidfile '%1$s'"
|
||||
msgstr "Не вдалося прочитати файл PID qemu-rdp «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Unable to read slirp pidfile '%1$s'"
|
||||
@ -20665,7 +20650,7 @@ msgid "Unable to set thread local variable"
|
||||
msgstr "Не вдалося встановити локальний змінну потоку виконання"
|
||||
|
||||
msgid "Unable to set throttle group"
|
||||
msgstr "Не вдалося встановити групу регулювання"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Unable to set vlan configuration on port %1$s: %2$s"
|
||||
@ -21755,7 +21740,7 @@ msgid "Unsupported object type %1$d"
|
||||
msgstr "Підтримки типів об'єктів %1$d не передбачено"
|
||||
|
||||
msgid "Unsupported qemu-rdp listen type"
|
||||
msgstr "Непідтримуваний тип очікування qemu-rdp"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unsupported resctrl monitor type"
|
||||
msgstr "Непідтримуваний тип монітора resctrl"
|
||||
@ -23192,15 +23177,11 @@ msgstr "блок"
|
||||
msgid ""
|
||||
"block 'iotune' can't be used together with 'throttlefilters' for disk '%1$s'"
|
||||
msgstr ""
|
||||
"блок «iotune» не можна використовувати разом із «throttlefilters» для диска "
|
||||
"«%1$s»"
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"block 'throttlefilters' can't be used together with 'iotune' for disk '%1$s'"
|
||||
msgstr ""
|
||||
"блок «throttlefilters» не можна використовувати разом із «iotune» для диска "
|
||||
"«%1$s»"
|
||||
|
||||
#, c-format
|
||||
msgid "block I/O throttle limit must be no more than %1$llu using QEMU"
|
||||
@ -23586,7 +23567,7 @@ msgid "can't manipulate inactive snapshots of disk '%1$s'"
|
||||
msgstr "неможлива робота із неактивними знімками диска «%1$s»"
|
||||
|
||||
msgid "can't open log context"
|
||||
msgstr "не вдалося відкрити контекст журналу"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "can't open session to the domain with id %1$d"
|
||||
@ -23831,7 +23812,7 @@ msgid "cannot change persistent config of a transient network"
|
||||
msgstr "не можна змінювати сталі налаштування тимчасової мережі"
|
||||
|
||||
msgid "cannot change port settings on rdp graphics"
|
||||
msgstr "не вдалося змінити параметри порту для графіки rdp"
|
||||
msgstr ""
|
||||
|
||||
msgid "cannot change port settings on spice graphics"
|
||||
msgstr "не вдалося змінити параметри порту графічної системи SPICE"
|
||||
@ -25191,7 +25172,7 @@ msgid "cd: %1$s: %2$s"
|
||||
msgstr "cd: %1$s: %2$s"
|
||||
|
||||
msgid "cdrom device with throttle filters isn't supported"
|
||||
msgstr "підтримки пристрою cdrom з фільтрами регулювання не передбачено"
|
||||
msgstr ""
|
||||
|
||||
msgid "cdrom device with virtio bus isn't supported"
|
||||
msgstr "підтримки пристроїв cdrom з каналом virtio не передбачено"
|
||||
@ -25485,7 +25466,7 @@ msgstr ""
|
||||
"нульовим виявленням"
|
||||
|
||||
msgid "comma separated list of throttle groups to be applied"
|
||||
msgstr "список відокремлених комами груп регулювання, які буде застосовано"
|
||||
msgstr ""
|
||||
|
||||
msgid "command"
|
||||
msgstr "команда"
|
||||
@ -25702,7 +25683,7 @@ msgid "control domain's outgoing traffics"
|
||||
msgstr "керування вихідними даними домену"
|
||||
|
||||
msgid "control next boot state"
|
||||
msgstr "керувати станом наступного завантаження"
|
||||
msgstr ""
|
||||
|
||||
msgid "control or query domain emulator affinity"
|
||||
msgstr "вказати або визначити прив'язку у емуляторі домену"
|
||||
@ -25718,8 +25699,6 @@ msgid ""
|
||||
"controller driver 'iothread' attribute can't be used together with "
|
||||
"'iothreads' subelement"
|
||||
msgstr ""
|
||||
"атрибут «iothread» драйвера контролера не можна використовувати з разом із "
|
||||
"піделементом «iothreads»"
|
||||
|
||||
#, c-format
|
||||
msgid "controller index='%1$d' already exists"
|
||||
@ -26432,8 +26411,6 @@ msgid ""
|
||||
"dbus-daemon died and reported:\n"
|
||||
"%1$s"
|
||||
msgstr ""
|
||||
"dbus-daemon завершив роботу і повідомив:\n"
|
||||
"%1$s"
|
||||
|
||||
msgid "default"
|
||||
msgstr "типовий"
|
||||
@ -27533,11 +27510,11 @@ msgstr "дублювання домену «%1$s»"
|
||||
|
||||
#, c-format
|
||||
msgid "duplicate filter name '%1$s' found"
|
||||
msgstr "виявлено дублювання назви фільтра «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "duplicate group name '%1$s' found"
|
||||
msgstr "виявлено дублювання назви групи «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "duplicate iothread id '%1$u' found"
|
||||
@ -28054,10 +28031,6 @@ msgid ""
|
||||
"oldMAC: %3$s\n"
|
||||
"newMAC: %4$s\n"
|
||||
msgstr ""
|
||||
"подія «nic-mac-change» для домену «%1$s»:\n"
|
||||
"альтернатива: %2$s\n"
|
||||
"стара-MAC: %3$s\n"
|
||||
"нова-MAC: %4$s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "event 'rtc-change' for domain '%1$s': %2$lld\n"
|
||||
@ -28763,7 +28736,7 @@ msgid "failed to get hostname"
|
||||
msgstr "помилка отримання назви вузла гіпервізора"
|
||||
|
||||
msgid "failed to get hypervisor CPU model names"
|
||||
msgstr "не вдалося отримати назви моделей процесорів гіпервізора"
|
||||
msgstr ""
|
||||
|
||||
msgid "failed to get hypervisor type"
|
||||
msgstr "помилка отримання типа гіпервізора"
|
||||
@ -29334,7 +29307,7 @@ msgid "failed to seek in log file %1$s"
|
||||
msgstr "не вдалося виконати позиціювання у файлі журналу %1$s"
|
||||
|
||||
msgid "failed to seek on file descriptor"
|
||||
msgstr "не вдалося виконати позиціювання на дескрипторі файла"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "failed to seek to end of %1$s"
|
||||
@ -29911,7 +29884,7 @@ msgid "format of the destination file"
|
||||
msgstr "формат файла призначення"
|
||||
|
||||
msgid "format of the save image file"
|
||||
msgstr "формат збереження файла образу"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "formatter for %1$s %2$s reported error"
|
||||
@ -30169,28 +30142,26 @@ msgstr ""
|
||||
"вистачає: %1$s"
|
||||
|
||||
msgid "guest agent command failed"
|
||||
msgstr "помилка команди агента гостьової системи"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "guest agent command failed: %1$s"
|
||||
msgstr "помилка команди агента гостьової системи: %1$s"
|
||||
msgstr ""
|
||||
|
||||
msgid "guest agent command timed out"
|
||||
msgstr "перевищено час очікування на виконання команди агента гостьової системи"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "guest agent command timed out: %1$s"
|
||||
msgstr ""
|
||||
"перевищено час очікування на виконання команди агента гостьової системи: %1$s"
|
||||
|
||||
#, c-format
|
||||
msgid "guest agent didn't respond to command within '%1$d' seconds"
|
||||
msgstr "агент гостьової системи не відповів на команду за «%1$d» секунд"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "guest agent didn't respond to synchronization within '%1$d' seconds"
|
||||
msgstr ""
|
||||
"агент гостьової системи не відповів на синхронізацію протягом %1$d секунд"
|
||||
|
||||
msgid "guest agent replied with wrong id to guest-sync command"
|
||||
msgstr ""
|
||||
@ -30661,7 +30632,7 @@ msgid "inbound rate larger than maximum %1$u"
|
||||
msgstr "вхідна швидкість перевищує максимальну, %1$u"
|
||||
|
||||
msgid "include all CPU models known to the hypervisor for the architecture"
|
||||
msgstr "включити усі моделі процесорів, відомі гіпервізору для архітектури"
|
||||
msgstr ""
|
||||
|
||||
msgid "include backup size estimate in XML dump"
|
||||
msgstr "включити оцінку розміру резервної копії до дампу XML"
|
||||
@ -32095,7 +32066,7 @@ msgid "list all domain blocks"
|
||||
msgstr "показати список всіх блоків"
|
||||
|
||||
msgid "list all domain throttlegroups."
|
||||
msgstr "вивести усі групи регулювання домену."
|
||||
msgstr ""
|
||||
|
||||
msgid "list all domain virtual interfaces"
|
||||
msgstr "список всіх віртуальних інтерфейсів домену"
|
||||
@ -32723,7 +32694,6 @@ msgstr "помилкове форматування слоту у даних щ
|
||||
|
||||
msgid "managed save cannot be requested for transient domains"
|
||||
msgstr ""
|
||||
"запит щодо керованого збереження не можна надсилати для тимчасових доменів"
|
||||
|
||||
msgid "managed save of a domain state"
|
||||
msgstr "кероване збереження стану домену"
|
||||
@ -33647,7 +33617,7 @@ msgid "missing gluster volume name for path '%1$s'"
|
||||
msgstr "не вказано назви тому gluster для шляху «%1$s»"
|
||||
|
||||
msgid "missing group name"
|
||||
msgstr "не вистачає назви групи"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "missing group_device value for '%1$s'"
|
||||
@ -33742,7 +33712,7 @@ msgid "missing listen element"
|
||||
msgstr "пропущено елемент listen"
|
||||
|
||||
msgid "missing listen element for VNC graphics"
|
||||
msgstr "пропущено елемент listen для графіки VNC"
|
||||
msgstr ""
|
||||
|
||||
msgid "missing listen element for spice graphics"
|
||||
msgstr "пропущено елемент очікування (listen) для графіки spice"
|
||||
@ -34820,7 +34790,7 @@ msgid "no CPUs given"
|
||||
msgstr "не вказано процесори"
|
||||
|
||||
msgid "no D-Bus address"
|
||||
msgstr "немає адреси D-Bus"
|
||||
msgstr ""
|
||||
|
||||
msgid "no FLR, PM reset or bus reset available"
|
||||
msgstr "немає FLR, доступне скидання PM чи шини"
|
||||
@ -35495,13 +35465,9 @@ msgstr "numad є недоступним для цього вузла"
|
||||
|
||||
msgid "number of IO channels to use for parallel restore"
|
||||
msgstr ""
|
||||
"кількість каналів введення-виведення для використання при паралельному "
|
||||
"відновленні"
|
||||
|
||||
msgid "number of IO channels to use for parallel save"
|
||||
msgstr ""
|
||||
"кількість каналів введення-виведення для використання при паралельному "
|
||||
"збереженні"
|
||||
|
||||
msgid "number of bytes read:"
|
||||
msgstr "кількість прочитаних байтів:"
|
||||
@ -35532,7 +35498,7 @@ msgstr ""
|
||||
"переходу до стану бездіяльності"
|
||||
|
||||
msgid "number of parallel save channels cannot be less than 1"
|
||||
msgstr "кількість каналів паралельного збереження не може бути меншою за 1"
|
||||
msgstr ""
|
||||
|
||||
msgid "number of read operations:"
|
||||
msgstr "кількість дій з читання:"
|
||||
@ -35687,8 +35653,6 @@ msgid ""
|
||||
"only 1 graphics device of each type (sdl, vnc, spice, headless, dbus, rdp) "
|
||||
"is supported"
|
||||
msgstr ""
|
||||
"передбачено підтримку лише 1 графічного пристрою кожного типу (sdl, vnc, "
|
||||
"spice, headless, dbus, rdp)"
|
||||
|
||||
msgid "only JSON objects can be top level"
|
||||
msgstr "на верхньому рівні можуть бути лише об'єкти JSON"
|
||||
@ -36096,7 +36060,7 @@ msgstr "значення параметра %1$s є занадто велики
|
||||
|
||||
#, c-format
|
||||
msgid "parameter '%1$s' is missing in reply of guest-get-load"
|
||||
msgstr "у відповіді guest-get-load не визначає параметра «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "parameter '%1$s' not supported"
|
||||
@ -36586,7 +36550,7 @@ msgid "preserve sparseness of volume"
|
||||
msgstr "зберегти розрідженість тому"
|
||||
|
||||
msgid "preserve state before shutting down"
|
||||
msgstr "зберегти стан до вимикання"
|
||||
msgstr ""
|
||||
|
||||
msgid "pretty-print any JSON output"
|
||||
msgstr "форматоване виведення для усіх виведених даних JSON"
|
||||
@ -36775,7 +36739,7 @@ msgid "qemu agent didn't return an array of keys"
|
||||
msgstr "Агентом qemu не повернуто масиву ключів"
|
||||
|
||||
msgid "qemu agent didn't return an array of loads"
|
||||
msgstr "агент qemu не повернув масиву навантажень"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "qemu didn't report thread id for vcpu '%1$zu'"
|
||||
@ -36851,23 +36815,18 @@ msgid ""
|
||||
"qemu-rdp died and reported:\n"
|
||||
"%1$s"
|
||||
msgstr ""
|
||||
"qemu-rdp завершив роботу і повернув:\n"
|
||||
"%1$s"
|
||||
|
||||
msgid "qemu-rdp does not support multiple listens for one graphics device."
|
||||
msgstr ""
|
||||
"у qemu-rdp не передбачено підтримки декількох каналів очікування для одного "
|
||||
"графічного пристрою."
|
||||
|
||||
msgid "qemu-rdp doesn't support the 'multiUser' attribute."
|
||||
msgstr "у qemu-rdp не передбачено підтримки атрибута «multiUser»."
|
||||
msgstr ""
|
||||
|
||||
msgid "qemu-rdp doesn't support the 'replaceUser' attribute."
|
||||
msgstr "у qemu-rdp не передбачено підтримки атрибута «replaceUser»."
|
||||
msgstr ""
|
||||
|
||||
msgid "qemu-rdp support requires a D-Bus bus graphics device."
|
||||
msgstr ""
|
||||
"для підтримки qemu-rdp потрібен графічний пристрій із підтримкою шини D-Bus."
|
||||
|
||||
#, c-format
|
||||
msgid "qom-get invalid object property type %1$d"
|
||||
@ -37127,11 +37086,11 @@ msgid "rawio is only supported for scsi host device"
|
||||
msgstr "підтримку rawio передбачено лише для пристроїв scsi основної системи"
|
||||
|
||||
msgid "rdp"
|
||||
msgstr "rdp"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "rdp_tls_x509_cert_dir directory '%1$s' does not exist"
|
||||
msgstr "каталогу rdp_tls_x509_cert_dir «%1$s» не існує"
|
||||
msgstr ""
|
||||
|
||||
msgid "re-initialize NVRAM from its pristine template"
|
||||
msgstr "повторно ініціалізувати NVRAM з її початкового шаблона"
|
||||
@ -37427,7 +37386,7 @@ msgid "report interface information"
|
||||
msgstr "вивести звіт щодо інтерфейсу"
|
||||
|
||||
msgid "report load averages information"
|
||||
msgstr "повідомити дані щодо середнього навантаження"
|
||||
msgstr ""
|
||||
|
||||
msgid "report only stats that are accessible instantly"
|
||||
msgstr "звітувати лише про статистичні дані, які негайно доступні"
|
||||
@ -37754,8 +37713,6 @@ msgstr "збереження скасовано"
|
||||
#, c-format
|
||||
msgid "save image format %1$s is not supported by this QEMU binary"
|
||||
msgstr ""
|
||||
"підтримки формату образу збереження «%1$s» у цьому виконуваному файлі QEMU "
|
||||
"не передбачено"
|
||||
|
||||
msgid "save image is incomplete"
|
||||
msgstr "збережений образ є неповним"
|
||||
@ -38162,10 +38119,10 @@ msgid "shares '%1$llu' must be in range [%2$llu, %3$llu]"
|
||||
msgstr "shares «%1$llu» має перебувати у діапазоні [%2$llu, %3$llu]"
|
||||
|
||||
msgid "shim is not supported by this QEMU binary"
|
||||
msgstr "підтримки shim у цьому виконуваному файлі QEMU не передбачено"
|
||||
msgstr ""
|
||||
|
||||
msgid "shim only allowed with kernel option"
|
||||
msgstr "shim можна використовувати лише з параметром ядра"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
@ -38394,8 +38351,6 @@ msgid ""
|
||||
"source disk for '%1$s' is not a regular file, reverting to snapshot is not "
|
||||
"supported"
|
||||
msgstr ""
|
||||
"початковий диск для «%1$s» не є звичайним файлом, повернення до знімка не "
|
||||
"передбачено"
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
@ -38558,7 +38513,7 @@ msgid "status mismatch in event (actual 0x%1$x, expected 0x%2$x)"
|
||||
msgstr "невідповідність станів у події (маємо 0x%1$x, мало бути 0x%2$x)"
|
||||
|
||||
msgid "stop the daemon"
|
||||
msgstr "зупинити фонову службу"
|
||||
msgstr ""
|
||||
|
||||
msgid "stopped, with no saved guests"
|
||||
msgstr "зупинено без збережених гостьових систем"
|
||||
@ -39287,18 +39242,18 @@ msgstr "порогове значення як масштабоване числ
|
||||
|
||||
#, c-format
|
||||
msgid "throttle group '%1$s' is still being used by disk %2$s"
|
||||
msgstr "група регулювання «%1$s» усе ще використовує диск %2$s"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "throttle group '%1$s' not found"
|
||||
msgstr "групи регулювання «%1$s» не знайдено"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "throttle group field '%1$s' must be an integer"
|
||||
msgstr "поле групи регулювання «%1$s» має бути цілим"
|
||||
msgstr ""
|
||||
|
||||
msgid "throttle group name"
|
||||
msgstr "назва групи регулювання"
|
||||
msgstr ""
|
||||
|
||||
msgid "time to set"
|
||||
msgstr "час, який слід встановити"
|
||||
@ -40603,7 +40558,7 @@ msgstr "неочікуваний тип файлової системи %1$d"
|
||||
|
||||
#, c-format
|
||||
msgid "unexpected graphics type '%1$d'"
|
||||
msgstr "неочікуваний тип графіки «%1$d»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "unexpected host-model CPU for %1$s architecture"
|
||||
@ -40896,15 +40851,15 @@ msgstr "невідомий тип розпізнавання %1$s"
|
||||
|
||||
#, c-format
|
||||
msgid "unknown auto_shutdown_poweroff '%1$s'"
|
||||
msgstr "невідоме значення auto_shutdown_poweroff «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "unknown auto_shutdown_try_save '%1$s'"
|
||||
msgstr "невідоме значення auto_shutdown_try_save «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "unknown auto_shutdown_try_shutdown '%1$s'"
|
||||
msgstr "невідоме значення auto_shutdown_try_shutdown «%1$s»"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "unknown backend source type '%1$s' for external TPM"
|
||||
@ -41484,7 +41439,7 @@ msgid "unsupported disk driver %1$s"
|
||||
msgstr "непідтримуваний драйвер диска, %1$s"
|
||||
|
||||
msgid "unsupported disk protocol"
|
||||
msgstr "непідтримуваний протокол роботи з диском"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "unsupported disk snapshot type '%1$s'"
|
||||
|
@ -818,6 +818,8 @@ class CParser:
|
||||
# Parse a comment block associate to a macro
|
||||
#
|
||||
def parseMacroComment(self, name, quiet=0):
|
||||
global ignored_macros
|
||||
|
||||
if name[0:2] == '__':
|
||||
quiet = 1
|
||||
if name in ignored_macros:
|
||||
@ -893,6 +895,8 @@ class CParser:
|
||||
# as possible
|
||||
#
|
||||
def mergeFunctionComment(self, name, description, quiet=0):
|
||||
global ignored_functions
|
||||
|
||||
if name == 'main':
|
||||
quiet = 1
|
||||
if name[0:2] == '__':
|
||||
@ -1131,6 +1135,8 @@ class CParser:
|
||||
self.lexer.push(tok)
|
||||
|
||||
def token(self):
|
||||
global ignored_words
|
||||
|
||||
token = self.lexer.token()
|
||||
while token is not None:
|
||||
if token[0] == 'comment':
|
||||
|
@ -4,7 +4,6 @@
|
||||
* Copyright (C) 2014 Roman Bogorodskiy
|
||||
* Copyright (C) 2014 Semihalf
|
||||
* Copyright (C) 2020 Fabian Freyer
|
||||
* Copyright (C) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -109,16 +108,6 @@ virBhyveDomainCapsFill(virDomainCaps *caps,
|
||||
VIR_DOMAIN_CAPS_ENUM_SET(caps->video.modelType, VIR_DOMAIN_VIDEO_TYPE_GOP);
|
||||
}
|
||||
|
||||
if (bhyvecaps & BHYVE_CAP_VIRTIO_RND) {
|
||||
caps->rng.supported = VIR_TRISTATE_BOOL_YES;
|
||||
caps->rng.model.report = true;
|
||||
caps->rng.backendModel.report = true;
|
||||
|
||||
VIR_DOMAIN_CAPS_ENUM_SET(caps->rng.model, VIR_DOMAIN_RNG_MODEL_VIRTIO);
|
||||
VIR_DOMAIN_CAPS_ENUM_SET(caps->rng.backendModel,
|
||||
VIR_DOMAIN_RNG_BACKEND_RANDOM);
|
||||
}
|
||||
|
||||
caps->hostdev.supported = VIR_TRISTATE_BOOL_NO;
|
||||
caps->features[VIR_DOMAIN_CAPS_FEATURE_IOTHREADS] = VIR_TRISTATE_BOOL_NO;
|
||||
caps->features[VIR_DOMAIN_CAPS_FEATURE_VMCOREINFO] = VIR_TRISTATE_BOOL_NO;
|
||||
@ -338,17 +327,6 @@ bhyveProbeCapsVirtio9p(unsigned int *caps, char *binary)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
bhyveProbeCapsVirtioRnd(unsigned int *caps, char *binary)
|
||||
{
|
||||
return bhyveProbeCapsDeviceHelper(caps, binary,
|
||||
"-s",
|
||||
"0,virtio-rnd",
|
||||
"pci slot 0:0: unknown device \"virtio-rnd\"",
|
||||
BHYVE_CAP_VIRTIO_RND);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virBhyveProbeCaps(unsigned int *caps)
|
||||
{
|
||||
@ -386,9 +364,6 @@ virBhyveProbeCaps(unsigned int *caps)
|
||||
if ((ret = bhyveProbeCapsVirtio9p(caps, binary)))
|
||||
goto out;
|
||||
|
||||
if ((ret = bhyveProbeCapsVirtioRnd(caps, binary)))
|
||||
goto out;
|
||||
|
||||
out:
|
||||
VIR_FREE(binary);
|
||||
return ret;
|
||||
|
@ -2,7 +2,6 @@
|
||||
* bhyve_capabilities.h: bhyve capabilities module
|
||||
*
|
||||
* Copyright (C) 2014 Semihalf
|
||||
* Copyright (C) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -53,7 +52,6 @@ typedef enum {
|
||||
BHYVE_CAP_SOUND_HDA = 1 << 7,
|
||||
BHYVE_CAP_VNC_PASSWORD = 1 << 8,
|
||||
BHYVE_CAP_VIRTIO_9P = 1 << 9,
|
||||
BHYVE_CAP_VIRTIO_RND = 1 << 10,
|
||||
} virBhyveCapsFlags;
|
||||
|
||||
int virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps);
|
||||
|
@ -2,7 +2,6 @@
|
||||
* bhyve_command.c: bhyve command generation
|
||||
*
|
||||
* Copyright (C) 2014 Roman Bogorodskiy
|
||||
* Copyright (C) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -27,7 +26,6 @@
|
||||
#include "bhyve_domain.h"
|
||||
#include "bhyve_conf.h"
|
||||
#include "bhyve_driver.h"
|
||||
#include "domain_validate.h"
|
||||
#include "datatypes.h"
|
||||
#include "viralloc.h"
|
||||
#include "virfile.h"
|
||||
@ -54,7 +52,6 @@ bhyveBuildNetArgStr(const virDomainDef *def,
|
||||
char *nic_model = NULL;
|
||||
int ret = -1;
|
||||
virDomainNetType actualType = virDomainNetGetActualType(net);
|
||||
g_autoptr(virConnect) netconn = NULL;
|
||||
|
||||
if (net->model == VIR_DOMAIN_NET_MODEL_VIRTIO) {
|
||||
nic_model = g_strdup("virtio-net");
|
||||
@ -72,43 +69,12 @@ bhyveBuildNetArgStr(const virDomainDef *def,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
||||
if (!netconn && !(netconn = virGetConnectNetwork()))
|
||||
goto cleanup;
|
||||
if (virDomainNetAllocateActualDevice(netconn, def, net) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
/* final validation now that actual type is known */
|
||||
if (virDomainActualNetDefValidate(net) < 0)
|
||||
return -1;
|
||||
|
||||
switch (actualType) {
|
||||
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
||||
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
||||
if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
||||
brname = g_strdup(virDomainNetGetActualBridgeName(net));
|
||||
if (!brname) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("No bridge name specified"));
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
||||
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
||||
case VIR_DOMAIN_NET_TYPE_USER:
|
||||
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
case VIR_DOMAIN_NET_TYPE_SERVER:
|
||||
case VIR_DOMAIN_NET_TYPE_CLIENT:
|
||||
case VIR_DOMAIN_NET_TYPE_MCAST:
|
||||
case VIR_DOMAIN_NET_TYPE_UDP:
|
||||
case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
||||
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
||||
case VIR_DOMAIN_NET_TYPE_VDPA:
|
||||
case VIR_DOMAIN_NET_TYPE_NULL:
|
||||
case VIR_DOMAIN_NET_TYPE_VDS:
|
||||
case VIR_DOMAIN_NET_TYPE_LAST:
|
||||
} else {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Unsupported network type %1$s"),
|
||||
virDomainNetTypeToString(actualType));
|
||||
_("Network type %1$d is not supported"),
|
||||
virDomainNetGetActualType(net));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -186,24 +152,6 @@ bhyveBuildConsoleArgStr(const virDomainDef *def, virCommand *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bhyveBuildRNGArgStr(const virDomainDef *def G_GNUC_UNUSED,
|
||||
virDomainRNGDef *rng,
|
||||
virCommand *cmd)
|
||||
{
|
||||
if (rng->backend != VIR_DOMAIN_RNG_BACKEND_RANDOM) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("RNG backend is not supported"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
virCommandAddArg(cmd, "-s");
|
||||
virCommandAddArgFormat(cmd, "%d:%d,virtio-rnd",
|
||||
rng->info.addr.pci.slot,
|
||||
rng->info.addr.pci.function);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bhyveBuildAHCIControllerArgStr(const virDomainDef *def,
|
||||
virDomainControllerDef *controller,
|
||||
@ -859,10 +807,6 @@ virBhyveProcessBuildBhyveCmd(struct _bhyveConn *driver, virDomainDef *def,
|
||||
if (bhyveBuildConsoleArgStr(def, cmd) < 0)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < def->nrngs; i++)
|
||||
if (bhyveBuildRNGArgStr(def, def->rngs[i], cmd) < 0)
|
||||
return NULL;
|
||||
|
||||
if (def->namespaceData) {
|
||||
bhyveDomainCmdlineDef *bhyvecmd;
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
* bhyve_device.c: bhyve device management
|
||||
*
|
||||
* Copyright (C) 2014 Roman Bogorodskiy
|
||||
* Copyright (C) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -185,16 +184,6 @@ bhyveAssignDevicePCISlots(virDomainDef *def,
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < def->nrngs; i++) {
|
||||
if (!virDeviceInfoPCIAddressIsWanted(&def->rngs[i]->info))
|
||||
continue;
|
||||
if (virDomainPCIAddressReserveNextAddr(addrs,
|
||||
&def->rngs[i]->info,
|
||||
VIR_PCI_CONNECT_TYPE_PCI_DEVICE,
|
||||
-1) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
* bhyve_domain.c: bhyve domain private state
|
||||
*
|
||||
* Copyright (C) 2014 Roman Bogorodskiy
|
||||
* Copyright (C) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -244,26 +243,6 @@ bhyveDomainDeviceDefValidate(const virDomainDeviceDef *dev,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dev->type == VIR_DOMAIN_DEVICE_RNG) {
|
||||
if (dev->data.rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO) {
|
||||
if (dev->data.rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM) {
|
||||
if (STRNEQ(dev->data.rng->source.file, "/dev/random")) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Only /dev/random source is supported"));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Only 'random' backend model is supported"));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Only 'virio' RNG device model is supported"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
* Copyright (C) 2006 Daniel P. Berrange
|
||||
* Copyright (c) 2011 NetApp, Inc.
|
||||
* Copyright (C) 2020 Fabian Freyer
|
||||
* Copyright (C) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -640,32 +639,6 @@ bhyveParsePCIFbuf(virDomainDef *def,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
bhyveParsePCIRND(virDomainDef *def,
|
||||
virDomainXMLOption *xmlopt G_GNUC_UNUSED,
|
||||
unsigned caps G_GNUC_UNUSED,
|
||||
unsigned bus,
|
||||
unsigned slot,
|
||||
unsigned function,
|
||||
const char *config G_GNUC_UNUSED)
|
||||
{
|
||||
/* -s slot,virtio-rnd */
|
||||
virDomainRNGDef *rng = g_new0(virDomainRNGDef, 1);
|
||||
|
||||
rng->model = VIR_DOMAIN_RNG_MODEL_VIRTIO;
|
||||
rng->backend = VIR_DOMAIN_RNG_BACKEND_RANDOM;
|
||||
|
||||
rng->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
|
||||
rng->info.addr.pci.bus = bus;
|
||||
rng->info.addr.pci.slot = slot;
|
||||
rng->info.addr.pci.function = function;
|
||||
rng->source.file = g_strdup("/dev/random");
|
||||
|
||||
VIR_APPEND_ELEMENT(def->rngs, def->nrngs, rng);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bhyveParseBhyvePCIArg(virDomainDef *def,
|
||||
virDomainXMLOption *xmlopt,
|
||||
@ -730,8 +703,6 @@ bhyveParseBhyvePCIArg(virDomainDef *def,
|
||||
VIR_DOMAIN_NET_MODEL_E1000, conf);
|
||||
else if (STREQ(emulation, "fbuf"))
|
||||
bhyveParsePCIFbuf(def, xmlopt, caps, bus, slot, function, conf);
|
||||
else if (STREQ(emulation, "virtio-rnd"))
|
||||
bhyveParsePCIRND(def, xmlopt, caps, bus, slot, function, conf);
|
||||
|
||||
VIR_FREE(emulation);
|
||||
VIR_FREE(slotdef);
|
||||
|
@ -2,7 +2,6 @@
|
||||
* bhyve_process.c: bhyve process management
|
||||
*
|
||||
* Copyright (C) 2014 Roman Bogorodskiy
|
||||
* Copyright (C) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -72,23 +71,18 @@ static void
|
||||
bhyveNetCleanup(virDomainObj *vm)
|
||||
{
|
||||
size_t i;
|
||||
g_autoptr(virConnect) conn = NULL;
|
||||
|
||||
for (i = 0; i < vm->def->nnets; i++) {
|
||||
virDomainNetDef *net = vm->def->nets[i];
|
||||
virDomainNetType actualType = virDomainNetGetActualType(net);
|
||||
|
||||
if (net->ifname) {
|
||||
ignore_value(virNetDevBridgeRemovePort(
|
||||
virDomainNetGetActualBridgeName(net),
|
||||
net->ifname));
|
||||
ignore_value(virNetDevTapDelete(net->ifname, NULL));
|
||||
}
|
||||
if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
||||
if (conn || (conn = virGetConnectNetwork()))
|
||||
virDomainNetReleaseActualDevice(conn, net);
|
||||
else
|
||||
VIR_WARN("Unable to release network device '%s'", NULLSTR(net->ifname));
|
||||
if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
||||
if (net->ifname) {
|
||||
ignore_value(virNetDevBridgeRemovePort(
|
||||
virDomainNetGetActualBridgeName(net),
|
||||
net->ifname));
|
||||
ignore_value(virNetDevTapDelete(net->ifname, NULL));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -443,8 +437,6 @@ virBhyveProcessReconnect(virDomainObj *vm,
|
||||
char **proc_argv;
|
||||
char *expected_proctitle = NULL;
|
||||
bhyveDomainObjPrivate *priv = vm->privateData;
|
||||
g_autoptr(virConnect) conn = NULL;
|
||||
size_t i;
|
||||
int ret = -1;
|
||||
|
||||
if (!virDomainObjIsActive(vm))
|
||||
@ -477,14 +469,6 @@ virBhyveProcessReconnect(virDomainObj *vm,
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < vm->def->nnets; i++) {
|
||||
virDomainNetDef *net = vm->def->nets[i];
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && !conn)
|
||||
conn = virGetConnectNetwork();
|
||||
|
||||
virDomainNetNotifyActualDevice(conn, vm->def, net);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (ret < 0) {
|
||||
/* If VM is reported to be in active state, but we cannot find
|
||||
|
@ -68,7 +68,6 @@ virCHDomainObjPrivateFree(void *data)
|
||||
virBitmapFree(priv->autoCpuset);
|
||||
virBitmapFree(priv->autoNodeset);
|
||||
virCgroupFree(priv->cgroup);
|
||||
g_free(priv->pidfile);
|
||||
g_free(priv);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,6 @@ struct _virCHDomainObjPrivate {
|
||||
virBitmap *autoCpuset;
|
||||
virBitmap *autoNodeset;
|
||||
virCgroup *cgroup;
|
||||
char *pidfile;
|
||||
};
|
||||
|
||||
#define CH_DOMAIN_PRIVATE(vm) \
|
||||
|
@ -54,10 +54,10 @@ static int
|
||||
virCHEventStopProcess(virDomainObj *vm,
|
||||
virDomainShutoffReason reason)
|
||||
{
|
||||
virCHDriver *driver = CH_DOMAIN_PRIVATE(vm)->driver;
|
||||
virCHDriver *driver = ((virCHDomainObjPrivate *)vm->privateData)->driver;
|
||||
|
||||
virObjectLock(vm);
|
||||
if (virDomainObjBeginJob(vm, VIR_JOB_DESTROY))
|
||||
if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY))
|
||||
return -1;
|
||||
virCHProcessStop(driver, vm, reason);
|
||||
virDomainObjEndJob(vm);
|
||||
@ -97,6 +97,7 @@ virCHProcessEvent(virCHMonitor *mon,
|
||||
case VIR_CH_EVENT_VM_BOOTING:
|
||||
case VIR_CH_EVENT_VM_BOOTED:
|
||||
case VIR_CH_EVENT_VM_REBOOTING:
|
||||
case VIR_CH_EVENT_VM_REBOOTED:
|
||||
case VIR_CH_EVENT_VM_PAUSING:
|
||||
case VIR_CH_EVENT_VM_PAUSED:
|
||||
case VIR_CH_EVENT_VM_RESUMING:
|
||||
@ -108,16 +109,15 @@ virCHProcessEvent(virCHMonitor *mon,
|
||||
case VIR_CH_EVENT_VM_DELETED:
|
||||
break;
|
||||
case VIR_CH_EVENT_VMM_SHUTDOWN:
|
||||
case VIR_CH_EVENT_VM_SHUTDOWN:
|
||||
if (virCHEventStopProcess(vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN)) {
|
||||
VIR_WARN("Failed to mark the VM(%s) as SHUTDOWN!",
|
||||
vm->def->name);
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case VIR_CH_EVENT_VM_REBOOTED:
|
||||
case VIR_CH_EVENT_VM_SHUTDOWN:
|
||||
virObjectLock(vm);
|
||||
virCHProcessUpdateInfo(vm);
|
||||
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
|
||||
virObjectUnlock(vm);
|
||||
break;
|
||||
case VIR_CH_EVENT_LAST:
|
||||
@ -297,7 +297,7 @@ int
|
||||
virCHStartEventHandler(virCHMonitor *mon)
|
||||
{
|
||||
g_autofree char *name = NULL;
|
||||
name = g_strdup_printf("ch-evt-%d", mon->vm->pid);
|
||||
name = g_strdup_printf("ch-evt-%d", mon->pid);
|
||||
|
||||
virObjectRef(mon);
|
||||
if (virThreadCreateFull(&mon->event_handler_thread,
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "ch_conf.h"
|
||||
#include "ch_domain.h"
|
||||
#include "ch_events.h"
|
||||
#include "ch_interface.h"
|
||||
#include "ch_monitor.h"
|
||||
@ -38,7 +37,6 @@
|
||||
#include "virfile.h"
|
||||
#include "virjson.h"
|
||||
#include "virlog.h"
|
||||
#include "virpidfile.h"
|
||||
#include "virstring.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_CH
|
||||
@ -156,7 +154,7 @@ virCHMonitorBuildPayloadJson(virJSONValue *content, virDomainDef *vmdef)
|
||||
buf = g_base64_decode(vmdef->sec->data.sev_snp.host_data, &len);
|
||||
if (len != host_data_len) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Invalid host_data provided. Expected '%1$zu' bytes"),
|
||||
_("Invalid host_data provided. Expected '%1$ld' bytes"),
|
||||
host_data_len);
|
||||
return -1;
|
||||
}
|
||||
@ -584,12 +582,10 @@ chMonitorCreateSocket(const char *socket_path)
|
||||
virCHMonitor *
|
||||
virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
|
||||
{
|
||||
virCHDomainObjPrivate *priv = vm->privateData;
|
||||
g_autoptr(virCHMonitor) mon = NULL;
|
||||
g_autoptr(virCommand) cmd = NULL;
|
||||
int socket_fd = 0;
|
||||
int event_monitor_fd;
|
||||
int rv;
|
||||
|
||||
if (virCHMonitorInitialize() < 0)
|
||||
return NULL;
|
||||
@ -648,7 +644,6 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
|
||||
virCommandSetErrorFD(cmd, &logfile);
|
||||
virCommandNonblockingFDs(cmd);
|
||||
virCommandSetUmask(cmd, 0x002);
|
||||
|
||||
socket_fd = chMonitorCreateSocket(mon->socketpath);
|
||||
if (socket_fd < 0) {
|
||||
virReportSystemError(errno,
|
||||
@ -660,26 +655,13 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
|
||||
virCommandAddArg(cmd, "--api-socket");
|
||||
virCommandAddArgFormat(cmd, "fd=%d", socket_fd);
|
||||
virCommandPassFD(cmd, socket_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
|
||||
|
||||
virCommandAddArg(cmd, "--event-monitor");
|
||||
virCommandAddArgFormat(cmd, "path=%s", mon->eventmonitorpath);
|
||||
virCommandSetPidFile(cmd, priv->pidfile);
|
||||
virCommandDaemonize(cmd);
|
||||
|
||||
/* launch Cloud-Hypervisor socket */
|
||||
if (virCommandRun(cmd, NULL) < 0) {
|
||||
VIR_DEBUG("CH vm=%p name=%s failed to spawn",
|
||||
vm, vm->def->name);
|
||||
if (virCommandRunAsync(cmd, &mon->pid) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((rv = virPidFileReadPath(priv->pidfile, &vm->pid)) < 0) {
|
||||
virReportSystemError(-rv,
|
||||
_("Domain %1$s didn't show up"),
|
||||
vm->def->name);
|
||||
return NULL;
|
||||
}
|
||||
VIR_DEBUG("CH vm=%p name=%s running with pid=%lld",
|
||||
vm, vm->def->name, (long long)vm->pid);
|
||||
|
||||
/* open the reader end of fifo before start Event Handler */
|
||||
while ((event_monitor_fd = open(mon->eventmonitorpath, O_RDONLY)) < 0) {
|
||||
@ -727,6 +709,12 @@ void virCHMonitorClose(virCHMonitor *mon)
|
||||
if (!mon)
|
||||
return;
|
||||
|
||||
if (mon->pid > 0) {
|
||||
/* try cleaning up the Cloud-Hypervisor process */
|
||||
virProcessAbort(mon->pid);
|
||||
mon->pid = 0;
|
||||
}
|
||||
|
||||
if (mon->handle)
|
||||
curl_easy_cleanup(mon->handle);
|
||||
|
||||
@ -1139,7 +1127,7 @@ virCHMonitorBuildRestoreJson(virDomainDef *vmdef,
|
||||
g_autoptr(virJSONValue) nets = virJSONValueNewArray();
|
||||
for (i = 0; i < vmdef->nnets; i++) {
|
||||
g_autoptr(virJSONValue) net_json = virJSONValueNewObject();
|
||||
g_autofree char *id = g_strdup_printf("%s_%zu", CH_NET_ID_PREFIX, i);
|
||||
g_autofree char *id = g_strdup_printf("%s_%ld", CH_NET_ID_PREFIX, i);
|
||||
if (virJSONValueObjectAppendString(net_json, "id", id) < 0)
|
||||
return -1;
|
||||
if (virJSONValueObjectAppendNumberInt(net_json, "num_fds", vmdef->nets[i]->driver.virtio.queues))
|
||||
@ -1208,7 +1196,10 @@ virCHMonitorGetIOThreads(virCHMonitor *mon,
|
||||
if (!(map = virProcessGetAffinity(iothreadinfo->iothread_id)))
|
||||
goto error;
|
||||
|
||||
virBitmapToData(map, &(iothreadinfo->cpumap), &(iothreadinfo->cpumaplen));
|
||||
if (virBitmapToData(map, &(iothreadinfo->cpumap),
|
||||
&(iothreadinfo->cpumaplen)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Append to iothreadinfolist */
|
||||
iothreadinfolist[niothreads] = g_steal_pointer(&iothreadinfo);
|
||||
|
@ -108,6 +108,8 @@ struct _virCHMonitor {
|
||||
size_t buf_fill_sz;
|
||||
} event_buffer;
|
||||
|
||||
pid_t pid;
|
||||
|
||||
virDomainObj *vm;
|
||||
|
||||
size_t nthreads;
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "virjson.h"
|
||||
#include "virlog.h"
|
||||
#include "virnuma.h"
|
||||
#include "virpidfile.h"
|
||||
#include "virstring.h"
|
||||
#include "ch_interface.h"
|
||||
#include "ch_hostdev.h"
|
||||
@ -131,7 +130,7 @@ virCHProcessUpdateConsole(virDomainObj *vm,
|
||||
virCHProcessUpdateConsoleDevice(vm, config, "serial");
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
virCHProcessUpdateInfo(virDomainObj *vm)
|
||||
{
|
||||
g_autoptr(virJSONValue) info = NULL;
|
||||
@ -430,8 +429,8 @@ virCHProcessSetupVcpus(virDomainObj *vm)
|
||||
size_t i;
|
||||
|
||||
if ((vm->def->cputune.period || vm->def->cputune.quota) &&
|
||||
!virCgroupHasController(CH_DOMAIN_PRIVATE(vm)->cgroup,
|
||||
VIR_CGROUP_CONTROLLER_CPU)) {
|
||||
!virCgroupHasController(((virCHDomainObjPrivate *) vm->privateData)->
|
||||
cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("cgroup cpu is required for scheduler tuning"));
|
||||
return -1;
|
||||
@ -701,7 +700,7 @@ chProcessAddNetworkDevices(virCHDriver *driver,
|
||||
VIR_DEBUG("payload sent with net-add request to CH = %s", payload);
|
||||
|
||||
virBufferAsprintf(&buf, "%s", virBufferCurrentContent(&http_headers));
|
||||
virBufferAsprintf(&buf, "Content-Length: %zu\r\n\r\n", strlen(payload));
|
||||
virBufferAsprintf(&buf, "Content-Length: %ld\r\n\r\n", strlen(payload));
|
||||
virBufferAsprintf(&buf, "%s", payload);
|
||||
payload_len = virBufferUse(&buf);
|
||||
payload = virBufferContentAndReset(&buf);
|
||||
@ -851,21 +850,6 @@ virCHProcessPrepareHost(virCHDriver *driver, virDomainObj *vm)
|
||||
if (virCHHostdevPrepareDomainDevices(driver, vm->def, hostdev_flags) < 0)
|
||||
return -1;
|
||||
|
||||
VIR_FREE(priv->pidfile);
|
||||
if (!(priv->pidfile = virPidFileBuildPath(cfg->stateDir, vm->def->name))) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Failed to build pidfile path."));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlink(priv->pidfile) < 0 &&
|
||||
errno != ENOENT) {
|
||||
virReportSystemError(errno,
|
||||
_("Cannot remove stale PID file %1$s"),
|
||||
priv->pidfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Ensure no historical cgroup for this VM is lying around */
|
||||
VIR_DEBUG("Ensuring no historical cgroup is lying around");
|
||||
virDomainCgroupRemoveCgroup(vm, priv->cgroup, priv->machineName);
|
||||
@ -957,6 +941,7 @@ virCHProcessStart(virCHDriver *driver,
|
||||
}
|
||||
}
|
||||
|
||||
vm->pid = priv->monitor->pid;
|
||||
vm->def->id = vm->pid;
|
||||
priv->machineName = virCHDomainGetMachineName(vm);
|
||||
|
||||
@ -1023,7 +1008,6 @@ virCHProcessStop(virCHDriver *driver,
|
||||
virErrorPreserveLast(&orig_err);
|
||||
|
||||
if (priv->monitor) {
|
||||
virProcessAbort(vm->pid);
|
||||
g_clear_pointer(&priv->monitor, virCHMonitorClose);
|
||||
}
|
||||
|
||||
@ -1051,15 +1035,6 @@ virCHProcessStop(virCHDriver *driver,
|
||||
vm->def->id = -1;
|
||||
g_clear_pointer(&priv->machineName, g_free);
|
||||
|
||||
if (priv->pidfile) {
|
||||
if (unlink(priv->pidfile) < 0 &&
|
||||
errno != ENOENT)
|
||||
VIR_WARN("Failed to remove PID file for %s: %s",
|
||||
vm->def->name, g_strerror(errno));
|
||||
|
||||
g_clear_pointer(&priv->pidfile, g_free);
|
||||
}
|
||||
|
||||
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
|
||||
|
||||
virHostdevReAttachDomainDevices(driver->hostdevMgr, CH_DRIVER_NAME, def,
|
||||
@ -1117,6 +1092,7 @@ virCHProcessStartRestore(virCHDriver *driver, virDomainObj *vm, const char *from
|
||||
}
|
||||
}
|
||||
|
||||
vm->pid = priv->monitor->pid;
|
||||
vm->def->id = vm->pid;
|
||||
priv->machineName = virCHDomainGetMachineName(vm);
|
||||
|
||||
@ -1130,7 +1106,7 @@ virCHProcessStartRestore(virCHDriver *driver, virDomainObj *vm, const char *from
|
||||
virBufferAddLit(&http_headers, "Host: localhost\r\n");
|
||||
virBufferAddLit(&http_headers, "Content-Type: application/json\r\n");
|
||||
virBufferAsprintf(&buf, "%s", virBufferCurrentContent(&http_headers));
|
||||
virBufferAsprintf(&buf, "Content-Length: %zu\r\n\r\n", strlen(payload));
|
||||
virBufferAsprintf(&buf, "Content-Length: %ld\r\n\r\n", strlen(payload));
|
||||
virBufferAsprintf(&buf, "%s", payload);
|
||||
payload_len = virBufferUse(&buf);
|
||||
payload = virBufferContentAndReset(&buf);
|
||||
|
@ -36,5 +36,3 @@ int virCHProcessSetupVcpu(virDomainObj *vm,
|
||||
int virCHProcessStartRestore(virCHDriver *driver,
|
||||
virDomainObj *vm,
|
||||
const char *from);
|
||||
|
||||
int virCHProcessUpdateInfo(virDomainObj *vm);
|
||||
|
@ -228,7 +228,7 @@ virDomainBackupDefParseXML(xmlXPathContextPtr ctxt,
|
||||
|
||||
def->server = g_new0(virStorageNetHostDef, 1);
|
||||
|
||||
if (virDomainStorageNetworkParseHost(node, def->server, true) < 0)
|
||||
if (virDomainStorageNetworkParseHost(node, def->server) < 0)
|
||||
return NULL;
|
||||
|
||||
if (def->server->transport == VIR_STORAGE_NET_HOST_TRANS_RDMA) {
|
||||
@ -388,7 +388,6 @@ virDomainBackupDefFormat(virBuffer *buf,
|
||||
if (def->server->port)
|
||||
virBufferAsprintf(&serverAttrBuf, " port='%u'", def->server->port);
|
||||
virBufferEscapeString(&serverAttrBuf, " socket='%s'", def->server->socket);
|
||||
virBufferEscapeString(&serverAttrBuf, " fdgroup='%s'", def->server->fdgroup);
|
||||
}
|
||||
|
||||
virXMLFormatElement(&childBuf, "server", &serverAttrBuf, NULL);
|
||||
|
@ -6014,81 +6014,58 @@ virDomainHostdevSubsysPCIDefParseXML(xmlNodePtr node,
|
||||
|
||||
int
|
||||
virDomainStorageNetworkParseHost(xmlNodePtr hostnode,
|
||||
virStorageNetHostDef *host,
|
||||
bool allow_fd)
|
||||
virStorageNetHostDef *host)
|
||||
{
|
||||
g_autofree char *socket = NULL;
|
||||
int ret = -1;
|
||||
g_autofree char *transport = NULL;
|
||||
g_autofree char *port = NULL;
|
||||
|
||||
memset(host, 0, sizeof(*host));
|
||||
|
||||
if (virXMLPropEnumDefault(hostnode, "transport",
|
||||
virStorageNetHostTransportTypeFromString,
|
||||
VIR_XML_PROP_NONE,
|
||||
&host->transport,
|
||||
VIR_STORAGE_NET_HOST_TRANS_TCP) < 0)
|
||||
return -1;
|
||||
VIR_STORAGE_NET_HOST_TRANS_TCP) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
socket = virXMLPropString(hostnode, "socket");
|
||||
host->socket = virXMLPropString(hostnode, "socket");
|
||||
|
||||
switch (host->transport) {
|
||||
case VIR_STORAGE_NET_HOST_TRANS_UNIX:
|
||||
if (!socket) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("missing socket for unix transport"));
|
||||
return -1;
|
||||
}
|
||||
if (host->transport == VIR_STORAGE_NET_HOST_TRANS_UNIX &&
|
||||
host->socket == NULL) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("missing socket for unix transport"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
host->socket = g_steal_pointer(&socket);
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_NET_HOST_TRANS_TCP:
|
||||
case VIR_STORAGE_NET_HOST_TRANS_RDMA: {
|
||||
g_autofree char *portstr = NULL;
|
||||
unsigned int port = 0;
|
||||
|
||||
if (socket) {
|
||||
virReportError(VIR_ERR_XML_ERROR,
|
||||
_("transport '%1$s' does not support socket attribute"),
|
||||
virStorageNetHostTransportTypeToString(host->transport));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((portstr = virXMLPropString(hostnode, "port")) &&
|
||||
virStringParsePort(portstr, &port) < 0)
|
||||
return -1;
|
||||
if (host->transport != VIR_STORAGE_NET_HOST_TRANS_UNIX &&
|
||||
host->socket != NULL) {
|
||||
virReportError(VIR_ERR_XML_ERROR,
|
||||
_("transport '%1$s' does not support socket attribute"),
|
||||
transport);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (host->transport != VIR_STORAGE_NET_HOST_TRANS_UNIX) {
|
||||
if (!(host->name = virXMLPropString(hostnode, "name"))) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("missing name for host"));
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
host->port = port;
|
||||
}
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_NET_HOST_TRANS_FD:
|
||||
if (!allow_fd) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("transport 'fd' is now allowed"));
|
||||
return -1;
|
||||
if ((port = virXMLPropString(hostnode, "port"))) {
|
||||
if (virStringParsePort(port, &host->port) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (socket) {
|
||||
virReportError(VIR_ERR_XML_ERROR,
|
||||
_("transport '%1$s' does not support socket attribute"),
|
||||
virStorageNetHostTransportTypeToString(host->transport));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(host->fdgroup = virXMLPropStringRequired(hostnode, "fdgroup")))
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_NET_HOST_TRANS_LAST:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (ret < 0)
|
||||
virStorageNetHostDefClear(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -6112,7 +6089,7 @@ virDomainStorageNetworkParseHosts(xmlNodePtr node,
|
||||
*nhosts = nhostnodes;
|
||||
|
||||
for (i = 0; i < nhostnodes; i++) {
|
||||
if (virDomainStorageNetworkParseHost(hostnodes[i], *hosts + i, false) < 0)
|
||||
if (virDomainStorageNetworkParseHost(hostnodes[i], *hosts + i) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -31002,7 +30979,7 @@ virDomainNetTypeSharesHostView(const virDomainNetDef *net)
|
||||
}
|
||||
|
||||
virNetworkPortDef *
|
||||
virDomainNetDefToNetworkPort(const virDomainDef *dom,
|
||||
virDomainNetDefToNetworkPort(virDomainDef *dom,
|
||||
virDomainNetDef *iface)
|
||||
{
|
||||
g_autoptr(virNetworkPortDef) port = NULL;
|
||||
@ -31128,7 +31105,7 @@ virDomainNetDefActualFromNetworkPort(virDomainNetDef *iface,
|
||||
}
|
||||
|
||||
virNetworkPortDef *
|
||||
virDomainNetDefActualToNetworkPort(const virDomainDef *dom,
|
||||
virDomainNetDefActualToNetworkPort(virDomainDef *dom,
|
||||
virDomainNetDef *iface)
|
||||
{
|
||||
virDomainActualNetDef *actual;
|
||||
@ -31240,7 +31217,7 @@ virDomainNetDefActualToNetworkPort(const virDomainDef *dom,
|
||||
|
||||
static int
|
||||
virDomainNetCreatePort(virConnectPtr conn,
|
||||
const virDomainDef *dom,
|
||||
virDomainDef *dom,
|
||||
virDomainNetDef *iface,
|
||||
unsigned int flags)
|
||||
{
|
||||
@ -31305,7 +31282,7 @@ virDomainNetCreatePort(virConnectPtr conn,
|
||||
|
||||
int
|
||||
virDomainNetAllocateActualDevice(virConnectPtr conn,
|
||||
const virDomainDef *dom,
|
||||
virDomainDef *dom,
|
||||
virDomainNetDef *iface)
|
||||
{
|
||||
return virDomainNetCreatePort(conn, dom, iface, 0);
|
||||
@ -31313,7 +31290,7 @@ virDomainNetAllocateActualDevice(virConnectPtr conn,
|
||||
|
||||
void
|
||||
virDomainNetNotifyActualDevice(virConnectPtr conn,
|
||||
const virDomainDef *dom,
|
||||
virDomainDef *dom,
|
||||
virDomainNetDef *iface)
|
||||
{
|
||||
virDomainNetType actualType = virDomainNetGetActualType(iface);
|
||||
|
@ -4024,8 +4024,7 @@ virDomainDiskByTarget(virDomainDef *def,
|
||||
|
||||
void virDomainDiskInsert(virDomainDef *def, virDomainDiskDef *disk);
|
||||
int virDomainStorageNetworkParseHost(xmlNodePtr hostnode,
|
||||
virStorageNetHostDef *host,
|
||||
bool allow_fd);
|
||||
virStorageNetHostDef *host);
|
||||
int virDomainDiskDefAssignAddress(virDomainXMLOption *xmlopt,
|
||||
virDomainDiskDef *def,
|
||||
const virDomainDef *vmdef);
|
||||
@ -4531,7 +4530,7 @@ virDomainDefLifecycleActionAllowed(virDomainLifecycle type,
|
||||
virDomainLifecycleAction action);
|
||||
|
||||
virNetworkPortDef *
|
||||
virDomainNetDefToNetworkPort(const virDomainDef *dom,
|
||||
virDomainNetDefToNetworkPort(virDomainDef *dom,
|
||||
virDomainNetDef *iface);
|
||||
|
||||
int
|
||||
@ -4539,18 +4538,18 @@ virDomainNetDefActualFromNetworkPort(virDomainNetDef *iface,
|
||||
virNetworkPortDef *port);
|
||||
|
||||
virNetworkPortDef *
|
||||
virDomainNetDefActualToNetworkPort(const virDomainDef *dom,
|
||||
virDomainNetDefActualToNetworkPort(virDomainDef *dom,
|
||||
virDomainNetDef *iface);
|
||||
|
||||
int
|
||||
virDomainNetAllocateActualDevice(virConnectPtr conn,
|
||||
const virDomainDef *dom,
|
||||
virDomainDef *dom,
|
||||
virDomainNetDef *iface)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
|
||||
void
|
||||
virDomainNetNotifyActualDevice(virConnectPtr conn,
|
||||
const virDomainDef *dom,
|
||||
virDomainDef *dom,
|
||||
virDomainNetDef *iface)
|
||||
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||
|
||||
|
@ -562,7 +562,7 @@ virDomainDiskDefValidateSourceChainOne(const virStorageSource *src)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (src->dataFileStore->dataFileStore || src->dataFileStore->backingStore) {
|
||||
if (src->dataFileStore->dataFileStore || src->backingStore) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("The <source> of <dataStore> can't have another nested <dataStore> or <backingStore> element"));
|
||||
return -1;
|
||||
|
@ -90,12 +90,6 @@
|
||||
<ref name="absFilePath"/>
|
||||
</attribute>
|
||||
</group>
|
||||
<group>
|
||||
<attribute name="transport">
|
||||
<value>fd</value>
|
||||
</attribute>
|
||||
<attribute name="fdgroup"/>
|
||||
</group>
|
||||
</choice>
|
||||
</element>
|
||||
<ref name="backupDisksPull"/>
|
||||
|
@ -1409,8 +1409,6 @@ virStorageVolDefParse(virStoragePoolDef *pool,
|
||||
"volume", &ctxt, "storagevol.rng", validate)))
|
||||
return NULL;
|
||||
|
||||
flags &= ~VIR_VOL_XML_PARSE_VALIDATE;
|
||||
|
||||
return virStorageVolDefParseXML(pool, ctxt, flags);
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,6 @@ VIR_ENUM_IMPL(virStorageNetHostTransport,
|
||||
"tcp",
|
||||
"unix",
|
||||
"rdma",
|
||||
"fd",
|
||||
);
|
||||
|
||||
|
||||
@ -142,6 +141,17 @@ virStorageSourceHasBacking(const virStorageSource *src)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
virStorageNetHostDefClear(virStorageNetHostDef *def)
|
||||
{
|
||||
if (!def)
|
||||
return;
|
||||
|
||||
VIR_FREE(def->name);
|
||||
VIR_FREE(def->socket);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
virStorageNetHostDefFree(size_t nhosts,
|
||||
virStorageNetHostDef *hosts)
|
||||
@ -151,12 +161,8 @@ virStorageNetHostDefFree(size_t nhosts,
|
||||
if (!hosts)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nhosts; i++) {
|
||||
g_free(hosts[i].name);
|
||||
g_free(hosts[i].socket);
|
||||
g_free(hosts[i].fdgroup);
|
||||
g_free(hosts[i].qemu_fdname);
|
||||
}
|
||||
for (i = 0; i < nhosts; i++)
|
||||
virStorageNetHostDefClear(&hosts[i]);
|
||||
|
||||
g_free(hosts);
|
||||
}
|
||||
|
@ -141,7 +141,6 @@ typedef enum {
|
||||
VIR_STORAGE_NET_HOST_TRANS_TCP,
|
||||
VIR_STORAGE_NET_HOST_TRANS_UNIX,
|
||||
VIR_STORAGE_NET_HOST_TRANS_RDMA,
|
||||
VIR_STORAGE_NET_HOST_TRANS_FD,
|
||||
|
||||
VIR_STORAGE_NET_HOST_TRANS_LAST
|
||||
} virStorageNetHostTransport;
|
||||
@ -155,9 +154,6 @@ struct _virStorageNetHostDef {
|
||||
unsigned int port;
|
||||
virStorageNetHostTransport transport;
|
||||
char *socket; /* path to unix socket */
|
||||
|
||||
char *fdgroup;
|
||||
char *qemu_fdname; /* name used with 'getfd' to pass to qemu - internal */
|
||||
};
|
||||
|
||||
|
||||
@ -506,6 +502,9 @@ virSecurityDeviceLabelDef *
|
||||
virStorageSourceGetSecurityLabelDef(virStorageSource *src,
|
||||
const char *model);
|
||||
|
||||
void
|
||||
virStorageNetHostDefClear(virStorageNetHostDef *def);
|
||||
|
||||
void
|
||||
virStorageNetHostDefFree(size_t nhosts,
|
||||
virStorageNetHostDef *hosts);
|
||||
|
@ -1,7 +1,5 @@
|
||||
cpumap_data = [
|
||||
'arm_a64fx.xml',
|
||||
'arm_Ampere-1a.xml',
|
||||
'arm_Ampere-1.xml',
|
||||
'arm_cortex-a53.xml',
|
||||
'arm_cortex-a57.xml',
|
||||
'arm_cortex-a72.xml',
|
||||
|
@ -687,9 +687,7 @@ esxConnectToVCenter(esxPrivate *priv,
|
||||
g_autofree char *url = NULL;
|
||||
|
||||
if (!hostSystemIPAddress &&
|
||||
(!priv->parsedUri->path ||
|
||||
STREQ(priv->parsedUri->path, "") ||
|
||||
STREQ(priv->parsedUri->path, "/"))) {
|
||||
(!priv->parsedUri->path || STREQ(priv->parsedUri->path, "/"))) {
|
||||
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
_("Path has to specify the datacenter and compute resource"));
|
||||
return -1;
|
||||
@ -801,7 +799,6 @@ esxConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
||||
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
||||
|
||||
if (STRCASENEQ(conn->uri->scheme, "vpx") &&
|
||||
STRNEQ(conn->uri->path, "") &&
|
||||
STRNEQ(conn->uri->path, "/")) {
|
||||
VIR_WARN("Ignoring unexpected path '%s' for non-vpx scheme '%s'",
|
||||
conn->uri->path, conn->uri->scheme);
|
||||
@ -4795,20 +4792,18 @@ esxConnectListAllDomains(virConnectPtr conn,
|
||||
virtualMachine = virtualMachine->_next) {
|
||||
g_autofree char *name = NULL;
|
||||
|
||||
/* If the lookup of the required properties fails for some of the machines
|
||||
* in the list it's preferrable to return the valid objects instead of
|
||||
* failing outright */
|
||||
if ((needIdentity && esxVI_GetVirtualMachineIdentity(virtualMachine, &id, &name, uuid) < 0) ||
|
||||
(needPowerState && esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0)) {
|
||||
|
||||
/* Raise error only if we didn't successfuly fill any domain */
|
||||
if (count == 0 && !virtualMachine->_next)
|
||||
if (needIdentity) {
|
||||
if (esxVI_GetVirtualMachineIdentity(virtualMachine, &id,
|
||||
&name, uuid) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* failure to fetch information of a single VM must not interrupt
|
||||
* the lookup of the rest */
|
||||
virResetLastError();
|
||||
continue;
|
||||
if (needPowerState) {
|
||||
if (esxVI_GetVirtualMachinePowerState(virtualMachine,
|
||||
&powerState) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* filter by active state */
|
||||
|
@ -652,7 +652,9 @@ virDomainDriverGetIOThreadsConfig(virDomainDef *targetDef,
|
||||
cpumask = bitmap;
|
||||
}
|
||||
}
|
||||
virBitmapToData(cpumask, &info_ret[i]->cpumap, &info_ret[i]->cpumaplen);
|
||||
if (virBitmapToData(cpumask, &info_ret[i]->cpumap,
|
||||
&info_ret[i]->cpumaplen) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*info = g_steal_pointer(&info_ret);
|
||||
|
@ -410,20 +410,17 @@ virConnectGetMaxVcpus(virConnectPtr conn,
|
||||
* Use of this API is strongly discouraged as the information provided
|
||||
* is not guaranteed to be accurate on all hardware platforms.
|
||||
*
|
||||
* The CPU frequency value (field 'mhz' in virNodeInfo) merely reflects the
|
||||
* speed that the first CPU in the machine is currently running at. This speed
|
||||
* may vary across CPUs and changes continually as the host OS throttles.
|
||||
* The mHZ value merely reflects the speed that the first CPU in the
|
||||
* machine is currently running at. This speed may vary across CPUs
|
||||
* and changes continually as the host OS throttles.
|
||||
*
|
||||
* The virNodeInfo structure is not extensible thus only supports global
|
||||
* nodes/sockets/cores/threads (sockets/cores/threads is per NUMA node)
|
||||
* topology information. If the host CPU has any further groupings (e.g.
|
||||
* dies, clusters, etc) or the NUMA topology is non-symmetrical the structure
|
||||
* can't faithfully represent the system. In such cases a fake topology
|
||||
* (nodes = 1, sockets = 1, cores = number of host cpus, threads = 1) which
|
||||
* only correctly represents the total host CPU count is reported.
|
||||
* The nodes/sockets/cores/threads data is potentially inaccurate as
|
||||
* it assumes a symmetric installation. If one NUMA node has more
|
||||
* sockets populated that another NUMA node this information will be
|
||||
* wrong. It is also not able to report about CPU dies.
|
||||
*
|
||||
* Applications are recommended to use the virConnectGetCapabilities()
|
||||
* call instead, which provides all the information except CPU frequency,
|
||||
* call instead, which provides all the information except CPU mHZ,
|
||||
* in a more accurate representation.
|
||||
*
|
||||
* Returns 0 in case of success and -1 in case of failure.
|
||||
|
@ -1153,6 +1153,7 @@ virStorageFileFeatureTypeFromString;
|
||||
virStorageFileFeatureTypeToString;
|
||||
virStorageFileFormatTypeFromString;
|
||||
virStorageFileFormatTypeToString;
|
||||
virStorageNetHostDefClear;
|
||||
virStorageNetHostDefCopy;
|
||||
virStorageNetHostDefFree;
|
||||
virStorageNetHostTransportTypeFromString;
|
||||
|
@ -582,107 +582,6 @@ libxlMakeDomBuildInfo(virDomainDef *def,
|
||||
VIR_TRISTATE_SWITCH_ON);
|
||||
#endif
|
||||
|
||||
#ifdef LIBXL_HAVE_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE
|
||||
if (def->features[VIR_DOMAIN_FEATURE_HYPERV] != VIR_DOMAIN_HYPERV_MODE_NONE) {
|
||||
libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
|
||||
LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
|
||||
|
||||
switch ((virDomainHyperVMode) def->features[VIR_DOMAIN_FEATURE_HYPERV]) {
|
||||
case VIR_DOMAIN_HYPERV_MODE_CUSTOM:
|
||||
/* Base is required by Xen to enable any other flag */
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_BASE);
|
||||
/* Enable crash ctl register by default to allow guest logs to reach Xen */
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_CRASH_CTL);
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH:
|
||||
libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_MODE_NONE:
|
||||
case VIR_DOMAIN_HYPERV_MODE_LAST:
|
||||
default:
|
||||
virReportEnumRangeError(virDomainHyperVMode,
|
||||
def->features[VIR_DOMAIN_FEATURE_HYPERV]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
|
||||
switch ((virDomainHyperv) i) {
|
||||
case VIR_DOMAIN_HYPERV_VPINDEX:
|
||||
case VIR_DOMAIN_HYPERV_RELAXED:
|
||||
/* Already set by base flag */
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_SYNIC:
|
||||
if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC);
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_STIMER:
|
||||
if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
|
||||
/* STIMER implies synic and clock features */
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_STIMER);
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC);
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT);
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC);
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_VAPIC:
|
||||
if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_APIC_ASSIST);
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_FREQUENCIES:
|
||||
if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_FREQ);
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_TLBFLUSH:
|
||||
if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_REMOTE_TLB_FLUSH);
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_IPI:
|
||||
if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
|
||||
libxl_bitmap_set(&b_info->u.hvm.viridian_enable,
|
||||
LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_IPI);
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_SPINLOCKS:
|
||||
case VIR_DOMAIN_HYPERV_VENDOR_ID:
|
||||
if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
|
||||
const char *name = virDomainHypervTypeToString(i);
|
||||
VIR_WARN("Hyper-v flag '%s' specified per-domain but is a global Xen setting and will be ignored.", name);
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_RUNTIME:
|
||||
case VIR_DOMAIN_HYPERV_RESET:
|
||||
case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
|
||||
case VIR_DOMAIN_HYPERV_EVMCS:
|
||||
case VIR_DOMAIN_HYPERV_AVIC:
|
||||
case VIR_DOMAIN_HYPERV_EMSR_BITMAP:
|
||||
case VIR_DOMAIN_HYPERV_XMM_INPUT:
|
||||
if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
|
||||
const char *name = virDomainHypervTypeToString(i);
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Hyper-v enlightenment feature '%1$s' is not supported for Xen domains."), name);
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_HYPERV_LAST:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* copy the table path to acpi_firmware */
|
||||
if (def->os.nacpiTables)
|
||||
b_info->u.hvm.acpi_firmware = g_strdup(def->os.acpiTables[0]->path);
|
||||
|
@ -710,8 +710,7 @@ networkStateInitialize(bool privileged,
|
||||
network_driver->networkEventState = virObjectEventStateNew();
|
||||
|
||||
#ifdef WITH_FIREWALLD
|
||||
if (!virGDBusHasSystemBus() ||
|
||||
!(sysbus = virGDBusGetSystemBus())) {
|
||||
if (!(sysbus = virGDBusGetSystemBus())) {
|
||||
VIR_WARN("DBus not available, disabling firewalld support "
|
||||
"in bridge_network_driver: %s", virGetLastErrorMessage());
|
||||
} else {
|
||||
|
@ -203,12 +203,12 @@ virNWFilterInstReset(virNWFilterInst *inst)
|
||||
|
||||
for (i = 0; i < inst->nfilters; i++)
|
||||
virNWFilterObjUnlock(inst->filters[i]);
|
||||
g_clear_pointer(&inst->filters, g_free);
|
||||
g_free(inst->filters);
|
||||
inst->nfilters = 0;
|
||||
|
||||
for (i = 0; i < inst->nrules; i++)
|
||||
virNWFilterRuleInstFree(inst->rules[i]);
|
||||
g_clear_pointer(&inst->rules, g_free);
|
||||
g_free(inst->rules);
|
||||
inst->nrules = 0;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ qemu_driver_sources = [
|
||||
'qemu_migration_params.c',
|
||||
'qemu_monitor.c',
|
||||
'qemu_monitor_json.c',
|
||||
'qemu_monitor_text.c',
|
||||
'qemu_namespace.c',
|
||||
'qemu_nbdkit.c',
|
||||
'qemu_passt.c',
|
||||
|
@ -87,7 +87,6 @@ qemuBackupPrepare(virDomainBackupDef *def)
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_NET_HOST_TRANS_RDMA:
|
||||
case VIR_STORAGE_NET_HOST_TRANS_FD:
|
||||
case VIR_STORAGE_NET_HOST_TRANS_LAST:
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unexpected transport in <domainbackup>"));
|
||||
@ -761,7 +760,6 @@ qemuBackupBegin(virDomainObj *vm,
|
||||
bool reuse = (flags & VIR_DOMAIN_BACKUP_BEGIN_REUSE_EXTERNAL);
|
||||
int rc = 0;
|
||||
int ret = -1;
|
||||
g_autoptr(qemuFDPassDirect) fdpass = NULL;
|
||||
|
||||
virCheckFlags(VIR_DOMAIN_BACKUP_BEGIN_REUSE_EXTERNAL, -1);
|
||||
|
||||
@ -848,29 +846,6 @@ qemuBackupBegin(virDomainObj *vm,
|
||||
|
||||
priv->backup = g_steal_pointer(&def);
|
||||
|
||||
if (pull && priv->backup->server->fdgroup) {
|
||||
virStorageSourceFDTuple *fdt = NULL;
|
||||
VIR_AUTOCLOSE fdcopy = -1;
|
||||
|
||||
if (!(fdt = virHashLookup(priv->fds, priv->backup->server->fdgroup))) {
|
||||
virReportError(VIR_ERR_INVALID_ARG,
|
||||
_("file descriptor group '%1$s' was not associated with the domain"),
|
||||
priv->backup->server->fdgroup);
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
if (fdt->nfds != 1) {
|
||||
virReportError(VIR_ERR_INVALID_ARG,
|
||||
_("file descriptor group '%1$s' must contain only 1 file descriptor for NBD server"),
|
||||
priv->backup->server->fdgroup);
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
priv->backup->server->qemu_fdname = g_strdup("libvirt-backup-nbd");
|
||||
fdcopy = dup(fdt->fds[0]);
|
||||
fdpass = qemuFDPassDirectNew(priv->backup->server->qemu_fdname, &fdcopy);
|
||||
}
|
||||
|
||||
if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_BACKUP) < 0)
|
||||
goto endjob;
|
||||
|
||||
@ -881,9 +856,6 @@ qemuBackupBegin(virDomainObj *vm,
|
||||
if (rc == 0 && tlsProps)
|
||||
rc = qemuMonitorAddObject(priv->mon, &tlsProps, &tlsAlias);
|
||||
|
||||
if (rc == 0 && fdpass)
|
||||
rc = qemuFDPassDirectTransferMonitor(fdpass, priv->mon);
|
||||
|
||||
if (rc == 0) {
|
||||
if ((rc = qemuMonitorNBDServerStart(priv->mon, priv->backup->server, tlsAlias)) == 0)
|
||||
nbd_running = true;
|
||||
|
@ -266,7 +266,6 @@ qemuBlockStorageSourceBuildJSONSocketAddress(virStorageNetHostDef *host)
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_NET_HOST_TRANS_RDMA:
|
||||
case VIR_STORAGE_NET_HOST_TRANS_FD:
|
||||
case VIR_STORAGE_NET_HOST_TRANS_LAST:
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("transport protocol '%1$s' is not yet supported"),
|
||||
@ -2875,9 +2874,6 @@ qemuBlockThrottleFiltersDetach(qemuMonitor *mon,
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
for (i = data->nfilterdata; i > 0; i--)
|
||||
qemuBlockThrottleFilterAttachRollback(mon, data->filterdata[i-1]);
|
||||
}
|
||||
@ -3645,6 +3641,9 @@ qemuBlockExportGetNBDProps(const char *nodename,
|
||||
* @writable: whether the NBD export allows writes
|
||||
* @bitmap: (optional) block dirty bitmap to export along
|
||||
*
|
||||
* This function automatically selects the proper invocation of exporting a
|
||||
* block backend via NBD in qemu.
|
||||
*
|
||||
* This function must be called while in the monitor context.
|
||||
*/
|
||||
int
|
||||
@ -3658,6 +3657,10 @@ qemuBlockExportAddNBD(virDomainObj *vm,
|
||||
g_autoptr(virJSONValue) nbdprops = NULL;
|
||||
const char *bitmaps[2] = { bitmap, NULL };
|
||||
|
||||
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_EXPORT_ADD))
|
||||
return qemuMonitorNBDServerAdd(priv->mon, qemuBlockStorageSourceGetEffectiveNodename(src),
|
||||
exportname, writable, bitmap);
|
||||
|
||||
if (!(nbdprops = qemuBlockExportGetNBDProps(qemuBlockStorageSourceGetEffectiveNodename(src),
|
||||
exportname, writable, bitmaps)))
|
||||
return -1;
|
||||
|
@ -529,7 +529,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
|
||||
|
||||
/* 330 */
|
||||
"bitmap-merge", /* X_QEMU_CAPS_BITMAP_MERGE */
|
||||
"nbd-bitmap", /* X_QEMU_CAPS_NBD_BITMAP */
|
||||
"nbd-bitmap", /* QEMU_CAPS_NBD_BITMAP */
|
||||
"x86-max-cpu", /* QEMU_CAPS_X86_MAX_CPU */
|
||||
"cpu-unavailable-features", /* QEMU_CAPS_CPU_UNAVAILABLE_FEATURES */
|
||||
"canonical-cpu-features", /* QEMU_CAPS_CANONICAL_CPU_FEATURES */
|
||||
@ -600,7 +600,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
|
||||
/* 380 */
|
||||
"usb-host.hostdevice", /* QEMU_CAPS_USB_HOST_HOSTDEVICE */
|
||||
"virtio-balloon.free-page-reporting", /* QEMU_CAPS_VIRTIO_BALLOON_FREE_PAGE_REPORTING */
|
||||
"block-export-add", /* X_QEMU_CAPS_BLOCK_EXPORT_ADD */
|
||||
"block-export-add", /* QEMU_CAPS_BLOCK_EXPORT_ADD */
|
||||
"netdev.vhost-vdpa", /* QEMU_CAPS_NETDEV_VHOST_VDPA */
|
||||
"fsdev.createmode", /* X_QEMU_CAPS_FSDEV_CREATEMODE */
|
||||
|
||||
@ -717,7 +717,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
|
||||
"machine-i8042-opt", /* QEMU_CAPS_MACHINE_I8042_OPT */
|
||||
|
||||
/* 465 */
|
||||
"snapshot-internal-qmp", /* X_QEMU_CAPS_SNAPSHOT_INTERNAL_QMP */
|
||||
"snapshot-internal-qmp", /* QEMU_CAPS_SNAPSHOT_INTERNAL_QMP */
|
||||
"chardev-reconnect-miliseconds", /* QEMU_CAPS_CHARDEV_RECONNECT_MILISECONDS */
|
||||
"virtio-ccw.loadparm", /* QEMU_CAPS_VIRTIO_CCW_DEVICE_LOADPARM */
|
||||
"netdev-stream-reconnect-miliseconds", /* QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS */
|
||||
@ -1243,6 +1243,7 @@ struct virQEMUCapsStringFlags virQEMUCapsCommands[] = {
|
||||
{ "query-cpu-definitions", QEMU_CAPS_QUERY_CPU_DEFINITIONS },
|
||||
{ "query-cpu-model-baseline", QEMU_CAPS_QUERY_CPU_MODEL_BASELINE },
|
||||
{ "query-cpu-model-comparison", QEMU_CAPS_QUERY_CPU_MODEL_COMPARISON },
|
||||
{ "block-export-add", QEMU_CAPS_BLOCK_EXPORT_ADD },
|
||||
{ "set-action", QEMU_CAPS_SET_ACTION },
|
||||
{ "query-dirty-rate", QEMU_CAPS_QUERY_DIRTY_RATE },
|
||||
{ "sev-inject-launch-secret", QEMU_CAPS_SEV_INJECT_LAUNCH_SECRET },
|
||||
@ -1250,6 +1251,7 @@ struct virQEMUCapsStringFlags virQEMUCapsCommands[] = {
|
||||
{ "query-stats", QEMU_CAPS_QUERY_STATS },
|
||||
{ "query-stats-schemas", QEMU_CAPS_QUERY_STATS_SCHEMAS },
|
||||
{ "display-reload", QEMU_CAPS_DISPLAY_RELOAD },
|
||||
{ "snapshot-save", QEMU_CAPS_SNAPSHOT_INTERNAL_QMP },
|
||||
{ "blockdev-set-active", QEMU_CAPS_BLOCKDEV_SET_ACTIVE },
|
||||
};
|
||||
|
||||
@ -1581,6 +1583,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = {
|
||||
{ "chardev-add/arg-type/backend/+qemu-vdagent", QEMU_CAPS_CHARDEV_QEMU_VDAGENT },
|
||||
{ "device_add/$json-cli-hotplug", QEMU_CAPS_DEVICE_JSON },
|
||||
{ "nbd-server-start/arg-type/tls-creds", QEMU_CAPS_NBD_TLS },
|
||||
{ "nbd-server-add/arg-type/bitmap", QEMU_CAPS_NBD_BITMAP },
|
||||
{ "netdev_add/arg-type/+stream", QEMU_CAPS_NETDEV_STREAM },
|
||||
{ "netdev_add/arg-type/+stream/reconnect", QEMU_CAPS_NETDEV_STREAM_RECONNECT },
|
||||
{ "netdev_add/arg-type/+vhost-vdpa", QEMU_CAPS_NETDEV_VHOST_VDPA },
|
||||
|
@ -510,7 +510,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
|
||||
|
||||
/* 330 */
|
||||
X_QEMU_CAPS_BITMAP_MERGE, /* block-dirty-bitmap-merge */
|
||||
X_QEMU_CAPS_NBD_BITMAP, /* nbd-server-add supports bitmap */
|
||||
QEMU_CAPS_NBD_BITMAP, /* nbd-server-add supports bitmap */
|
||||
QEMU_CAPS_X86_MAX_CPU, /* max-x86_64-cpu type exists */
|
||||
QEMU_CAPS_CPU_UNAVAILABLE_FEATURES, /* "unavailable-features" CPU property */
|
||||
QEMU_CAPS_CANONICAL_CPU_FEATURES, /* avoid CPU feature aliases */
|
||||
@ -581,7 +581,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
|
||||
/* 380 */
|
||||
QEMU_CAPS_USB_HOST_HOSTDEVICE, /* -device usb-host.hostdevice */
|
||||
QEMU_CAPS_VIRTIO_BALLOON_FREE_PAGE_REPORTING, /*virtio balloon free-page-reporting */
|
||||
X_QEMU_CAPS_BLOCK_EXPORT_ADD, /* 'block-export-add' command is supported */
|
||||
QEMU_CAPS_BLOCK_EXPORT_ADD, /* 'block-export-add' command is supported */
|
||||
QEMU_CAPS_NETDEV_VHOST_VDPA, /* -netdev vhost-vdpa*/
|
||||
X_QEMU_CAPS_FSDEV_CREATEMODE, /* fsdev.createmode */
|
||||
|
||||
@ -698,7 +698,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
|
||||
QEMU_CAPS_MACHINE_I8042_OPT, /* -machine xxx,i8042=on/off; use virQEMUCapsSupportsI8042Toggle() to query this capability */
|
||||
|
||||
/* 465 */
|
||||
X_QEMU_CAPS_SNAPSHOT_INTERNAL_QMP, /* internal snapshot support via QMP commands 'snapshot-save'/'snapshot-delete' */
|
||||
QEMU_CAPS_SNAPSHOT_INTERNAL_QMP, /* internal snapshot support via QMP commands 'snapshot-save'/'snapshot-delete' */
|
||||
QEMU_CAPS_CHARDEV_RECONNECT_MILISECONDS, /* 'reconnect-ms' option for chardevs supported */
|
||||
QEMU_CAPS_VIRTIO_CCW_DEVICE_LOADPARM, /* loadparm available on CCW device for multi device boot */
|
||||
QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS, /* 'reconnect-ms' option for netdev stream supported */
|
||||
|
@ -10685,6 +10685,12 @@ qemuBuildCommandLine(virDomainObj *vm,
|
||||
if (qemuBuildSecCommandLine(vm, cmd, def->sec) < 0)
|
||||
return NULL;
|
||||
|
||||
/* Internal snapshot reversion happens via QMP command after startup if
|
||||
* supported */
|
||||
if (snapshot &&
|
||||
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SNAPSHOT_INTERNAL_QMP))
|
||||
virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
|
||||
|
||||
if (def->namespaceData) {
|
||||
qemuDomainXmlNsDef *qemuxmlns;
|
||||
GStrv n;
|
||||
|
@ -5321,7 +5321,8 @@ qemuDomainDefFormatBufInternal(virQEMUDriver *driver,
|
||||
*/
|
||||
if (origCPU) {
|
||||
virCPUDefFree(def->cpu);
|
||||
def->cpu = virCPUDefCopy(origCPU);
|
||||
if (!(def->cpu = virCPUDefCopy(origCPU)))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (def->cpu &&
|
||||
@ -5790,7 +5791,7 @@ static void
|
||||
qemuDomainRemoveInactiveCommon(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
virDomainUndefineFlagsValues flags,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
{
|
||||
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
||||
g_autofree char *snapDir = NULL;
|
||||
@ -5816,7 +5817,7 @@ qemuDomainRemoveInactiveCommon(virQEMUDriver *driver,
|
||||
if (rmdir(chkDir) < 0 && errno != ENOENT)
|
||||
VIR_WARN("unable to remove checkpoint directory %s", chkDir);
|
||||
}
|
||||
qemuExtDevicesCleanupHost(driver, vm->def, flags, migration);
|
||||
qemuExtDevicesCleanupHost(driver, vm->def, flags, outgoingMigration);
|
||||
}
|
||||
|
||||
|
||||
@ -5829,14 +5830,14 @@ void
|
||||
qemuDomainRemoveInactive(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
virDomainUndefineFlagsValues flags,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
{
|
||||
if (vm->persistent) {
|
||||
/* Short-circuit, we don't want to remove a persistent domain */
|
||||
return;
|
||||
}
|
||||
|
||||
qemuDomainRemoveInactiveCommon(driver, vm, flags, migration);
|
||||
qemuDomainRemoveInactiveCommon(driver, vm, flags, outgoingMigration);
|
||||
|
||||
virDomainObjListRemove(driver->domains, vm);
|
||||
}
|
||||
@ -9353,8 +9354,8 @@ qemuDomainSaveCookieNew(virDomainObj *vm)
|
||||
if (!(cookie = virObjectNew(qemuDomainSaveCookieClass)))
|
||||
return NULL;
|
||||
|
||||
if (priv->origCPU)
|
||||
cookie->cpu = virCPUDefCopy(vm->def->cpu);
|
||||
if (priv->origCPU && !(cookie->cpu = virCPUDefCopy(vm->def->cpu)))
|
||||
return NULL;
|
||||
|
||||
cookie->slirpHelper = qemuDomainGetSlirpHelperOk(vm);
|
||||
|
||||
@ -9694,7 +9695,7 @@ qemuDomainPrepareStorageSourceFDs(virStorageSource *src,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
int
|
||||
qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
|
||||
virStorageSource *src,
|
||||
const char *nodenameprefix,
|
||||
@ -10087,7 +10088,6 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
|
||||
case QEMU_PROCESS_EVENT_WATCHDOG:
|
||||
case QEMU_PROCESS_EVENT_DEVICE_DELETED:
|
||||
case QEMU_PROCESS_EVENT_NETDEV_STREAM_DISCONNECTED:
|
||||
case QEMU_PROCESS_EVENT_NETDEV_VHOST_USER_DISCONNECTED:
|
||||
case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
|
||||
case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
|
||||
case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED:
|
||||
|
@ -469,7 +469,6 @@ typedef enum {
|
||||
QEMU_PROCESS_EVENT_GUESTPANIC,
|
||||
QEMU_PROCESS_EVENT_DEVICE_DELETED,
|
||||
QEMU_PROCESS_EVENT_NETDEV_STREAM_DISCONNECTED,
|
||||
QEMU_PROCESS_EVENT_NETDEV_VHOST_USER_DISCONNECTED,
|
||||
QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED,
|
||||
QEMU_PROCESS_EVENT_SERIAL_CHANGED,
|
||||
QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE,
|
||||
@ -694,7 +693,7 @@ int qemuDomainMomentDiscardAll(void *payload,
|
||||
void qemuDomainRemoveInactive(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
virDomainUndefineFlagsValues flags,
|
||||
bool migration);
|
||||
bool outgoingMigration);
|
||||
|
||||
void
|
||||
qemuDomainRemoveInactiveLocked(virQEMUDriver *driver,
|
||||
@ -758,6 +757,11 @@ int qemuDomainStorageSourceAccessAllow(virQEMUDriver *driver,
|
||||
bool newSource,
|
||||
bool chainTop);
|
||||
|
||||
int qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
|
||||
virStorageSource *src,
|
||||
const char *nodenameprefix,
|
||||
qemuDomainObjPrivate *priv,
|
||||
virQEMUDriverConfig *cfg);
|
||||
int qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDef *disk,
|
||||
virStorageSource *src,
|
||||
qemuDomainObjPrivate *priv,
|
||||
|
@ -3607,12 +3607,12 @@ processDeviceDeletedEvent(virQEMUDriver *driver,
|
||||
|
||||
|
||||
static void
|
||||
processNetdevDisconnectedEvent(virDomainObj *vm,
|
||||
const char *netdevId,
|
||||
const char *eventName)
|
||||
processNetdevStreamDisconnectedEvent(virDomainObj *vm,
|
||||
const char *netdevId)
|
||||
{
|
||||
virDomainDeviceDef dev;
|
||||
virDomainNetDef *def;
|
||||
virQEMUCaps *qemuCaps = QEMU_DOMAIN_PRIVATE(vm)->qemuCaps;
|
||||
const char *devAlias = STRSKIP(netdevId, "host");
|
||||
|
||||
/* The event sends us the "netdev-id", but we don't store the
|
||||
@ -3624,13 +3624,13 @@ processNetdevDisconnectedEvent(virDomainObj *vm,
|
||||
*/
|
||||
|
||||
if (!devAlias) {
|
||||
VIR_WARN("Received %s event for unrecognized netdev %s from domain %p %s",
|
||||
eventName, netdevId, vm, vm->def->name);
|
||||
VIR_WARN("Received NETDEV_STREAM_DISCONNECTED event for unrecognized netdev %s from domain %p %s",
|
||||
netdevId, vm, vm->def->name);
|
||||
return;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Received %s event for device %s from domain %p %s",
|
||||
eventName, devAlias, vm, vm->def->name);
|
||||
VIR_DEBUG("Received NETDEV_STREAM_DISCONNECTED event for device %s from domain %p %s",
|
||||
devAlias, vm, vm->def->name);
|
||||
|
||||
if (virDomainObjBeginJob(vm, VIR_JOB_QUERY) < 0)
|
||||
return;
|
||||
@ -3641,28 +3641,34 @@ processNetdevDisconnectedEvent(virDomainObj *vm,
|
||||
}
|
||||
|
||||
if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) {
|
||||
VIR_WARN("%s event received for non-existent device %s in domain %s",
|
||||
eventName, devAlias, vm->def->name);
|
||||
VIR_WARN("NETDEV_STREAM_DISCONNECTED event received for non-existent device %s in domain %s",
|
||||
devAlias, vm->def->name);
|
||||
goto endjob;
|
||||
}
|
||||
if (dev.type != VIR_DOMAIN_DEVICE_NET) {
|
||||
VIR_WARN("%s event received for non-network device %s in domain %s",
|
||||
eventName, devAlias, vm->def->name);
|
||||
VIR_WARN("NETDEV_STREAM_DISCONNECTED event received for non-network device %s in domain %s",
|
||||
devAlias, vm->def->name);
|
||||
goto endjob;
|
||||
}
|
||||
def = dev.data.net;
|
||||
|
||||
if (def->backend.type != VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
VIR_DEBUG("ignore %s event for non-passt network device %s in domain %s",
|
||||
eventName, def->info.alias, vm->def->name);
|
||||
VIR_DEBUG("ignore NETDEV_STREAM_DISCONNECTED event for non-passt network device %s in domain %s",
|
||||
def->info.alias, vm->def->name);
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV_STREAM_RECONNECT)) {
|
||||
VIR_WARN("ignore NETDEV_STREAM_DISCONNECTED event for passt network device %s in domain %s - QEMU binary does not support reconnect",
|
||||
def->info.alias, vm->def->name);
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
/* handle the event - restart the passt process with its original
|
||||
* parameters
|
||||
*/
|
||||
VIR_DEBUG("process %s event for network device %s in domain %s",
|
||||
eventName, def->info.alias, vm->def->name);
|
||||
VIR_DEBUG("process NETDEV_STREAM_DISCONNECTED event for network device %s in domain %s",
|
||||
def->info.alias, vm->def->name);
|
||||
|
||||
if (qemuPasstStart(vm, def) < 0)
|
||||
goto endjob;
|
||||
@ -3672,22 +3678,6 @@ processNetdevDisconnectedEvent(virDomainObj *vm,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
processNetdevStreamDisconnectedEvent(virDomainObj *vm,
|
||||
const char *netdevId)
|
||||
{
|
||||
processNetdevDisconnectedEvent(vm, netdevId, "NETDEV_STREAM_DISCONNECTED");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
processNetdevVhostUserDisconnectedEvent(virDomainObj *vm,
|
||||
const char *netdevId)
|
||||
{
|
||||
processNetdevDisconnectedEvent(vm, netdevId, "NETDEV_VHOST_USER_DISCONNECTED");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
processNicRxFilterChangedEvent(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
@ -3855,7 +3845,6 @@ processMonitorEOFEvent(virQEMUDriver *driver,
|
||||
const char *auditReason = "shutdown";
|
||||
unsigned int stopFlags = 0;
|
||||
virObjectEvent *event = NULL;
|
||||
bool migration;
|
||||
|
||||
if (vm->def->id != domid) {
|
||||
VIR_DEBUG("Domain %s was restarted, ignoring EOF",
|
||||
@ -3866,8 +3855,6 @@ processMonitorEOFEvent(virQEMUDriver *driver,
|
||||
if (qemuProcessBeginStopJob(vm, VIR_JOB_DESTROY, true) < 0)
|
||||
return;
|
||||
|
||||
migration = vm->job->asyncJob == VIR_ASYNC_JOB_MIGRATION_IN;
|
||||
|
||||
if (!virDomainObjIsActive(vm)) {
|
||||
VIR_DEBUG("Domain %p '%s' is not active, ignoring EOF",
|
||||
vm, vm->def->name);
|
||||
@ -3882,7 +3869,7 @@ processMonitorEOFEvent(virQEMUDriver *driver,
|
||||
auditReason = "failed";
|
||||
}
|
||||
|
||||
if (migration) {
|
||||
if (vm->job->asyncJob == VIR_ASYNC_JOB_MIGRATION_IN) {
|
||||
stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
|
||||
qemuMigrationDstErrorSave(driver, vm->def->name,
|
||||
qemuMonitorLastError(priv->mon));
|
||||
@ -3895,7 +3882,7 @@ processMonitorEOFEvent(virQEMUDriver *driver,
|
||||
virObjectEventStateQueue(driver->domainEventState, event);
|
||||
|
||||
endjob:
|
||||
qemuDomainRemoveInactive(driver, vm, 0, migration);
|
||||
qemuDomainRemoveInactive(driver, vm, 0, false);
|
||||
qemuProcessEndStopJob(vm);
|
||||
}
|
||||
|
||||
@ -4089,9 +4076,6 @@ static void qemuProcessEventHandler(void *data, void *opaque)
|
||||
case QEMU_PROCESS_EVENT_NETDEV_STREAM_DISCONNECTED:
|
||||
processNetdevStreamDisconnectedEvent(vm, processEvent->data);
|
||||
break;
|
||||
case QEMU_PROCESS_EVENT_NETDEV_VHOST_USER_DISCONNECTED:
|
||||
processNetdevVhostUserDisconnectedEvent(vm, processEvent->data);
|
||||
break;
|
||||
case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
|
||||
processNicRxFilterChangedEvent(driver, vm, processEvent->data);
|
||||
break;
|
||||
@ -4803,7 +4787,8 @@ qemuDomainGetIOThreadsLive(virDomainObj *vm,
|
||||
if (!(map = virProcessGetAffinity(iothreads[i]->thread_id)))
|
||||
goto endjob;
|
||||
|
||||
virBitmapToData(map, &info_ret[i]->cpumap, &info_ret[i]->cpumaplen);
|
||||
if (virBitmapToData(map, &info_ret[i]->cpumap, &info_ret[i]->cpumaplen) < 0)
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
*info = g_steal_pointer(&info_ret);
|
||||
@ -14399,6 +14384,13 @@ qemuDomainBlockCopyCommon(virDomainObj *vm,
|
||||
* as read-write for the duration of the copy job */
|
||||
mirror->readonly = false;
|
||||
|
||||
/* we must initialize XML-provided chain prior to detecting to keep semantics
|
||||
* with VM startup */
|
||||
for (n = mirror; virStorageSourceIsBacking(n); n = n->backingStore) {
|
||||
if (qemuDomainPrepareStorageSourceBlockdev(disk, n, priv, cfg) < 0)
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
/* 'qemuDomainPrepareStorageSourceBlockdev' calls
|
||||
* 'qemuDomainPrepareDiskSourceData' which propagates 'detect_zeroes'
|
||||
* into the topmost virStorage source of the disk chain.
|
||||
@ -14409,13 +14401,6 @@ qemuDomainBlockCopyCommon(virDomainObj *vm,
|
||||
mirror->detect_zeroes = disk->detect_zeroes;
|
||||
mirror->discard_no_unref = disk->discard_no_unref;
|
||||
|
||||
/* we must initialize XML-provided chain prior to detecting to keep semantics
|
||||
* with VM startup */
|
||||
for (n = mirror; virStorageSourceIsBacking(n); n = n->backingStore) {
|
||||
if (qemuDomainPrepareStorageSourceBlockdev(disk, n, priv, cfg) < 0)
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
/* If reusing an external image that includes a backing file but the user
|
||||
* did not enumerate the chain in the XML we need to detect the chain */
|
||||
if (mirror_reuse &&
|
||||
@ -14512,8 +14497,10 @@ qemuDomainBlockCopyCommon(virDomainObj *vm,
|
||||
|
||||
virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0);
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
qemuDomainStorageSourceChainAccessRevoke(driver, vm, mirror);
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
/* Update vm in place to match changes. */
|
||||
need_unlink = false;
|
||||
|
@ -154,7 +154,7 @@ void
|
||||
qemuExtDevicesCleanupHost(virQEMUDriver *driver,
|
||||
virDomainDef *def,
|
||||
virDomainUndefineFlagsValues flags,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@ -165,7 +165,7 @@ qemuExtDevicesCleanupHost(virQEMUDriver *driver,
|
||||
virDomainTPMDef *tpm = def->tpms[i];
|
||||
|
||||
if (tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR)
|
||||
qemuExtTPMCleanupHost(driver, tpm, flags, migration);
|
||||
qemuExtTPMCleanupHost(driver, tpm, flags, outgoingMigration);
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,7 +280,7 @@ qemuExtDevicesStart(virQEMUDriver *driver,
|
||||
void
|
||||
qemuExtDevicesStop(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
{
|
||||
virDomainDef *def = vm->def;
|
||||
size_t i;
|
||||
@ -297,7 +297,7 @@ qemuExtDevicesStop(virQEMUDriver *driver,
|
||||
|
||||
for (i = 0; i < def->ntpms; i++) {
|
||||
if (def->tpms[i]->type == VIR_DOMAIN_TPM_TYPE_EMULATOR)
|
||||
qemuExtTPMStop(driver, vm, migration);
|
||||
qemuExtTPMStop(driver, vm, outgoingMigration);
|
||||
}
|
||||
|
||||
for (i = 0; i < def->nnets; i++) {
|
||||
|
@ -48,7 +48,7 @@ int qemuExtDevicesPrepareHost(virQEMUDriver *driver,
|
||||
void qemuExtDevicesCleanupHost(virQEMUDriver *driver,
|
||||
virDomainDef *def,
|
||||
virDomainUndefineFlagsValues flags,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int qemuExtDevicesStart(virQEMUDriver *driver,
|
||||
@ -59,7 +59,7 @@ int qemuExtDevicesStart(virQEMUDriver *driver,
|
||||
|
||||
void qemuExtDevicesStop(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
|
||||
bool qemuExtDevicesHasDevice(virDomainDef *def);
|
||||
|
@ -740,15 +740,10 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm,
|
||||
if (rc < 0)
|
||||
goto rollback;
|
||||
|
||||
if (!(filterData = qemuBuildThrottleFiltersAttachPrepareBlockdev(disk)))
|
||||
return -1;
|
||||
|
||||
if (filterData->nfilterdata > 0) {
|
||||
if ((filterData = qemuBuildThrottleFiltersAttachPrepareBlockdev(disk))) {
|
||||
if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
|
||||
return -1;
|
||||
|
||||
rc = qemuBlockThrottleFiltersAttach(priv->mon, filterData);
|
||||
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
if (rc < 0)
|
||||
goto rollback;
|
||||
@ -1273,7 +1268,12 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
|
||||
|
||||
if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
|
||||
qemuPasstPrepareVhostUser(vm, net);
|
||||
/* vhostuser needs socket path in this location, and when
|
||||
* backend is passt, the path is derived from other info,
|
||||
* not taken from config.
|
||||
*/
|
||||
g_free(net->data.vhostuser->data.nix.path);
|
||||
net->data.vhostuser->data.nix.path = qemuPasstCreateSocketPath(vm, net);
|
||||
|
||||
if (qemuPasstStart(vm, net) < 0)
|
||||
goto cleanup;
|
||||
|
@ -3609,7 +3609,7 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
|
||||
* and there is no 'goto cleanup;' in the middle of those */
|
||||
VIR_FREE(priv->origname);
|
||||
virDomainObjRemoveTransientDef(vm);
|
||||
qemuDomainRemoveInactive(driver, vm, 0, true);
|
||||
qemuDomainRemoveInactive(driver, vm, 0, false);
|
||||
}
|
||||
virDomainObjEndAPI(&vm);
|
||||
virErrorRestore(&origErr);
|
||||
@ -6977,7 +6977,7 @@ qemuMigrationDstFinishActive(virQEMUDriver *driver,
|
||||
}
|
||||
|
||||
if (!qemuDomainObjIsActive(vm))
|
||||
qemuDomainRemoveInactive(driver, vm, VIR_DOMAIN_UNDEFINE_TPM, true);
|
||||
qemuDomainRemoveInactive(driver, vm, VIR_DOMAIN_UNDEFINE_TPM, false);
|
||||
|
||||
virErrorRestore(&orig_err);
|
||||
return NULL;
|
||||
@ -7113,7 +7113,7 @@ qemuMigrationProcessUnattended(virQEMUDriver *driver,
|
||||
qemuMigrationJobFinish(vm);
|
||||
|
||||
if (!virDomainObjIsActive(vm))
|
||||
qemuDomainRemoveInactive(driver, vm, 0, true);
|
||||
qemuDomainRemoveInactive(driver, vm, 0, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "qemu_alias.h"
|
||||
#include "qemu_monitor.h"
|
||||
#include "qemu_monitor_text.h"
|
||||
#include "qemu_monitor_json.h"
|
||||
#include "qemu_domain.h"
|
||||
#include "qemu_capabilities.h"
|
||||
@ -79,7 +80,7 @@ VIR_LOG_INIT("qemu.qemu_monitor");
|
||||
_("monitor must not be NULL")); \
|
||||
exit; \
|
||||
} \
|
||||
VIR_DEBUG("mon:%p vm:%p monfd:%d", mon, mon->vm, mon->fd); \
|
||||
VIR_DEBUG("mon:%p vm:%p fd:%d", mon, mon->vm, mon->fd); \
|
||||
} while (0)
|
||||
|
||||
/* Check monitor and return NULL on error */
|
||||
@ -1264,17 +1265,6 @@ qemuMonitorEmitNetdevStreamDisconnected(qemuMonitor *mon,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
qemuMonitorEmitNetdevVhostUserDisconnected(qemuMonitor *mon,
|
||||
const char *devAlias)
|
||||
{
|
||||
VIR_DEBUG("mon=%p", mon);
|
||||
|
||||
QEMU_MONITOR_CALLBACK(mon, domainNetdevVhostUserDisconnected,
|
||||
mon->vm, devAlias);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
qemuMonitorEmitSerialChange(qemuMonitor *mon,
|
||||
const char *devAlias,
|
||||
@ -2755,6 +2745,30 @@ qemuMonitorDelObject(qemuMonitor *mon,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorCreateSnapshot(qemuMonitor *mon, const char *name)
|
||||
{
|
||||
VIR_DEBUG("name=%s", name);
|
||||
|
||||
QEMU_CHECK_MONITOR(mon);
|
||||
|
||||
/* there won't ever be a direct QMP replacement for this function */
|
||||
return qemuMonitorTextCreateSnapshot(mon, name);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorDeleteSnapshot(qemuMonitor *mon, const char *name)
|
||||
{
|
||||
VIR_DEBUG("name=%s", name);
|
||||
|
||||
QEMU_CHECK_MONITOR(mon);
|
||||
|
||||
/* there won't ever be a direct QMP replacement for this function */
|
||||
return qemuMonitorTextDeleteSnapshot(mon, name);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorSnapshotSave(qemuMonitor *mon,
|
||||
const char *jobname,
|
||||
@ -3523,6 +3537,23 @@ qemuMonitorNBDServerStart(qemuMonitor *mon,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorNBDServerAdd(qemuMonitor *mon,
|
||||
const char *deviceID,
|
||||
const char *export,
|
||||
bool writable,
|
||||
const char *bitmap)
|
||||
{
|
||||
VIR_DEBUG("deviceID=%s, export=%s, bitmap=%s", deviceID, NULLSTR(export),
|
||||
NULLSTR(bitmap));
|
||||
|
||||
QEMU_CHECK_MONITOR(mon);
|
||||
|
||||
return qemuMonitorJSONNBDServerAdd(mon, deviceID, export, writable,
|
||||
bitmap);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorNBDServerStop(qemuMonitor *mon)
|
||||
{
|
||||
|
@ -255,9 +255,6 @@ typedef void (*qemuMonitorDomainDeviceUnplugErrCallback)(qemuMonitor *mon,
|
||||
typedef void (*qemuMonitorDomainNetdevStreamDisconnectedCallback)(qemuMonitor *mon,
|
||||
virDomainObj *vm,
|
||||
const char *devAlias);
|
||||
typedef void (*qemuMonitorDomainNetdevVhostUserDisconnectedCallback)(qemuMonitor *mon,
|
||||
virDomainObj *vm,
|
||||
const char *devAlias);
|
||||
typedef void (*qemuMonitorDomainNicRxFilterChangedCallback)(qemuMonitor *mon,
|
||||
virDomainObj *vm,
|
||||
const char *devAlias);
|
||||
@ -406,7 +403,6 @@ struct _qemuMonitorCallbacks {
|
||||
qemuMonitorDomainMemoryDeviceSizeChange domainMemoryDeviceSizeChange;
|
||||
qemuMonitorDomainDeviceUnplugErrCallback domainDeviceUnplugError;
|
||||
qemuMonitorDomainNetdevStreamDisconnectedCallback domainNetdevStreamDisconnected;
|
||||
qemuMonitorDomainNetdevVhostUserDisconnectedCallback domainNetdevVhostUserDisconnected;
|
||||
};
|
||||
|
||||
qemuMonitor *qemuMonitorOpen(virDomainObj *vm,
|
||||
@ -494,8 +490,6 @@ void qemuMonitorEmitDeviceUnplugErr(qemuMonitor *mon,
|
||||
const char *devAlias);
|
||||
void qemuMonitorEmitNetdevStreamDisconnected(qemuMonitor *mon,
|
||||
const char *devAlias);
|
||||
void qemuMonitorEmitNetdevVhostUserDisconnected(qemuMonitor *mon,
|
||||
const char *devAlias);
|
||||
void qemuMonitorEmitNicRxFilterChanged(qemuMonitor *mon,
|
||||
const char *devAlias);
|
||||
void qemuMonitorEmitSerialChange(qemuMonitor *mon,
|
||||
@ -982,6 +976,9 @@ int qemuMonitorDelObject(qemuMonitor *mon,
|
||||
const char *objalias,
|
||||
bool report_error);
|
||||
|
||||
int qemuMonitorCreateSnapshot(qemuMonitor *mon, const char *name);
|
||||
int qemuMonitorDeleteSnapshot(qemuMonitor *mon, const char *name);
|
||||
|
||||
int qemuMonitorTransaction(qemuMonitor *mon, virJSONValue **actions)
|
||||
ATTRIBUTE_NONNULL(2);
|
||||
int qemuMonitorBlockdevMirror(qemuMonitor *mon,
|
||||
@ -1224,6 +1221,11 @@ int qemuMonitorNBDServerStart(qemuMonitor *mon,
|
||||
const virStorageNetHostDef *server,
|
||||
const char *tls_alias)
|
||||
ATTRIBUTE_NONNULL(2);
|
||||
int qemuMonitorNBDServerAdd(qemuMonitor *mon,
|
||||
const char *deviceID,
|
||||
const char *export,
|
||||
bool writable,
|
||||
const char *bitmap);
|
||||
int qemuMonitorNBDServerStop(qemuMonitor *mon);
|
||||
|
||||
int qemuMonitorBlockExportAdd(qemuMonitor *mon,
|
||||
|
@ -85,7 +85,6 @@ static void qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon, virJSONValue *d
|
||||
static void qemuMonitorJSONHandleMemoryDeviceSizeChange(qemuMonitor *mon, virJSONValue *data);
|
||||
static void qemuMonitorJSONHandleDeviceUnplugErr(qemuMonitor *mon, virJSONValue *data);
|
||||
static void qemuMonitorJSONHandleNetdevStreamDisconnected(qemuMonitor *mon, virJSONValue *data);
|
||||
static void qemuMonitorJSONHandleNetdevVhostUserDisconnected(qemuMonitor *mon, virJSONValue *data);
|
||||
|
||||
typedef struct {
|
||||
const char *type;
|
||||
@ -109,7 +108,6 @@ static qemuEventHandler eventHandlers[] = {
|
||||
{ "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
|
||||
{ "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
|
||||
{ "NETDEV_STREAM_DISCONNECTED", qemuMonitorJSONHandleNetdevStreamDisconnected, },
|
||||
{ "NETDEV_VHOST_USER_DISCONNECTED", qemuMonitorJSONHandleNetdevVhostUserDisconnected, },
|
||||
{ "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
|
||||
{ "PR_MANAGER_STATUS_CHANGED", qemuMonitorJSONHandlePRManagerStatusChanged, },
|
||||
{ "RDMA_GID_STATUS_CHANGED", qemuMonitorJSONHandleRdmaGidStatusChanged, },
|
||||
@ -1046,20 +1044,6 @@ qemuMonitorJSONHandleNetdevStreamDisconnected(qemuMonitor *mon, virJSONValue *da
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qemuMonitorJSONHandleNetdevVhostUserDisconnected(qemuMonitor *mon, virJSONValue *data)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
if (!(name = virJSONValueObjectGetString(data, "netdev-id"))) {
|
||||
VIR_WARN("missing device in NETDEV_VHOST_USER_DISCONNECTED event");
|
||||
return;
|
||||
}
|
||||
|
||||
qemuMonitorEmitNetdevVhostUserDisconnected(mon, name);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitor *mon, virJSONValue *data)
|
||||
{
|
||||
@ -6339,24 +6323,6 @@ qemuMonitorJSONBuildUnixSocketAddress(const char *path)
|
||||
}
|
||||
|
||||
|
||||
static virJSONValue *
|
||||
qemuMonitorJSONBuildFDSocketAddress(const char *name)
|
||||
{
|
||||
g_autoptr(virJSONValue) addr = NULL;
|
||||
g_autoptr(virJSONValue) data = NULL;
|
||||
|
||||
if (virJSONValueObjectAdd(&data, "s:str", name, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
if (virJSONValueObjectAdd(&addr,
|
||||
"s:type", "fd",
|
||||
"a:data", &data, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
return g_steal_pointer(&addr);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorJSONNBDServerStart(qemuMonitor *mon,
|
||||
const virStorageNetHostDef *server,
|
||||
@ -6375,9 +6341,6 @@ qemuMonitorJSONNBDServerStart(qemuMonitor *mon,
|
||||
case VIR_STORAGE_NET_HOST_TRANS_UNIX:
|
||||
addr = qemuMonitorJSONBuildUnixSocketAddress(server->socket);
|
||||
break;
|
||||
case VIR_STORAGE_NET_HOST_TRANS_FD:
|
||||
addr = qemuMonitorJSONBuildFDSocketAddress(server->qemu_fdname);
|
||||
break;
|
||||
case VIR_STORAGE_NET_HOST_TRANS_RDMA:
|
||||
case VIR_STORAGE_NET_HOST_TRANS_LAST:
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
@ -6402,6 +6365,34 @@ qemuMonitorJSONNBDServerStart(qemuMonitor *mon,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
qemuMonitorJSONNBDServerAdd(qemuMonitor *mon,
|
||||
const char *deviceID,
|
||||
const char *export,
|
||||
bool writable,
|
||||
const char *bitmap)
|
||||
{
|
||||
g_autoptr(virJSONValue) cmd = NULL;
|
||||
g_autoptr(virJSONValue) reply = NULL;
|
||||
|
||||
/* Note: bitmap must be NULL if QEMU_CAPS_NBD_BITMAP is lacking */
|
||||
if (!(cmd = qemuMonitorJSONMakeCommand("nbd-server-add",
|
||||
"s:device", deviceID,
|
||||
"S:name", export,
|
||||
"b:writable", writable,
|
||||
"S:bitmap", bitmap,
|
||||
NULL)))
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
qemuMonitorJSONNBDServerStop(qemuMonitor *mon)
|
||||
{
|
||||
|
@ -541,6 +541,12 @@ qemuMonitorJSONNBDServerStart(qemuMonitor *mon,
|
||||
const virStorageNetHostDef *server,
|
||||
const char *tls_alias);
|
||||
int
|
||||
qemuMonitorJSONNBDServerAdd(qemuMonitor *mon,
|
||||
const char *deviceID,
|
||||
const char *export,
|
||||
bool writable,
|
||||
const char *bitmap);
|
||||
int
|
||||
qemuMonitorJSONNBDServerStop(qemuMonitor *mon);
|
||||
|
||||
int
|
||||
|
88
src/qemu/qemu_monitor_text.c
Normal file
88
src/qemu/qemu_monitor_text.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* qemu_monitor_text.c: interaction with QEMU monitor console
|
||||
*
|
||||
* Copyright (C) 2006-2014 Red Hat, Inc.
|
||||
* Copyright (C) 2006 Daniel P. Berrange
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#include "qemu_monitor_text.h"
|
||||
#include "qemu_monitor_json.h"
|
||||
#include "virlog.h"
|
||||
#include "virerror.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_QEMU
|
||||
|
||||
VIR_LOG_INIT("qemu.qemu_monitor_text");
|
||||
|
||||
int
|
||||
qemuMonitorTextCreateSnapshot(qemuMonitor *mon,
|
||||
const char *name)
|
||||
{
|
||||
g_autofree char *cmd = NULL;
|
||||
g_autofree char *reply = NULL;
|
||||
|
||||
cmd = g_strdup_printf("savevm \"%s\"", name);
|
||||
|
||||
if (qemuMonitorJSONHumanCommand(mon, cmd, -1, &reply))
|
||||
return -1;
|
||||
|
||||
if (strstr(reply, "Error while creating snapshot") ||
|
||||
strstr(reply, "Could not open VM state file") ||
|
||||
strstr(reply, "State blocked by non-migratable device") ||
|
||||
strstr(reply, "Error: ") ||
|
||||
(strstr(reply, "Error") && strstr(reply, "while writing VM"))) {
|
||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||
_("Failed to take snapshot: %1$s"), reply);
|
||||
return -1;
|
||||
} else if (strstr(reply, "No block device can accept snapshots")) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("this domain does not have a device to take snapshots"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qemuMonitorTextDeleteSnapshot(qemuMonitor *mon, const char *name)
|
||||
{
|
||||
g_autofree char *cmd = NULL;
|
||||
g_autofree char *reply = NULL;
|
||||
|
||||
cmd = g_strdup_printf("delvm \"%s\"", name);
|
||||
if (qemuMonitorJSONHumanCommand(mon, cmd, -1, &reply))
|
||||
return -1;
|
||||
|
||||
if (strstr(reply, "No block device supports snapshots")) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("this domain does not have a device to delete snapshots"));
|
||||
return -1;
|
||||
} else if (strstr(reply, "Snapshots not supported on device")) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s", reply);
|
||||
return -1;
|
||||
} else if (strstr(reply, "Error: ") ||
|
||||
(strstr(reply, "Error") &&
|
||||
strstr(reply, "while deleting snapshot"))) {
|
||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||
_("Failed to delete snapshot: %1$s"), reply);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
29
src/qemu/qemu_monitor_text.h
Normal file
29
src/qemu/qemu_monitor_text.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* qemu_monitor_text.h: interaction with QEMU monitor console
|
||||
*
|
||||
* Copyright (C) 2006-2009, 2011-2012 Red Hat, Inc.
|
||||
* Copyright (C) 2006 Daniel P. Berrange
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include "qemu_monitor.h"
|
||||
|
||||
int qemuMonitorTextCreateSnapshot(qemuMonitor *mon, const char *name);
|
||||
int qemuMonitorTextDeleteSnapshot(qemuMonitor *mon, const char *name);
|
@ -36,7 +36,7 @@ VIR_LOG_INIT("qemu.passt");
|
||||
|
||||
|
||||
#define PASST "passt"
|
||||
#define QEMU_PASST_RECONNECT_TIMEOUT 5
|
||||
|
||||
|
||||
static char *
|
||||
qemuPasstCreatePidFilename(virDomainObj *vm,
|
||||
@ -106,15 +106,11 @@ qemuPasstAddNetProps(virDomainObj *vm,
|
||||
|
||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV_STREAM_RECONNECT)) {
|
||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS)) {
|
||||
if (virJSONValueObjectAdd(netprops, "u:reconnect-ms",
|
||||
QEMU_PASST_RECONNECT_TIMEOUT * 1000, NULL) < 0) {
|
||||
if (virJSONValueObjectAdd(netprops, "u:reconnect-ms", 5000, NULL) < 0)
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (virJSONValueObjectAdd(netprops, "u:reconnect",
|
||||
QEMU_PASST_RECONNECT_TIMEOUT, NULL) < 0) {
|
||||
if (virJSONValueObjectAdd(netprops, "u:reconnect", 5, NULL) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,31 +165,6 @@ qemuPasstSetupCgroup(virDomainObj *vm,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
qemuPasstPrepareVhostUser(virDomainObj *vm,
|
||||
virDomainNetDef *net)
|
||||
{
|
||||
/* There are some options on the QEMU commandline for a vhost-user
|
||||
* chr device that are normally configurable, but when it is passt
|
||||
* speaking to the vhost-user device those things are
|
||||
* derived/fixed. This function, which is called prior to
|
||||
* generating the QEMU commandline, sets thos derived/fixed things
|
||||
* in the chr device object.
|
||||
*/
|
||||
|
||||
/* The socket path is not user-configurable for passt - it is
|
||||
* derived from other info
|
||||
*/
|
||||
g_free(net->data.vhostuser->data.nix.path);
|
||||
net->data.vhostuser->data.nix.path = qemuPasstCreateSocketPath(vm, net);
|
||||
|
||||
/* reconnect is always enabled, with timeout always at 5 seconds, when
|
||||
* using passt
|
||||
*/
|
||||
net->data.vhostuser->data.nix.reconnect.enabled = VIR_TRISTATE_BOOL_YES;
|
||||
net->data.vhostuser->data.nix.reconnect.timeout = QEMU_PASST_RECONNECT_TIMEOUT;
|
||||
}
|
||||
|
||||
int
|
||||
qemuPasstStart(virDomainObj *vm,
|
||||
virDomainNetDef *net)
|
||||
|
@ -37,8 +37,5 @@ int qemuPasstSetupCgroup(virDomainObj *vm,
|
||||
virDomainNetDef *net,
|
||||
virCgroup *cgroup);
|
||||
|
||||
void qemuPasstPrepareVhostUser(virDomainObj *vm,
|
||||
virDomainNetDef *net);
|
||||
|
||||
char *qemuPasstCreateSocketPath(virDomainObj *vm,
|
||||
virDomainNetDef *net);
|
||||
|
@ -1402,23 +1402,6 @@ qemuProcessHandleNetdevStreamDisconnected(qemuMonitor *mon G_GNUC_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qemuProcessHandleNetdevVhostUserDisconnected(qemuMonitor *mon G_GNUC_UNUSED,
|
||||
virDomainObj *vm,
|
||||
const char *devAlias)
|
||||
{
|
||||
virObjectLock(vm);
|
||||
|
||||
VIR_DEBUG("Device %s Netdev vhost-user Disconnected in domain %p %s",
|
||||
devAlias, vm, vm->def->name);
|
||||
|
||||
qemuProcessEventSubmit(vm, QEMU_PROCESS_EVENT_NETDEV_VHOST_USER_DISCONNECTED,
|
||||
0, 0, g_strdup(devAlias));
|
||||
|
||||
virObjectUnlock(vm);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qemuProcessHandleNicRxFilterChanged(qemuMonitor *mon G_GNUC_UNUSED,
|
||||
virDomainObj *vm,
|
||||
@ -1865,7 +1848,6 @@ static qemuMonitorCallbacks monitorCallbacks = {
|
||||
.domainMemoryDeviceSizeChange = qemuProcessHandleMemoryDeviceSizeChange,
|
||||
.domainDeviceUnplugError = qemuProcessHandleDeviceUnplugErr,
|
||||
.domainNetdevStreamDisconnected = qemuProcessHandleNetdevStreamDisconnected,
|
||||
.domainNetdevVhostUserDisconnected = qemuProcessHandleNetdevVhostUserDisconnected,
|
||||
};
|
||||
|
||||
static void
|
||||
@ -6022,8 +6004,13 @@ qemuProcessPrepareDomainNetwork(virDomainObj *vm)
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
/* some extra setup of internal data for passt vhostuser mode */
|
||||
qemuPasstPrepareVhostUser(vm, net);
|
||||
/* when using the passt backend, the path of the
|
||||
* unix socket is always derived from other info
|
||||
* *not* manually given in the config, but all the
|
||||
* vhostuser code looks for it there.
|
||||
*/
|
||||
g_free(net->data.vhostuser->data.nix.path);
|
||||
net->data.vhostuser->data.nix.path = qemuPasstCreateSocketPath(vm, net);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -8252,7 +8239,8 @@ qemuProcessLaunch(virConnectPtr conn,
|
||||
|
||||
qemuDomainVcpuPersistOrder(vm->def);
|
||||
|
||||
if (snapshot) {
|
||||
if (snapshot &&
|
||||
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SNAPSHOT_INTERNAL_QMP)) {
|
||||
VIR_DEBUG("reverting internal snapshot via QMP");
|
||||
if (qemuSnapshotInternalRevert(vm, snapshot, asyncJob) < 0)
|
||||
goto cleanup;
|
||||
@ -8926,6 +8914,7 @@ void qemuProcessStop(virQEMUDriver *driver,
|
||||
size_t i;
|
||||
g_autofree char *timestamp = NULL;
|
||||
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
||||
bool outgoingMigration;
|
||||
|
||||
VIR_DEBUG("Shutting down vm=%p name=%s id=%d pid=%lld, "
|
||||
"reason=%s, asyncJob=%s, flags=0x%x",
|
||||
@ -9001,7 +8990,10 @@ void qemuProcessStop(virQEMUDriver *driver,
|
||||
|
||||
qemuDomainCleanupRun(driver, vm);
|
||||
|
||||
qemuExtDevicesStop(driver, vm, !!(flags & VIR_QEMU_PROCESS_STOP_MIGRATED));
|
||||
outgoingMigration = (flags & VIR_QEMU_PROCESS_STOP_MIGRATED) &&
|
||||
(asyncJob == VIR_ASYNC_JOB_MIGRATION_OUT);
|
||||
|
||||
qemuExtDevicesStop(driver, vm, outgoingMigration);
|
||||
|
||||
qemuDBusStop(driver, vm);
|
||||
|
||||
@ -9267,7 +9259,7 @@ qemuProcessAutoDestroy(virDomainObj *dom,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
||||
|
||||
qemuDomainRemoveInactive(driver, dom, 0, !!(stopFlags & VIR_QEMU_PROCESS_STOP_MIGRATED));
|
||||
qemuDomainRemoveInactive(driver, dom, 0, false);
|
||||
|
||||
qemuProcessEndStopJob(dom);
|
||||
|
||||
|
@ -413,25 +413,12 @@ qemuRdpSetCredentials(virDomainObj *vm,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* qemuRdpAvailable:
|
||||
* @helper: name (or path to) 'qemu-rdp' binary
|
||||
*
|
||||
* Returns whether 'qemu-rdp' is available.
|
||||
*
|
||||
* Important:
|
||||
* This function is called from 'virQEMUDriverGetDomainCapabilities'. It must
|
||||
* not report any errors and must not add any additional checks.
|
||||
*
|
||||
* This function is mocked from 'tests/testutilsqemu.c'
|
||||
*
|
||||
*/
|
||||
bool
|
||||
qemuRdpAvailable(const char *helper)
|
||||
{
|
||||
g_autofree char *helperPath = NULL;
|
||||
g_autoptr(qemuRdp) rdp = NULL;
|
||||
|
||||
/* This function was added corresponding to the first release of 'qemu-rdp'
|
||||
* thus checking existence of the helper binary is sufficient. */
|
||||
return !!(helperPath = virFindFileInPath(helper));
|
||||
rdp = qemuRdpNewForHelper(helper);
|
||||
|
||||
return rdp && qemuRdpHasFeature(rdp, QEMU_RDP_FEATURE_DBUS_ADDRESS);
|
||||
}
|
||||
|
@ -554,12 +554,12 @@ qemuSnapshotCreateActiveInternal(virQEMUDriver *driver,
|
||||
virDomainMomentObj *snap,
|
||||
unsigned int flags)
|
||||
{
|
||||
qemuDomainObjPrivate *priv = vm->privateData;
|
||||
virObjectEvent *event = NULL;
|
||||
bool resume = false;
|
||||
virDomainSnapshotDef *snapdef = virDomainSnapshotObjGetDef(snap);
|
||||
int ret = -1;
|
||||
int rv = 0;
|
||||
g_autoptr(qemuBlockJobData) job = NULL;
|
||||
|
||||
if (!qemuMigrationSrcIsAllowed(vm, false, VIR_ASYNC_JOB_SNAPSHOT, 0))
|
||||
goto cleanup;
|
||||
@ -581,11 +581,27 @@ qemuSnapshotCreateActiveInternal(virQEMUDriver *driver,
|
||||
}
|
||||
}
|
||||
|
||||
if (!(job = qemuSnapshotCreateActiveInternalStart(vm, snapdef)))
|
||||
goto cleanup;
|
||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SNAPSHOT_INTERNAL_QMP)) {
|
||||
g_autoptr(qemuBlockJobData) job = NULL;
|
||||
|
||||
while ((rv = qemuSnapshotCreateActiveInternalDone(vm, job)) != 1) {
|
||||
if (rv < 0 || qemuDomainObjWait(vm) < 0)
|
||||
if (!(job = qemuSnapshotCreateActiveInternalStart(vm, snapdef)))
|
||||
goto cleanup;
|
||||
|
||||
while ((rv = qemuSnapshotCreateActiveInternalDone(vm, job)) != 1) {
|
||||
if (rv < 0 || qemuDomainObjWait(vm) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_SNAPSHOT) < 0) {
|
||||
resume = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
if (ret < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -601,8 +617,6 @@ qemuSnapshotCreateActiveInternal(virQEMUDriver *driver,
|
||||
resume = false;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (resume && virDomainObjIsActive(vm) &&
|
||||
qemuProcessStartCPUs(driver, vm,
|
||||
@ -929,6 +943,7 @@ qemuSnapshotPrepare(virDomainObj *vm,
|
||||
bool *has_manual,
|
||||
unsigned int *flags)
|
||||
{
|
||||
qemuDomainObjPrivate *priv = vm->privateData;
|
||||
size_t i;
|
||||
bool active = virDomainObjIsActive(vm);
|
||||
bool reuse = (*flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
|
||||
@ -1049,6 +1064,13 @@ qemuSnapshotPrepare(virDomainObj *vm,
|
||||
* varstore is in qcow2 format.
|
||||
*/
|
||||
if (active && found_internal) {
|
||||
if (virDomainDefHasOldStyleUEFI(vm->def) &&
|
||||
!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SNAPSHOT_INTERNAL_QMP)) {
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||
_("internal snapshots of a VM with pflash based firmware are not supported with this qemu"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vm->def->os.loader &&
|
||||
vm->def->os.loader->nvram &&
|
||||
vm->def->os.loader->nvram->format != VIR_STORAGE_FILE_QCOW2) {
|
||||
@ -4097,13 +4119,22 @@ qemuSnapshotDiscardImpl(virDomainObj *vm,
|
||||
return -1;
|
||||
} else {
|
||||
virDomainSnapshotDef *snapdef = virDomainSnapshotObjGetDef(snap);
|
||||
qemuDomainObjPrivate *priv = vm->privateData;
|
||||
|
||||
/* Similarly as internal snapshot creation we would use a regular job
|
||||
* here so set a mask to forbid any other job. */
|
||||
qemuDomainObjSetAsyncJobMask(vm, VIR_JOB_NONE);
|
||||
|
||||
if (qemuSnapshotDiscardActiveInternal(vm, snapdef) < 0)
|
||||
return -1;
|
||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SNAPSHOT_INTERNAL_QMP)) {
|
||||
if (qemuSnapshotDiscardActiveInternal(vm, snapdef) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_SNAPSHOT) < 0)
|
||||
return -1;
|
||||
/* we continue on even in the face of error */
|
||||
qemuMonitorDeleteSnapshot(qemuDomainGetMonitor(vm), snap->def->name);
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
}
|
||||
|
||||
qemuDomainObjSetAsyncJobMask(vm, VIR_JOB_DEFAULT_MASK);
|
||||
}
|
||||
|
@ -929,8 +929,7 @@ qemuTPMEmulatorInitPaths(virDomainTPMDef *tpm,
|
||||
* @driver: QEMU driver
|
||||
* @tpm: TPM definition
|
||||
* @flags: flags indicating whether to keep or remove TPM persistent state
|
||||
* @migration: whether cleanup is due to a successful outgoing or failed
|
||||
* incoming migration
|
||||
* @outgoingMigration: whether cleanup is due to an outgoing migration
|
||||
*
|
||||
* Clean up persistent storage for the swtpm.
|
||||
*/
|
||||
@ -938,12 +937,14 @@ static void
|
||||
qemuTPMEmulatorCleanupHost(virQEMUDriver *driver,
|
||||
virDomainTPMDef *tpm,
|
||||
virDomainUndefineFlagsValues flags,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
{
|
||||
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
||||
|
||||
/* Never remove the state in case of migration with shared storage. */
|
||||
if (migration &&
|
||||
/* Never remove the state in case of outgoing migration with shared
|
||||
* storage.
|
||||
*/
|
||||
if (outgoingMigration &&
|
||||
virFileIsSharedFS(tpm->data.emulator.source_path, cfg->sharedFilesystems) == 1)
|
||||
return;
|
||||
|
||||
@ -1314,9 +1315,9 @@ void
|
||||
qemuExtTPMCleanupHost(virQEMUDriver *driver,
|
||||
virDomainTPMDef *tpm,
|
||||
virDomainUndefineFlagsValues flags,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
{
|
||||
qemuTPMEmulatorCleanupHost(driver, tpm, flags, migration);
|
||||
qemuTPMEmulatorCleanupHost(driver, tpm, flags, outgoingMigration);
|
||||
}
|
||||
|
||||
|
||||
@ -1340,7 +1341,7 @@ qemuExtTPMStart(virQEMUDriver *driver,
|
||||
void
|
||||
qemuExtTPMStop(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
{
|
||||
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
||||
g_autofree char *shortName = virDomainDefGetShortName(vm->def);
|
||||
@ -1350,7 +1351,7 @@ qemuExtTPMStop(virQEMUDriver *driver,
|
||||
return;
|
||||
|
||||
qemuTPMEmulatorStop(cfg->swtpmStateDir, shortName);
|
||||
if (migration && qemuTPMHasSharedStorage(driver, vm->def))
|
||||
if (outgoingMigration && qemuTPMHasSharedStorage(driver, vm->def))
|
||||
restoreTPMStateLabel = false;
|
||||
|
||||
if (qemuSecurityRestoreTPMLabels(driver, vm, restoreTPMStateLabel, false) < 0)
|
||||
|
@ -38,7 +38,7 @@ int qemuExtTPMPrepareHost(virQEMUDriver *driver,
|
||||
void qemuExtTPMCleanupHost(virQEMUDriver *driver,
|
||||
virDomainTPMDef *tpm,
|
||||
virDomainUndefineFlagsValues flags,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int qemuExtTPMStart(virQEMUDriver *driver,
|
||||
@ -52,7 +52,7 @@ int qemuExtTPMStart(virQEMUDriver *driver,
|
||||
|
||||
void qemuExtTPMStop(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
bool migration)
|
||||
bool outgoingMigration)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int qemuExtTPMSetupCgroup(virQEMUDriver *driver,
|
||||
|
@ -742,42 +742,6 @@ remoteConnectFormatURI(virURI *uri,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
remoteCallOpen(virConnectPtr conn,
|
||||
struct private_data *priv,
|
||||
const char *name,
|
||||
unsigned int flags)
|
||||
{
|
||||
remote_connect_open_args args = { (char**) &name, flags };
|
||||
|
||||
VIR_DEBUG("Trying to open URI '%s'", name);
|
||||
if (call(conn, priv, 0, REMOTE_PROC_CONNECT_OPEN,
|
||||
(xdrproc_t) xdr_remote_connect_open_args, (char *) &args,
|
||||
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
||||
return -1;
|
||||
|
||||
/* Now try and find out what URI the daemon used */
|
||||
if (conn->uri == NULL) {
|
||||
remote_connect_get_uri_ret uriret = { 0 };
|
||||
|
||||
VIR_DEBUG("Trying to query remote URI");
|
||||
if (call(conn, priv, 0,
|
||||
REMOTE_PROC_CONNECT_GET_URI,
|
||||
(xdrproc_t) xdr_void, (char *) NULL,
|
||||
(xdrproc_t) xdr_remote_connect_get_uri_ret, (char *) &uriret) < 0)
|
||||
return -1;
|
||||
|
||||
VIR_DEBUG("Auto-probed URI is %s", uriret.uri);
|
||||
conn->uri = virURIParse(uriret.uri);
|
||||
VIR_FREE(uriret.uri);
|
||||
if (!conn->uri)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* helper macro to ease extraction of arguments from the URI */
|
||||
#define EXTRACT_URI_ARG_STR(ARG_NAME, ARG_VAR) \
|
||||
if (STRCASEEQ(var->name, ARG_NAME)) { \
|
||||
@ -794,74 +758,13 @@ remoteCallOpen(virConnectPtr conn,
|
||||
virReportError(VIR_ERR_INVALID_ARG, \
|
||||
_("Failed to parse value of URI component %1$s"), \
|
||||
var->name); \
|
||||
return -1; \
|
||||
goto error; \
|
||||
} \
|
||||
ARG_VAR = tmp == 0; \
|
||||
var->ignore = 1; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
static int
|
||||
doRemoteOpenExtractURIArgs(virConnectPtr conn,
|
||||
char **name,
|
||||
char **command,
|
||||
char **sockname,
|
||||
char **authtype,
|
||||
char **sshauth,
|
||||
char **netcat,
|
||||
char **keyfile,
|
||||
char **pkipath,
|
||||
char **knownHosts,
|
||||
char **knownHostsVerify,
|
||||
char **tls_priority,
|
||||
char **mode_str,
|
||||
char **proxy_str,
|
||||
#ifndef WIN32
|
||||
bool *tty,
|
||||
#endif
|
||||
bool *sanity,
|
||||
bool *verify)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < conn->uri->paramsCount; i++) {
|
||||
virURIParam *var = &conn->uri->params[i];
|
||||
|
||||
EXTRACT_URI_ARG_STR("name", *name);
|
||||
EXTRACT_URI_ARG_STR("command", *command);
|
||||
EXTRACT_URI_ARG_STR("socket", *sockname);
|
||||
EXTRACT_URI_ARG_STR("auth", *authtype);
|
||||
EXTRACT_URI_ARG_STR("sshauth", *sshauth);
|
||||
EXTRACT_URI_ARG_STR("netcat", *netcat);
|
||||
EXTRACT_URI_ARG_STR("keyfile", *keyfile);
|
||||
EXTRACT_URI_ARG_STR("pkipath", *pkipath);
|
||||
EXTRACT_URI_ARG_STR("known_hosts", *knownHosts);
|
||||
EXTRACT_URI_ARG_STR("known_hosts_verify", *knownHostsVerify);
|
||||
EXTRACT_URI_ARG_STR("tls_priority", *tls_priority);
|
||||
EXTRACT_URI_ARG_STR("mode", *mode_str);
|
||||
EXTRACT_URI_ARG_STR("proxy", *proxy_str);
|
||||
EXTRACT_URI_ARG_BOOL("no_sanity", *sanity);
|
||||
EXTRACT_URI_ARG_BOOL("no_verify", *verify);
|
||||
#ifndef WIN32
|
||||
EXTRACT_URI_ARG_BOOL("no_tty", *tty);
|
||||
#endif
|
||||
|
||||
if (STRCASEEQ(var->name, "authfile")) {
|
||||
/* Strip this param, used by virauth.c */
|
||||
var->ignore = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
VIR_DEBUG("passing through variable '%s' ('%s') to remote end",
|
||||
var->name, var->value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef EXTRACT_URI_ARG_STR
|
||||
#undef EXTRACT_URI_ARG_BOOL
|
||||
|
||||
|
||||
/*
|
||||
* URIs that this driver needs to handle:
|
||||
@ -915,6 +818,7 @@ doRemoteOpen(virConnectPtr conn,
|
||||
bool tty = true;
|
||||
#endif
|
||||
int mode;
|
||||
size_t i;
|
||||
int proxy;
|
||||
|
||||
/* We handle *ALL* URIs here. The caller has rejected any
|
||||
@ -940,28 +844,35 @@ doRemoteOpen(virConnectPtr conn,
|
||||
* although that won't be the case for now).
|
||||
*/
|
||||
if (conn->uri) {
|
||||
/* This really needs to be a separate function to keep
|
||||
* the stack size at sane levels. */
|
||||
if (doRemoteOpenExtractURIArgs(conn,
|
||||
&name,
|
||||
&command,
|
||||
&sockname,
|
||||
&authtype,
|
||||
&sshauth,
|
||||
&netcat,
|
||||
&keyfile,
|
||||
&pkipath,
|
||||
&knownHosts,
|
||||
&knownHostsVerify,
|
||||
&tls_priority,
|
||||
&mode_str,
|
||||
&proxy_str,
|
||||
for (i = 0; i < conn->uri->paramsCount; i++) {
|
||||
virURIParam *var = &conn->uri->params[i];
|
||||
EXTRACT_URI_ARG_STR("name", name);
|
||||
EXTRACT_URI_ARG_STR("command", command);
|
||||
EXTRACT_URI_ARG_STR("socket", sockname);
|
||||
EXTRACT_URI_ARG_STR("auth", authtype);
|
||||
EXTRACT_URI_ARG_STR("sshauth", sshauth);
|
||||
EXTRACT_URI_ARG_STR("netcat", netcat);
|
||||
EXTRACT_URI_ARG_STR("keyfile", keyfile);
|
||||
EXTRACT_URI_ARG_STR("pkipath", pkipath);
|
||||
EXTRACT_URI_ARG_STR("known_hosts", knownHosts);
|
||||
EXTRACT_URI_ARG_STR("known_hosts_verify", knownHostsVerify);
|
||||
EXTRACT_URI_ARG_STR("tls_priority", tls_priority);
|
||||
EXTRACT_URI_ARG_STR("mode", mode_str);
|
||||
EXTRACT_URI_ARG_STR("proxy", proxy_str);
|
||||
EXTRACT_URI_ARG_BOOL("no_sanity", sanity);
|
||||
EXTRACT_URI_ARG_BOOL("no_verify", verify);
|
||||
#ifndef WIN32
|
||||
&tty,
|
||||
EXTRACT_URI_ARG_BOOL("no_tty", tty);
|
||||
#endif
|
||||
&sanity,
|
||||
&verify) < 0) {
|
||||
goto error;
|
||||
|
||||
if (STRCASEEQ(var->name, "authfile")) {
|
||||
/* Strip this param, used by virauth.c */
|
||||
var->ignore = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
VIR_DEBUG("passing through variable '%s' ('%s') to remote end",
|
||||
var->name, var->value);
|
||||
}
|
||||
|
||||
/* Construct the original name. */
|
||||
@ -1063,7 +974,7 @@ doRemoteOpen(virConnectPtr conn,
|
||||
|
||||
VIR_DEBUG("Connecting with transport %d", transport);
|
||||
|
||||
switch (transport) {
|
||||
switch ((remoteDriverTransport)transport) {
|
||||
case REMOTE_DRIVER_TRANSPORT_UNIX:
|
||||
case REMOTE_DRIVER_TRANSPORT_SSH:
|
||||
case REMOTE_DRIVER_TRANSPORT_LIBSSH:
|
||||
@ -1088,7 +999,7 @@ doRemoteOpen(virConnectPtr conn,
|
||||
VIR_DEBUG("Chosen UNIX socket %s", NULLSTR(sockname));
|
||||
|
||||
/* Connect to the remote service. */
|
||||
switch (transport) {
|
||||
switch ((remoteDriverTransport)transport) {
|
||||
case REMOTE_DRIVER_TRANSPORT_TLS:
|
||||
if (conf && !tls_priority &&
|
||||
virConfGetValueString(conf, "tls_priority", &tls_priority) < 0)
|
||||
@ -1277,8 +1188,33 @@ doRemoteOpen(virConnectPtr conn,
|
||||
}
|
||||
|
||||
/* Finally we can call the remote side's open function. */
|
||||
if (remoteCallOpen(conn, priv, name, flags) < 0)
|
||||
goto error;
|
||||
{
|
||||
remote_connect_open_args args = { &name, flags };
|
||||
|
||||
VIR_DEBUG("Trying to open URI '%s'", name);
|
||||
if (call(conn, priv, 0, REMOTE_PROC_CONNECT_OPEN,
|
||||
(xdrproc_t) xdr_remote_connect_open_args, (char *) &args,
|
||||
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Now try and find out what URI the daemon used */
|
||||
if (conn->uri == NULL) {
|
||||
remote_connect_get_uri_ret uriret = { 0 };
|
||||
|
||||
VIR_DEBUG("Trying to query remote URI");
|
||||
if (call(conn, priv, 0,
|
||||
REMOTE_PROC_CONNECT_GET_URI,
|
||||
(xdrproc_t) xdr_void, (char *) NULL,
|
||||
(xdrproc_t) xdr_remote_connect_get_uri_ret, (char *) &uriret) < 0)
|
||||
goto error;
|
||||
|
||||
VIR_DEBUG("Auto-probed URI is %s", uriret.uri);
|
||||
conn->uri = virURIParse(uriret.uri);
|
||||
VIR_FREE(uriret.uri);
|
||||
if (!conn->uri)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Set up events */
|
||||
if (!(priv->eventState = virObjectEventStateNew()))
|
||||
@ -1312,6 +1248,8 @@ doRemoteOpen(virConnectPtr conn,
|
||||
VIR_FREE(priv->hostname);
|
||||
return VIR_DRV_OPEN_ERROR;
|
||||
}
|
||||
#undef EXTRACT_URI_ARG_STR
|
||||
#undef EXTRACT_URI_ARG_BOOL
|
||||
|
||||
static struct private_data *
|
||||
remoteAllocPrivateData(void)
|
||||
|
@ -117,4 +117,6 @@
|
||||
deny /sys/fs/cgroup?*{,/**} wklx,
|
||||
deny /sys/fs?*{,/**} wklx,
|
||||
|
||||
@BEGIN_APPARMOR_3@
|
||||
include if exists <abstractions/libvirt-lxc.d>
|
||||
@END_APPARMOR_3@
|
@ -190,6 +190,7 @@
|
||||
/usr/{lib,lib64}/libswtpm_libtpms.so mr,
|
||||
/usr/lib/@{multiarch}/libswtpm_libtpms.so mr,
|
||||
|
||||
@BEGIN_APPARMOR_3@
|
||||
# support for passt network back-end
|
||||
/usr/bin/passt Cx -> passt,
|
||||
|
||||
@ -205,6 +206,7 @@
|
||||
|
||||
include if exists <abstractions/passt>
|
||||
}
|
||||
@END_APPARMOR_3@
|
||||
|
||||
# for save and resume
|
||||
/{usr/,}bin/dash rmix,
|
||||
@ -279,4 +281,6 @@
|
||||
owner /var/lib/libvirt/qemu/nvram/*_VARS.fd rwk,
|
||||
owner /var/lib/libvirt/qemu/nvram/*_VARS.ms.fd rwk,
|
||||
|
||||
@BEGIN_APPARMOR_3@
|
||||
include if exists <abstractions/libvirt-qemu.d>
|
||||
@END_APPARMOR_3@
|
@ -5,6 +5,11 @@ apparmor_gen_profiles = [
|
||||
'usr.sbin.virtxend',
|
||||
]
|
||||
|
||||
apparmor_gen_abstractions = [
|
||||
'libvirt-qemu',
|
||||
'libvirt-lxc',
|
||||
]
|
||||
|
||||
apparmor_gen_profiles_conf = configuration_data({
|
||||
'sysconfdir': sysconfdir,
|
||||
'sbindir': sbindir,
|
||||
@ -14,9 +19,41 @@ apparmor_gen_profiles_conf = configuration_data({
|
||||
|
||||
apparmor_dir = sysconfdir / 'apparmor.d'
|
||||
|
||||
# Our profiles use some features that only work well on AppArmor 3.x,
|
||||
# specifically the 'include if exists' directive. In order to keep
|
||||
# supporting AppArmor 2.x, the bits that are version-specific are
|
||||
# enclosed in special markers and we decide which ones to include
|
||||
# based on the AppArmor version detected on the host.
|
||||
#
|
||||
# TODO: drop the additional complexity once we no longer target
|
||||
# distros that ship AppArmor 2.x (Debian 11, Ubuntu 20.04)
|
||||
if conf.has('WITH_APPARMOR_3')
|
||||
apparmor_gen_cmd = [
|
||||
'sed',
|
||||
'-e', '/[@]BEGIN_APPARMOR_3[@]/d',
|
||||
'-e', '/[@]END_APPARMOR_3[@]/d',
|
||||
'-e', '/[@]BEGIN_APPARMOR_2[@]/,/[@]END_APPARMOR_2[@]/d',
|
||||
'@INPUT@'
|
||||
]
|
||||
else
|
||||
apparmor_gen_cmd = [
|
||||
'sed',
|
||||
'-e', '/[@]BEGIN_APPARMOR_3[@]/,/[@]END_APPARMOR_3[@]/d',
|
||||
'-e', '/[@]BEGIN_APPARMOR_2[@]/d',
|
||||
'-e', '/[@]END_APPARMOR_2[@]/d',
|
||||
'@INPUT@'
|
||||
]
|
||||
endif
|
||||
|
||||
foreach name : apparmor_gen_profiles
|
||||
configure_file(
|
||||
tmp = configure_file(
|
||||
input: '@0@.in'.format(name),
|
||||
output: '@0@.tmp'.format(name),
|
||||
command: apparmor_gen_cmd,
|
||||
capture: true,
|
||||
)
|
||||
configure_file(
|
||||
input: tmp,
|
||||
output: name,
|
||||
configuration: apparmor_gen_profiles_conf,
|
||||
install: true,
|
||||
@ -24,12 +61,29 @@ foreach name : apparmor_gen_profiles
|
||||
)
|
||||
endforeach
|
||||
|
||||
install_data(
|
||||
[ 'libvirt-qemu', 'libvirt-lxc' ],
|
||||
install_dir: apparmor_dir / 'abstractions',
|
||||
)
|
||||
foreach name : apparmor_gen_abstractions
|
||||
configure_file(
|
||||
input: '@0@.in'.format(name),
|
||||
output: name,
|
||||
command: apparmor_gen_cmd,
|
||||
capture: true,
|
||||
install: true,
|
||||
install_dir: apparmor_dir / 'abstractions',
|
||||
)
|
||||
endforeach
|
||||
|
||||
install_data(
|
||||
[ 'TEMPLATE.qemu', 'TEMPLATE.lxc' ],
|
||||
install_dir: apparmor_dir / 'libvirt',
|
||||
)
|
||||
|
||||
if not conf.has('WITH_APPARMOR_3')
|
||||
# We only install the empty local override for AppArmor 2.x. For
|
||||
# AppArmor 3.x, upstream's preference is to avoid creating these
|
||||
# files in order to limit the amount of filesystem clutter.
|
||||
install_data(
|
||||
'usr.lib.libvirt.virt-aa-helper.local',
|
||||
install_dir: apparmor_dir / 'local',
|
||||
rename: 'usr.lib.libvirt.virt-aa-helper',
|
||||
)
|
||||
endif
|
||||
|
@ -74,5 +74,10 @@ profile virt-aa-helper @libexecdir@/virt-aa-helper {
|
||||
/**.[iI][sS][oO] r,
|
||||
/**/disk{,.*} r,
|
||||
|
||||
@BEGIN_APPARMOR_3@
|
||||
include if exists <local/usr.lib.libvirt.virt-aa-helper>
|
||||
@END_APPARMOR_3@
|
||||
@BEGIN_APPARMOR_2@
|
||||
#include <local/usr.lib.libvirt.virt-aa-helper>
|
||||
@END_APPARMOR_2@
|
||||
}
|
||||
|
@ -144,5 +144,7 @@ profile libvirtd @sbindir@/libvirtd flags=(attach_disconnected) {
|
||||
/usr/{lib,lib64,lib/qemu,libexec,libexec/qemu}/qemu-bridge-helper rmix,
|
||||
}
|
||||
|
||||
@BEGIN_APPARMOR_3@
|
||||
include if exists <local/usr.sbin.libvirtd>
|
||||
@END_APPARMOR_3@
|
||||
}
|
||||
|
@ -136,5 +136,7 @@ profile virtqemud @sbindir@/virtqemud flags=(attach_disconnected) {
|
||||
/usr/{lib,lib64,lib/qemu,libexec,libexec/qemu}/qemu-bridge-helper rmix,
|
||||
}
|
||||
|
||||
@BEGIN_APPARMOR_3@
|
||||
include if exists <local/usr.sbin.virtqemud>
|
||||
@END_APPARMOR_3@
|
||||
}
|
||||
|
@ -55,5 +55,7 @@ profile virtxend @sbindir@/virtxend flags=(attach_disconnected) {
|
||||
/etc/libvirt/hooks/** rmix,
|
||||
/etc/xen/scripts/** rmix,
|
||||
|
||||
@BEGIN_APPARMOR_3@
|
||||
include if exists <local/usr.sbin.virtxend>
|
||||
@END_APPARMOR_3@
|
||||
}
|
||||
|
@ -1560,8 +1560,13 @@ main(int argc, char **argv)
|
||||
|
||||
/* create the profile from TEMPLATE */
|
||||
if (ctl->cmd == 'c' || purged) {
|
||||
g_autofree char *tmp = g_strdup_printf(
|
||||
" #include if exists <libvirt/%s.files>\n", ctl->uuid);
|
||||
g_autofree char *tmp = NULL;
|
||||
#if defined(WITH_APPARMOR_3)
|
||||
const char *ifexists = "if exists ";
|
||||
#else
|
||||
const char *ifexists = "";
|
||||
#endif
|
||||
tmp = g_strdup_printf(" #include %s<libvirt/%s.files>\n", ifexists, ctl->uuid);
|
||||
|
||||
if (ctl->dryrun) {
|
||||
vah_info(profile);
|
||||
|
@ -1939,7 +1939,6 @@ storageVolCreateXML(virStoragePoolPtr pool,
|
||||
if (backend->buildVol) {
|
||||
int buildret;
|
||||
virStorageVolDef *buildvoldef = NULL;
|
||||
unsigned int buildFlags = flags;
|
||||
|
||||
buildvoldef = g_new0(virStorageVolDef, 1);
|
||||
|
||||
@ -1954,8 +1953,7 @@ storageVolCreateXML(virStoragePoolPtr pool,
|
||||
voldef->building = true;
|
||||
virObjectUnlock(obj);
|
||||
|
||||
buildFlags &= ~VIR_STORAGE_VOL_CREATE_VALIDATE;
|
||||
buildret = backend->buildVol(obj, buildvoldef, buildFlags);
|
||||
buildret = backend->buildVol(obj, buildvoldef, flags);
|
||||
|
||||
VIR_FREE(buildvoldef);
|
||||
|
||||
|
@ -74,7 +74,6 @@ virStorageFileBackendGlusterInitServer(virStorageFileBackendGlusterPriv *priv,
|
||||
hoststr = host->socket;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_NET_HOST_TRANS_FD:
|
||||
case VIR_STORAGE_NET_HOST_TRANS_LAST:
|
||||
break;
|
||||
}
|
||||
|
@ -637,8 +637,10 @@ virBitmapNewData(const void *data,
|
||||
* Convert a bitmap to a chunk of data containing bits information.
|
||||
* Data consists of sequential bytes, with lower bytes containing
|
||||
* lower bits. This function allocates @data.
|
||||
*
|
||||
* Returns 0 on success, -1 otherwise.
|
||||
*/
|
||||
void
|
||||
int
|
||||
virBitmapToData(virBitmap *bitmap,
|
||||
unsigned char **data,
|
||||
int *dataLen)
|
||||
@ -654,6 +656,8 @@ virBitmapToData(virBitmap *bitmap,
|
||||
*dataLen = len;
|
||||
|
||||
virBitmapToDataBuf(bitmap, *data, *dataLen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -91,7 +91,7 @@ virBitmap *virBitmapNewCopy(virBitmap *src) ATTRIBUTE_NONNULL(1);
|
||||
|
||||
virBitmap *virBitmapNewData(const void *data, int len) ATTRIBUTE_NONNULL(1);
|
||||
|
||||
void virBitmapToData(virBitmap *bitmap, unsigned char **data, int *dataLen)
|
||||
int virBitmapToData(virBitmap *bitmap, unsigned char **data, int *dataLen)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||
|
||||
void virBitmapToDataBuf(virBitmap *bitmap, unsigned char *data, size_t len)
|
||||
|
@ -643,8 +643,9 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
|
||||
int nodecpus, nodecores, nodesockets, nodethreads, offline = 0;
|
||||
int threads_per_subcore = 0;
|
||||
unsigned int node;
|
||||
g_autofree char *sysfs_nodedir = NULL;
|
||||
g_autofree char *sysfs_cpudir_fallback = NULL;
|
||||
int ret = -1;
|
||||
char *sysfs_nodedir = NULL;
|
||||
char *sysfs_cpudir = NULL;
|
||||
int direrr;
|
||||
|
||||
*mhz = 0;
|
||||
@ -658,11 +659,12 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
|
||||
|
||||
/* Get information about what CPUs are present in the host and what
|
||||
* CPUs are online, so that we don't have to so for each node */
|
||||
if (!(present_cpus_map = virHostCPUGetPresentBitmap()))
|
||||
return -1;
|
||||
|
||||
if (!(online_cpus_map = virHostCPUGetOnlineBitmap()))
|
||||
return -1;
|
||||
present_cpus_map = virHostCPUGetPresentBitmap();
|
||||
if (!present_cpus_map)
|
||||
goto cleanup;
|
||||
online_cpus_map = virHostCPUGetOnlineBitmap();
|
||||
if (!online_cpus_map)
|
||||
goto cleanup;
|
||||
|
||||
/* OK, we've parsed clock speed out of /proc/cpuinfo. Get the
|
||||
* core, node, socket, thread and topology information from /sys
|
||||
@ -697,7 +699,7 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
|
||||
* On hosts other than POWER this will be 0, in which case a simpler
|
||||
* thread-counting logic will be used */
|
||||
if ((threads_per_subcore = virHostCPUGetThreadsPerSubcore(arch)) < 0)
|
||||
return -1;
|
||||
goto cleanup;
|
||||
|
||||
/* If the subcore configuration is not valid, just pretend subcores
|
||||
* are not in use and count threads one by one */
|
||||
@ -705,8 +707,6 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
|
||||
threads_per_subcore = 0;
|
||||
|
||||
while ((direrr = virDirRead(nodedir, &nodedirent, sysfs_nodedir)) > 0) {
|
||||
g_autofree char *sysfs_cpudir = NULL;
|
||||
|
||||
if (sscanf(nodedirent->d_name, "node%u", &node) != 1)
|
||||
continue;
|
||||
|
||||
@ -721,7 +721,9 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
|
||||
threads_per_subcore,
|
||||
&nodesockets, &nodecores,
|
||||
&nodethreads, &offline)) < 0)
|
||||
return -1;
|
||||
goto cleanup;
|
||||
|
||||
VIR_FREE(sysfs_cpudir);
|
||||
|
||||
*cpus += nodecpus;
|
||||
|
||||
@ -736,21 +738,23 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
|
||||
}
|
||||
|
||||
if (direrr < 0)
|
||||
return -1;
|
||||
goto cleanup;
|
||||
|
||||
if (*cpus && *nodes)
|
||||
goto done;
|
||||
|
||||
fallback:
|
||||
sysfs_cpudir_fallback = g_strdup_printf("%s/cpu", SYSFS_SYSTEM_PATH);
|
||||
VIR_FREE(sysfs_cpudir);
|
||||
|
||||
if ((nodecpus = virHostCPUParseNode(sysfs_cpudir_fallback, arch,
|
||||
sysfs_cpudir = g_strdup_printf("%s/cpu", SYSFS_SYSTEM_PATH);
|
||||
|
||||
if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
|
||||
present_cpus_map,
|
||||
online_cpus_map,
|
||||
threads_per_subcore,
|
||||
&nodesockets, &nodecores,
|
||||
&nodethreads, &offline)) < 0)
|
||||
return -1;
|
||||
goto cleanup;
|
||||
|
||||
*nodes = 1;
|
||||
*cpus = nodecpus;
|
||||
@ -762,17 +766,17 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
|
||||
/* There should always be at least one cpu, socket, node, and thread. */
|
||||
if (*cpus == 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs found"));
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (*sockets == 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets found"));
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (*threads == 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads found"));
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Now check if the topology makes sense. There are machines that don't
|
||||
@ -792,7 +796,12 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
|
||||
*threads = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(sysfs_nodedir);
|
||||
VIR_FREE(sysfs_cpudir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK))
|
||||
@ -1101,8 +1110,8 @@ virHostCPUGetMap(unsigned char **cpumap,
|
||||
if (!(cpus = virHostCPUGetOnlineBitmap()))
|
||||
goto cleanup;
|
||||
|
||||
if (cpumap)
|
||||
virBitmapToData(cpus, cpumap, &dummy);
|
||||
if (cpumap && virBitmapToData(cpus, cpumap, &dummy) < 0)
|
||||
goto cleanup;
|
||||
if (online)
|
||||
*online = virBitmapCountBits(cpus);
|
||||
|
||||
|
@ -70,14 +70,11 @@ virInhibitorAcquire(const char *what,
|
||||
VIR_DEBUG("what=%s who=%s why=%s mode=%s",
|
||||
NULLSTR(what), NULLSTR(who), NULLSTR(why), NULLSTR(mode));
|
||||
|
||||
if (!virGDBusHasSystemBus()) {
|
||||
if (!(systemBus = virGDBusGetSystemBus())) {
|
||||
VIR_DEBUG("system dbus not available, skipping system inhibitor");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(systemBus = virGDBusGetSystemBus()))
|
||||
return 0;
|
||||
|
||||
if (virSystemdHasLogind() < 0) {
|
||||
VIR_DEBUG("logind not available, skipping system inhibitor");
|
||||
return 0;
|
||||
|
@ -4553,507 +4553,6 @@ static int vboxCloseDisksRecursively(virDomainPtr dom, char *location)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vboxSnapshotReplaceRWDisks(struct _vboxDriver *data,
|
||||
virVBoxSnapshotConfMachine *snapshotMachineDesc,
|
||||
char *currentSnapshotXmlFilePath)
|
||||
{
|
||||
g_auto(GStrv) realReadWriteDisksPath = NULL;
|
||||
g_auto(GStrv) realReadOnlyDisksPath = NULL;
|
||||
int realReadWriteDisksPathSize = 0;
|
||||
int realReadOnlyDisksPathSize = 0;
|
||||
int it = 0;
|
||||
|
||||
/*
|
||||
* We have created fake disks, so we have to remove them and replace them with
|
||||
* the read-write disks if there are any. The fake disks will be closed during
|
||||
* the machine unregistration.
|
||||
*/
|
||||
if (virVBoxSnapshotConfRemoveFakeDisks(snapshotMachineDesc) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to remove Fake Disks"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
realReadWriteDisksPathSize = virVBoxSnapshotConfGetRWDisksPathsFromLibvirtXML(currentSnapshotXmlFilePath,
|
||||
&realReadWriteDisksPath);
|
||||
realReadOnlyDisksPathSize = virVBoxSnapshotConfGetRODisksPathsFromLibvirtXML(currentSnapshotXmlFilePath,
|
||||
&realReadOnlyDisksPath);
|
||||
/* The read-only disk number is necessarily greater or equal to the
|
||||
* read-write disk number */
|
||||
if (realReadOnlyDisksPathSize < realReadWriteDisksPathSize) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("The read only disk number must be greater or equal to the read write disk number"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (it = 0; it < realReadWriteDisksPathSize; it++) {
|
||||
virVBoxSnapshotConfHardDisk *readWriteDisk = NULL;
|
||||
PRUnichar *locationUtf = NULL;
|
||||
IMedium *readWriteMedium = NULL;
|
||||
char *uuid = NULL;
|
||||
PRUnichar *formatUtf = NULL;
|
||||
char *format = NULL;
|
||||
const char *parentUuid = NULL;
|
||||
vboxIID iid;
|
||||
nsresult rc;
|
||||
|
||||
VBOX_IID_INITIALIZE(&iid);
|
||||
VBOX_UTF8_TO_UTF16(realReadWriteDisksPath[it], &locationUtf);
|
||||
rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj,
|
||||
locationUtf,
|
||||
DeviceType_HardDisk,
|
||||
AccessMode_ReadWrite,
|
||||
&readWriteMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to open HardDisk"));
|
||||
VBOX_UTF16_FREE(locationUtf);
|
||||
return -1;
|
||||
}
|
||||
VBOX_UTF16_FREE(locationUtf);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(readWriteMedium, &iid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get the read write medium id"));
|
||||
return -1;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid);
|
||||
vboxIIDUnalloc(&iid);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetFormat(readWriteMedium, &formatUtf);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get the read write medium format"));
|
||||
return -1;
|
||||
}
|
||||
VBOX_UTF16_TO_UTF8(formatUtf, &format);
|
||||
VBOX_UTF16_FREE(formatUtf);
|
||||
|
||||
readWriteDisk = g_new0(virVBoxSnapshotConfHardDisk, 1);
|
||||
|
||||
readWriteDisk->format = format;
|
||||
readWriteDisk->uuid = uuid;
|
||||
readWriteDisk->location = realReadWriteDisksPath[it];
|
||||
/*
|
||||
* We get the current snapshot's read-only disk uuid in order to add the
|
||||
* read-write disk to the media registry as its child. The read-only disk
|
||||
* is already in the media registry because it is the fake disk's parent.
|
||||
*/
|
||||
parentUuid = virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc,
|
||||
realReadOnlyDisksPath[it]);
|
||||
if (parentUuid == NULL) {
|
||||
VIR_FREE(readWriteDisk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(readWriteDisk,
|
||||
snapshotMachineDesc->mediaRegistry,
|
||||
parentUuid) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to add hard disk to media Registry"));
|
||||
VIR_FREE(readWriteDisk);
|
||||
return -1;
|
||||
}
|
||||
rc = gVBoxAPI.UIMedium.Close(readWriteMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to close HardDisk"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vboxSnapshotAddDisksToMediaRegistry(struct _vboxDriver *data,
|
||||
virDomainSnapshotDef *def,
|
||||
virVBoxSnapshotConfMachine *snapshotMachineDesc)
|
||||
{
|
||||
int it = 0;
|
||||
|
||||
for (it = 0; it < def->parent.dom->ndisks; it++) {
|
||||
int diskInMediaRegistry = 0;
|
||||
IMedium *readOnlyMedium = NULL;
|
||||
PRUnichar *locationUtf = NULL;
|
||||
char *uuid = NULL;
|
||||
PRUnichar *formatUtf = NULL;
|
||||
char *format = NULL;
|
||||
char *parentUuid = NULL;
|
||||
virVBoxSnapshotConfHardDisk *readOnlyDisk = NULL;
|
||||
vboxIID iid, parentiid;
|
||||
IMedium *parentReadOnlyMedium = NULL;
|
||||
nsresult rc;
|
||||
|
||||
VBOX_IID_INITIALIZE(&iid);
|
||||
VBOX_IID_INITIALIZE(&parentiid);
|
||||
diskInMediaRegistry = virVBoxSnapshotConfDiskIsInMediaRegistry(snapshotMachineDesc,
|
||||
def->parent.dom->disks[it]->src->path);
|
||||
if (diskInMediaRegistry == -1) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to know if disk is in media registry"));
|
||||
return -1;
|
||||
}
|
||||
if (diskInMediaRegistry == 1) /* Nothing to do. */
|
||||
continue;
|
||||
/* The read only disk is not in the media registry */
|
||||
|
||||
VBOX_UTF8_TO_UTF16(def->parent.dom->disks[it]->src->path, &locationUtf);
|
||||
rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj,
|
||||
locationUtf,
|
||||
DeviceType_HardDisk,
|
||||
AccessMode_ReadWrite,
|
||||
&readOnlyMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to open HardDisk"));
|
||||
VBOX_UTF16_FREE(locationUtf);
|
||||
return -1;
|
||||
}
|
||||
VBOX_UTF16_FREE(locationUtf);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(readOnlyMedium, &iid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get hard disk id"));
|
||||
return -1;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid);
|
||||
vboxIIDUnalloc(&iid);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetFormat(readOnlyMedium, &formatUtf);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get hard disk format"));
|
||||
VIR_FREE(uuid);
|
||||
return -1;
|
||||
}
|
||||
VBOX_UTF16_TO_UTF8(formatUtf, &format);
|
||||
VBOX_UTF16_FREE(formatUtf);
|
||||
|
||||
/* This disk is already in the media registry */
|
||||
rc = gVBoxAPI.UIMedium.GetParent(readOnlyMedium, &parentReadOnlyMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get parent hard disk"));
|
||||
VIR_FREE(uuid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(parentReadOnlyMedium, &parentiid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get hard disk id"));
|
||||
VIR_FREE(uuid);
|
||||
return -1;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid);
|
||||
vboxIIDUnalloc(&parentiid);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.Close(readOnlyMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to close HardDisk"));
|
||||
VIR_FREE(uuid);
|
||||
VIR_FREE(parentUuid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
readOnlyDisk = g_new0(virVBoxSnapshotConfHardDisk, 1);
|
||||
|
||||
readOnlyDisk->format = format;
|
||||
readOnlyDisk->uuid = uuid;
|
||||
readOnlyDisk->location = g_strdup(def->parent.dom->disks[it]->src->path);
|
||||
|
||||
if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(readOnlyDisk, snapshotMachineDesc->mediaRegistry,
|
||||
parentUuid) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to add hard disk to media registry"));
|
||||
VIR_FREE(readOnlyDisk);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vboxSnapshotAddRWDisks(struct _vboxDriver *data,
|
||||
virDomainSnapshotDef *def,
|
||||
virVBoxSnapshotConfMachine *snapshotMachineDesc,
|
||||
bool needToChangeStorageController)
|
||||
{
|
||||
int it = 0;
|
||||
|
||||
for (it = 0; it < def->ndisks; it++) {
|
||||
IMedium *medium = NULL;
|
||||
PRUnichar *locationUtf16 = NULL;
|
||||
virVBoxSnapshotConfHardDisk *disk = NULL;
|
||||
PRUnichar *formatUtf16 = NULL;
|
||||
char *format = NULL;
|
||||
char *uuid = NULL;
|
||||
IMedium *parentDisk = NULL;
|
||||
char *parentUuid = NULL;
|
||||
vboxIID iid, parentiid;
|
||||
nsresult rc;
|
||||
|
||||
VBOX_IID_INITIALIZE(&iid);
|
||||
VBOX_IID_INITIALIZE(&parentiid);
|
||||
VBOX_UTF8_TO_UTF16(def->disks[it].src->path, &locationUtf16);
|
||||
rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj,
|
||||
locationUtf16,
|
||||
DeviceType_HardDisk,
|
||||
AccessMode_ReadWrite,
|
||||
&medium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to open HardDisk"));
|
||||
return -1;
|
||||
}
|
||||
VBOX_UTF16_FREE(locationUtf16);
|
||||
|
||||
disk = g_new0(virVBoxSnapshotConfHardDisk, 1);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetFormat(medium, &formatUtf16);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get disk format"));
|
||||
VIR_FREE(disk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
VBOX_UTF16_TO_UTF8(formatUtf16, &format);
|
||||
disk->format = format;
|
||||
VBOX_UTF16_FREE(formatUtf16);
|
||||
|
||||
disk->location = g_strdup(def->disks[it].src->path);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(medium, &iid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get disk uuid"));
|
||||
VIR_FREE(disk);
|
||||
return -1;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid);
|
||||
disk->uuid = uuid;
|
||||
vboxIIDUnalloc(&iid);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetParent(medium, &parentDisk);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get disk parent"));
|
||||
VIR_FREE(disk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
gVBoxAPI.UIMedium.GetId(parentDisk, &parentiid);
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid);
|
||||
vboxIIDUnalloc(&parentiid);
|
||||
if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(disk,
|
||||
snapshotMachineDesc->mediaRegistry,
|
||||
parentUuid) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to add hard disk to the media registry"));
|
||||
VIR_FREE(disk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (needToChangeStorageController) {
|
||||
/* We need to append this disk in the storage controller */
|
||||
g_auto(GStrv) searchResultTab = NULL;
|
||||
char *tmp = NULL;
|
||||
ssize_t resultSize = 0;
|
||||
|
||||
resultSize = virStringSearch(snapshotMachineDesc->storageController,
|
||||
VBOX_UUID_REGEX,
|
||||
it + 1,
|
||||
&searchResultTab);
|
||||
if (resultSize != it + 1) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Unable to find UUID %1$s"), searchResultTab[it]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = virStringReplace(snapshotMachineDesc->storageController,
|
||||
searchResultTab[it],
|
||||
disk->uuid);
|
||||
VIR_FREE(snapshotMachineDesc->storageController);
|
||||
if (!tmp)
|
||||
return -1;
|
||||
snapshotMachineDesc->storageController = g_strdup(tmp);
|
||||
|
||||
VIR_FREE(tmp);
|
||||
}
|
||||
/* Close disk */
|
||||
rc = gVBoxAPI.UIMedium.Close(medium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to close HardDisk"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vboxSnapshotCreateFakeDiffStorage(struct _vboxDriver *data,
|
||||
virDomainSnapshotDef *def,
|
||||
char *machineLocationPath,
|
||||
virVBoxSnapshotConfMachine *snapshotMachineDesc)
|
||||
{
|
||||
virVBoxSnapshotConfHardDisk *newHardDisk = NULL;
|
||||
int it;
|
||||
int ret = -1;
|
||||
|
||||
for (it = 0; it < def->parent.dom->ndisks; it++) {
|
||||
IMedium *medium = NULL;
|
||||
PRUnichar *locationUtf16 = NULL;
|
||||
char *parentUuid = NULL;
|
||||
IMedium *newMedium = NULL;
|
||||
PRUnichar *formatUtf16 = NULL;
|
||||
PRUnichar *newLocation = NULL;
|
||||
char *newLocationUtf8 = NULL;
|
||||
resultCodeUnion resultCode;
|
||||
char *uuid = NULL;
|
||||
char *format = NULL;
|
||||
char *tmp = NULL;
|
||||
vboxIID iid, parentiid;
|
||||
IProgress *progress = NULL;
|
||||
PRUint32 tab[1];
|
||||
nsresult rc;
|
||||
g_auto(GStrv) searchResultTab = NULL;
|
||||
ssize_t resultSize = 0;
|
||||
|
||||
VBOX_IID_INITIALIZE(&iid);
|
||||
VBOX_IID_INITIALIZE(&parentiid);
|
||||
VBOX_UTF8_TO_UTF16(def->parent.dom->disks[it]->src->path, &locationUtf16);
|
||||
rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj,
|
||||
locationUtf16,
|
||||
DeviceType_HardDisk,
|
||||
AccessMode_ReadWrite,
|
||||
&medium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to open HardDisk"));
|
||||
VBOX_UTF16_FREE(locationUtf16);
|
||||
goto cleanup;
|
||||
}
|
||||
VBOX_UTF16_FREE(locationUtf16);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(medium, &parentiid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get hard disk id"));
|
||||
goto cleanup;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid);
|
||||
vboxIIDUnalloc(&parentiid);
|
||||
VBOX_UTF8_TO_UTF16("VDI", &formatUtf16);
|
||||
|
||||
newLocationUtf8 = g_strdup_printf("%sfakedisk-%d.vdi",
|
||||
machineLocationPath, it);
|
||||
VBOX_UTF8_TO_UTF16(newLocationUtf8, &newLocation);
|
||||
rc = gVBoxAPI.UIVirtualBox.CreateHardDisk(data->vboxObj,
|
||||
formatUtf16,
|
||||
newLocation,
|
||||
&newMedium);
|
||||
VBOX_UTF16_FREE(newLocation);
|
||||
VBOX_UTF16_FREE(formatUtf16);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to create HardDisk"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tab[0] = MediumVariant_Diff;
|
||||
gVBoxAPI.UIMedium.CreateDiffStorage(medium, newMedium, 1, tab, &progress);
|
||||
|
||||
gVBoxAPI.UIProgress.WaitForCompletion(progress, -1);
|
||||
gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode);
|
||||
if (RC_FAILED(resultCode)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Error while creating diff storage, rc=%1$08x"),
|
||||
resultCode.uResultCode);
|
||||
goto cleanup;
|
||||
}
|
||||
VBOX_RELEASE(progress);
|
||||
/*
|
||||
* The differential newHardDisk is created, we add it to the
|
||||
* media registry and the machine storage controllers.
|
||||
*/
|
||||
|
||||
newHardDisk = g_new0(virVBoxSnapshotConfHardDisk, 1);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(newMedium, &iid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get medium uuid"));
|
||||
goto cleanup;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid);
|
||||
newHardDisk->uuid = uuid;
|
||||
vboxIIDUnalloc(&iid);
|
||||
|
||||
newHardDisk->location = g_strdup(newLocationUtf8);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetFormat(newMedium, &formatUtf16);
|
||||
VBOX_UTF16_TO_UTF8(formatUtf16, &format);
|
||||
newHardDisk->format = format;
|
||||
VBOX_UTF16_FREE(formatUtf16);
|
||||
|
||||
if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(newHardDisk,
|
||||
snapshotMachineDesc->mediaRegistry,
|
||||
parentUuid) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to add hard disk to the media registry"));
|
||||
goto cleanup;
|
||||
}
|
||||
newHardDisk = NULL; /* Consumed by above */
|
||||
/* Adding the fake disk to the machine storage controllers */
|
||||
|
||||
resultSize = virStringSearch(snapshotMachineDesc->storageController,
|
||||
VBOX_UUID_REGEX,
|
||||
it + 1,
|
||||
&searchResultTab);
|
||||
if (resultSize != it + 1) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Unable to find UUID %1$s"), searchResultTab[it]);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tmp = virStringReplace(snapshotMachineDesc->storageController,
|
||||
searchResultTab[it],
|
||||
uuid);
|
||||
VIR_FREE(snapshotMachineDesc->storageController);
|
||||
if (!tmp)
|
||||
goto cleanup;
|
||||
snapshotMachineDesc->storageController = g_strdup(tmp);
|
||||
|
||||
VIR_FREE(tmp);
|
||||
/* Closing the "fake" disk */
|
||||
rc = gVBoxAPI.UIMedium.Close(newMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to close the new medium"));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
virVboxSnapshotConfHardDiskFree(newHardDisk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vboxSnapshotRedefine(virDomainPtr dom,
|
||||
virDomainSnapshotDef *def,
|
||||
@ -5097,10 +4596,15 @@ vboxSnapshotRedefine(virDomainPtr dom,
|
||||
char *currentSnapshotXmlFilePath = NULL;
|
||||
PRUnichar *machineNameUtf16 = NULL;
|
||||
char *machineName = NULL;
|
||||
g_auto(GStrv) realReadWriteDisksPath = NULL;
|
||||
int realReadWriteDisksPathSize = 0;
|
||||
g_auto(GStrv) realReadOnlyDisksPath = NULL;
|
||||
int realReadOnlyDisksPathSize = 0;
|
||||
virVBoxSnapshotConfSnapshot *newSnapshotPtr = NULL;
|
||||
unsigned char snapshotUuid[VIR_UUID_BUFLEN];
|
||||
virVBoxSnapshotConfHardDisk **hardDiskToOpen = NULL;
|
||||
size_t hardDiskToOpenSize = 0;
|
||||
virVBoxSnapshotConfHardDisk *newHardDisk = NULL;
|
||||
g_auto(GStrv) searchResultTab = NULL;
|
||||
ssize_t resultSize = 0;
|
||||
int it = 0;
|
||||
@ -5164,10 +4668,102 @@ vboxSnapshotRedefine(virDomainPtr dom,
|
||||
}
|
||||
|
||||
if (snapshotFileExists) {
|
||||
if (vboxSnapshotReplaceRWDisks(data, snapshotMachineDesc,
|
||||
currentSnapshotXmlFilePath) < 0)
|
||||
/*
|
||||
* We have created fake disks, so we have to remove them and replace them with
|
||||
* the read-write disks if there are any. The fake disks will be closed during
|
||||
* the machine unregistration.
|
||||
*/
|
||||
if (virVBoxSnapshotConfRemoveFakeDisks(snapshotMachineDesc) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to remove Fake Disks"));
|
||||
goto cleanup;
|
||||
}
|
||||
realReadWriteDisksPathSize = virVBoxSnapshotConfGetRWDisksPathsFromLibvirtXML(currentSnapshotXmlFilePath,
|
||||
&realReadWriteDisksPath);
|
||||
realReadOnlyDisksPathSize = virVBoxSnapshotConfGetRODisksPathsFromLibvirtXML(currentSnapshotXmlFilePath,
|
||||
&realReadOnlyDisksPath);
|
||||
/* The read-only disk number is necessarily greater or equal to the
|
||||
* read-write disk number */
|
||||
if (realReadOnlyDisksPathSize < realReadWriteDisksPathSize) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("The read only disk number must be greater or equal to the read write disk number"));
|
||||
goto cleanup;
|
||||
}
|
||||
for (it = 0; it < realReadWriteDisksPathSize; it++) {
|
||||
virVBoxSnapshotConfHardDisk *readWriteDisk = NULL;
|
||||
PRUnichar *locationUtf = NULL;
|
||||
IMedium *readWriteMedium = NULL;
|
||||
char *uuid = NULL;
|
||||
PRUnichar *formatUtf = NULL;
|
||||
char *format = NULL;
|
||||
const char *parentUuid = NULL;
|
||||
vboxIID iid;
|
||||
|
||||
VBOX_IID_INITIALIZE(&iid);
|
||||
VBOX_UTF8_TO_UTF16(realReadWriteDisksPath[it], &locationUtf);
|
||||
rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj,
|
||||
locationUtf,
|
||||
DeviceType_HardDisk,
|
||||
AccessMode_ReadWrite,
|
||||
&readWriteMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to open HardDisk"));
|
||||
VBOX_UTF16_FREE(locationUtf);
|
||||
goto cleanup;
|
||||
}
|
||||
VBOX_UTF16_FREE(locationUtf);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(readWriteMedium, &iid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get the read write medium id"));
|
||||
goto cleanup;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid);
|
||||
vboxIIDUnalloc(&iid);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetFormat(readWriteMedium, &formatUtf);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get the read write medium format"));
|
||||
goto cleanup;
|
||||
}
|
||||
VBOX_UTF16_TO_UTF8(formatUtf, &format);
|
||||
VBOX_UTF16_FREE(formatUtf);
|
||||
|
||||
readWriteDisk = g_new0(virVBoxSnapshotConfHardDisk, 1);
|
||||
|
||||
readWriteDisk->format = format;
|
||||
readWriteDisk->uuid = uuid;
|
||||
readWriteDisk->location = realReadWriteDisksPath[it];
|
||||
/*
|
||||
* We get the current snapshot's read-only disk uuid in order to add the
|
||||
* read-write disk to the media registry as its child. The read-only disk
|
||||
* is already in the media registry because it is the fake disk's parent.
|
||||
*/
|
||||
parentUuid = virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc,
|
||||
realReadOnlyDisksPath[it]);
|
||||
if (parentUuid == NULL) {
|
||||
VIR_FREE(readWriteDisk);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(readWriteDisk,
|
||||
snapshotMachineDesc->mediaRegistry,
|
||||
parentUuid) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to add hard disk to media Registry"));
|
||||
VIR_FREE(readWriteDisk);
|
||||
goto cleanup;
|
||||
}
|
||||
rc = gVBoxAPI.UIMedium.Close(readWriteMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to close HardDisk"));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now we have done this swap, we remove the snapshot xml file from the
|
||||
* current machine location.
|
||||
@ -5183,8 +4779,106 @@ vboxSnapshotRedefine(virDomainPtr dom,
|
||||
* read-only disks are in the redefined snapshot's media registry (the disks need to
|
||||
* be open to query their uuid).
|
||||
*/
|
||||
if (vboxSnapshotAddDisksToMediaRegistry(data, def, snapshotMachineDesc) < 0)
|
||||
goto cleanup;
|
||||
for (it = 0; it < def->parent.dom->ndisks; it++) {
|
||||
int diskInMediaRegistry = 0;
|
||||
IMedium *readOnlyMedium = NULL;
|
||||
PRUnichar *locationUtf = NULL;
|
||||
char *uuid = NULL;
|
||||
PRUnichar *formatUtf = NULL;
|
||||
char *format = NULL;
|
||||
char *parentUuid = NULL;
|
||||
virVBoxSnapshotConfHardDisk *readOnlyDisk = NULL;
|
||||
vboxIID iid, parentiid;
|
||||
IMedium *parentReadOnlyMedium = NULL;
|
||||
|
||||
VBOX_IID_INITIALIZE(&iid);
|
||||
VBOX_IID_INITIALIZE(&parentiid);
|
||||
diskInMediaRegistry = virVBoxSnapshotConfDiskIsInMediaRegistry(snapshotMachineDesc,
|
||||
def->parent.dom->disks[it]->src->path);
|
||||
if (diskInMediaRegistry == -1) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to know if disk is in media registry"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (diskInMediaRegistry == 1) /* Nothing to do. */
|
||||
continue;
|
||||
/* The read only disk is not in the media registry */
|
||||
|
||||
VBOX_UTF8_TO_UTF16(def->parent.dom->disks[it]->src->path, &locationUtf);
|
||||
rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj,
|
||||
locationUtf,
|
||||
DeviceType_HardDisk,
|
||||
AccessMode_ReadWrite,
|
||||
&readOnlyMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to open HardDisk"));
|
||||
VBOX_UTF16_FREE(locationUtf);
|
||||
goto cleanup;
|
||||
}
|
||||
VBOX_UTF16_FREE(locationUtf);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(readOnlyMedium, &iid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get hard disk id"));
|
||||
goto cleanup;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid);
|
||||
vboxIIDUnalloc(&iid);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetFormat(readOnlyMedium, &formatUtf);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get hard disk format"));
|
||||
VIR_FREE(uuid);
|
||||
goto cleanup;
|
||||
}
|
||||
VBOX_UTF16_TO_UTF8(formatUtf, &format);
|
||||
VBOX_UTF16_FREE(formatUtf);
|
||||
|
||||
/* This disk is already in the media registry */
|
||||
rc = gVBoxAPI.UIMedium.GetParent(readOnlyMedium, &parentReadOnlyMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get parent hard disk"));
|
||||
VIR_FREE(uuid);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(parentReadOnlyMedium, &parentiid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get hard disk id"));
|
||||
VIR_FREE(uuid);
|
||||
goto cleanup;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid);
|
||||
vboxIIDUnalloc(&parentiid);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.Close(readOnlyMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to close HardDisk"));
|
||||
VIR_FREE(uuid);
|
||||
VIR_FREE(parentUuid);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
readOnlyDisk = g_new0(virVBoxSnapshotConfHardDisk, 1);
|
||||
|
||||
readOnlyDisk->format = format;
|
||||
readOnlyDisk->uuid = uuid;
|
||||
readOnlyDisk->location = g_strdup(def->parent.dom->disks[it]->src->path);
|
||||
|
||||
if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(readOnlyDisk, snapshotMachineDesc->mediaRegistry,
|
||||
parentUuid) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to add hard disk to media registry"));
|
||||
VIR_FREE(readOnlyDisk);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, we can unregister the machine */
|
||||
rc = gVBoxAPI.UIMachine.Unregister(machine,
|
||||
@ -5368,20 +5062,243 @@ vboxSnapshotRedefine(virDomainPtr dom,
|
||||
* If the snapshot to redefine is the current snapshot, we add read-write disks in
|
||||
* the machine storage controllers.
|
||||
*/
|
||||
if (vboxSnapshotAddRWDisks(data, def, snapshotMachineDesc,
|
||||
needToChangeStorageController) < 0) {
|
||||
goto cleanup;
|
||||
for (it = 0; it < def->ndisks; it++) {
|
||||
IMedium *medium = NULL;
|
||||
PRUnichar *locationUtf16 = NULL;
|
||||
virVBoxSnapshotConfHardDisk *disk = NULL;
|
||||
PRUnichar *formatUtf16 = NULL;
|
||||
char *format = NULL;
|
||||
char *uuid = NULL;
|
||||
IMedium *parentDisk = NULL;
|
||||
char *parentUuid = NULL;
|
||||
vboxIID iid, parentiid;
|
||||
|
||||
VBOX_IID_INITIALIZE(&iid);
|
||||
VBOX_IID_INITIALIZE(&parentiid);
|
||||
VBOX_UTF8_TO_UTF16(def->disks[it].src->path, &locationUtf16);
|
||||
rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj,
|
||||
locationUtf16,
|
||||
DeviceType_HardDisk,
|
||||
AccessMode_ReadWrite,
|
||||
&medium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to open HardDisk"));
|
||||
goto cleanup;
|
||||
}
|
||||
VBOX_UTF16_FREE(locationUtf16);
|
||||
|
||||
disk = g_new0(virVBoxSnapshotConfHardDisk, 1);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetFormat(medium, &formatUtf16);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get disk format"));
|
||||
VIR_FREE(disk);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VBOX_UTF16_TO_UTF8(formatUtf16, &format);
|
||||
disk->format = format;
|
||||
VBOX_UTF16_FREE(formatUtf16);
|
||||
|
||||
disk->location = g_strdup(def->disks[it].src->path);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(medium, &iid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get disk uuid"));
|
||||
VIR_FREE(disk);
|
||||
goto cleanup;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid);
|
||||
disk->uuid = uuid;
|
||||
vboxIIDUnalloc(&iid);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetParent(medium, &parentDisk);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get disk parent"));
|
||||
VIR_FREE(disk);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
gVBoxAPI.UIMedium.GetId(parentDisk, &parentiid);
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid);
|
||||
vboxIIDUnalloc(&parentiid);
|
||||
if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(disk,
|
||||
snapshotMachineDesc->mediaRegistry,
|
||||
parentUuid) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to add hard disk to the media registry"));
|
||||
VIR_FREE(disk);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (needToChangeStorageController) {
|
||||
/* We need to append this disk in the storage controller */
|
||||
char *tmp = NULL;
|
||||
resultSize = virStringSearch(snapshotMachineDesc->storageController,
|
||||
VBOX_UUID_REGEX,
|
||||
it + 1,
|
||||
&searchResultTab);
|
||||
if (resultSize != it + 1) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Unable to find UUID %1$s"), searchResultTab[it]);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tmp = virStringReplace(snapshotMachineDesc->storageController,
|
||||
searchResultTab[it],
|
||||
disk->uuid);
|
||||
VIR_FREE(snapshotMachineDesc->storageController);
|
||||
if (!tmp)
|
||||
goto cleanup;
|
||||
snapshotMachineDesc->storageController = g_strdup(tmp);
|
||||
|
||||
VIR_FREE(tmp);
|
||||
}
|
||||
/* Close disk */
|
||||
rc = gVBoxAPI.UIMedium.Close(medium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to close HardDisk"));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char *snapshotContent;
|
||||
|
||||
/* Create a "fake" disk to avoid corrupting children snapshot disks. */
|
||||
if (vboxSnapshotCreateFakeDiffStorage(data, def,
|
||||
machineLocationPath,
|
||||
snapshotMachineDesc) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
for (it = 0; it < def->parent.dom->ndisks; it++) {
|
||||
IMedium *medium = NULL;
|
||||
PRUnichar *locationUtf16 = NULL;
|
||||
char *parentUuid = NULL;
|
||||
IMedium *newMedium = NULL;
|
||||
PRUnichar *formatUtf16 = NULL;
|
||||
PRUnichar *newLocation = NULL;
|
||||
char *newLocationUtf8 = NULL;
|
||||
resultCodeUnion resultCode;
|
||||
char *uuid = NULL;
|
||||
char *format = NULL;
|
||||
char *tmp = NULL;
|
||||
vboxIID iid, parentiid;
|
||||
IProgress *progress = NULL;
|
||||
PRUint32 tab[1];
|
||||
|
||||
VBOX_IID_INITIALIZE(&iid);
|
||||
VBOX_IID_INITIALIZE(&parentiid);
|
||||
VBOX_UTF8_TO_UTF16(def->parent.dom->disks[it]->src->path, &locationUtf16);
|
||||
rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj,
|
||||
locationUtf16,
|
||||
DeviceType_HardDisk,
|
||||
AccessMode_ReadWrite,
|
||||
&medium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to open HardDisk"));
|
||||
VBOX_UTF16_FREE(locationUtf16);
|
||||
goto cleanup;
|
||||
}
|
||||
VBOX_UTF16_FREE(locationUtf16);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(medium, &parentiid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get hard disk id"));
|
||||
goto cleanup;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid);
|
||||
vboxIIDUnalloc(&parentiid);
|
||||
VBOX_UTF8_TO_UTF16("VDI", &formatUtf16);
|
||||
|
||||
newLocationUtf8 = g_strdup_printf("%sfakedisk-%d.vdi",
|
||||
machineLocationPath, it);
|
||||
VBOX_UTF8_TO_UTF16(newLocationUtf8, &newLocation);
|
||||
rc = gVBoxAPI.UIVirtualBox.CreateHardDisk(data->vboxObj,
|
||||
formatUtf16,
|
||||
newLocation,
|
||||
&newMedium);
|
||||
VBOX_UTF16_FREE(newLocation);
|
||||
VBOX_UTF16_FREE(formatUtf16);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to create HardDisk"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tab[0] = MediumVariant_Diff;
|
||||
gVBoxAPI.UIMedium.CreateDiffStorage(medium, newMedium, 1, tab, &progress);
|
||||
|
||||
gVBoxAPI.UIProgress.WaitForCompletion(progress, -1);
|
||||
gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode);
|
||||
if (RC_FAILED(resultCode)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Error while creating diff storage, rc=%1$08x"),
|
||||
resultCode.uResultCode);
|
||||
goto cleanup;
|
||||
}
|
||||
VBOX_RELEASE(progress);
|
||||
/*
|
||||
* The differential newHardDisk is created, we add it to the
|
||||
* media registry and the machine storage controllers.
|
||||
*/
|
||||
|
||||
newHardDisk = g_new0(virVBoxSnapshotConfHardDisk, 1);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetId(newMedium, &iid);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to get medium uuid"));
|
||||
goto cleanup;
|
||||
}
|
||||
gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid);
|
||||
newHardDisk->uuid = uuid;
|
||||
vboxIIDUnalloc(&iid);
|
||||
|
||||
newHardDisk->location = g_strdup(newLocationUtf8);
|
||||
|
||||
rc = gVBoxAPI.UIMedium.GetFormat(newMedium, &formatUtf16);
|
||||
VBOX_UTF16_TO_UTF8(formatUtf16, &format);
|
||||
newHardDisk->format = format;
|
||||
VBOX_UTF16_FREE(formatUtf16);
|
||||
|
||||
if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(newHardDisk,
|
||||
snapshotMachineDesc->mediaRegistry,
|
||||
parentUuid) < 0) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to add hard disk to the media registry"));
|
||||
goto cleanup;
|
||||
}
|
||||
newHardDisk = NULL; /* Consumed by above */
|
||||
/* Adding the fake disk to the machine storage controllers */
|
||||
|
||||
resultSize = virStringSearch(snapshotMachineDesc->storageController,
|
||||
VBOX_UUID_REGEX,
|
||||
it + 1,
|
||||
&searchResultTab);
|
||||
if (resultSize != it + 1) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Unable to find UUID %1$s"), searchResultTab[it]);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tmp = virStringReplace(snapshotMachineDesc->storageController,
|
||||
searchResultTab[it],
|
||||
uuid);
|
||||
VIR_FREE(snapshotMachineDesc->storageController);
|
||||
if (!tmp)
|
||||
goto cleanup;
|
||||
snapshotMachineDesc->storageController = g_strdup(tmp);
|
||||
|
||||
VIR_FREE(tmp);
|
||||
/* Closing the "fake" disk */
|
||||
rc = gVBoxAPI.UIMedium.Close(newMedium);
|
||||
if (NS_FAILED(rc)) {
|
||||
vboxReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to close the new medium"));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We save the snapshot xml file to retrieve the real read-write disk during the
|
||||
* next define. This file is saved as "'machineLocation'/snapshot-'uuid'.xml"
|
||||
@ -5470,6 +5387,7 @@ vboxSnapshotRedefine(virDomainPtr dom,
|
||||
VIR_FREE(currentSnapshotXmlFilePath);
|
||||
VBOX_UTF16_FREE(machineNameUtf16);
|
||||
VBOX_UTF8_FREE(machineName);
|
||||
virVboxSnapshotConfHardDiskFree(newHardDisk);
|
||||
VIR_FREE(hardDiskToOpen);
|
||||
VIR_FREE(newSnapshotPtr);
|
||||
VIR_FREE(machineLocationPath);
|
||||
|
@ -1,8 +0,0 @@
|
||||
/usr/sbin/bhyve \
|
||||
-c 1 \
|
||||
-m 214 \
|
||||
-H \
|
||||
-P \
|
||||
-s 0:0,hostbridge \
|
||||
-s 1:0,virtio-rnd \
|
||||
bhyve
|
@ -1,20 +0,0 @@
|
||||
<domain type='bhyve'>
|
||||
<name>bhyve</name>
|
||||
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||
<memory unit='KiB'>219136</memory>
|
||||
<currentMemory unit='KiB'>219136</currentMemory>
|
||||
<vcpu placement='static'>1</vcpu>
|
||||
<os>
|
||||
<type>hvm</type>
|
||||
</os>
|
||||
<clock offset='localtime'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>destroy</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<rng model='virtio'>
|
||||
<backend model='random'>/dev/random</backend>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
|
||||
</rng>
|
||||
</devices>
|
||||
</domain>
|
@ -188,7 +188,6 @@ mymain(void)
|
||||
DO_TEST("vnc-vga-io");
|
||||
DO_TEST("vnc-resolution");
|
||||
DO_TEST("vnc-password");
|
||||
DO_TEST("virtio-rnd");
|
||||
|
||||
virObjectUnref(driver.caps);
|
||||
virObjectUnref(driver.xmlopt);
|
||||
|
@ -1,26 +0,0 @@
|
||||
<domain type='bhyve'>
|
||||
<name>bhyve</name>
|
||||
<uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
|
||||
<memory>219136</memory>
|
||||
<vcpu>1</vcpu>
|
||||
<os>
|
||||
<type>hvm</type>
|
||||
</os>
|
||||
<devices>
|
||||
<disk type='file'>
|
||||
<driver name='file' type='raw'/>
|
||||
<source file='/tmp/freebsd.img'/>
|
||||
<target dev='hda' bus='sata'/>
|
||||
<address type='drive' controller='0' bus='0' target='2' unit='0'/>
|
||||
</disk>
|
||||
<interface type='bridge'>
|
||||
<mac address='52:54:00:b9:94:02'/>
|
||||
<model type='virtio'/>
|
||||
<source bridge="virbr0"/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
</interface>
|
||||
<rng model='virtio'>
|
||||
<backend model='builtin'/>
|
||||
</rng>
|
||||
</devices>
|
||||
</domain>
|
@ -1,26 +0,0 @@
|
||||
<domain type='bhyve'>
|
||||
<name>bhyve</name>
|
||||
<uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
|
||||
<memory>219136</memory>
|
||||
<vcpu>1</vcpu>
|
||||
<os>
|
||||
<type>hvm</type>
|
||||
</os>
|
||||
<devices>
|
||||
<disk type='file'>
|
||||
<driver name='file' type='raw'/>
|
||||
<source file='/tmp/freebsd.img'/>
|
||||
<target dev='hda' bus='sata'/>
|
||||
<address type='drive' controller='0' bus='0' target='2' unit='0'/>
|
||||
</disk>
|
||||
<interface type='bridge'>
|
||||
<mac address='52:54:00:b9:94:02'/>
|
||||
<model type='virtio'/>
|
||||
<source bridge="virbr0"/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
</interface>
|
||||
<rng model='virtio'>
|
||||
<backend model='random'>/random/dev</backend>
|
||||
</rng>
|
||||
</devices>
|
||||
</domain>
|
@ -1,26 +0,0 @@
|
||||
<domain type='bhyve'>
|
||||
<name>bhyve</name>
|
||||
<uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
|
||||
<memory>219136</memory>
|
||||
<vcpu>1</vcpu>
|
||||
<os>
|
||||
<type>hvm</type>
|
||||
</os>
|
||||
<devices>
|
||||
<disk type='file'>
|
||||
<driver name='file' type='raw'/>
|
||||
<source file='/tmp/freebsd.img'/>
|
||||
<target dev='hda' bus='sata'/>
|
||||
<address type='drive' controller='0' bus='0' target='2' unit='0'/>
|
||||
</disk>
|
||||
<interface type='bridge'>
|
||||
<mac address='52:54:00:b9:94:02'/>
|
||||
<model type='virtio'/>
|
||||
<source bridge="virbr0"/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
</interface>
|
||||
<rng model='virtio-transitional'>
|
||||
<backend model='random'/>
|
||||
</rng>
|
||||
</devices>
|
||||
</domain>
|
@ -1,11 +0,0 @@
|
||||
bhyve \
|
||||
-c 1 \
|
||||
-m 214 \
|
||||
-u \
|
||||
-H \
|
||||
-P \
|
||||
-s 0:0,hostbridge \
|
||||
-s 2:0,ahci,hd:/tmp/freebsd.img \
|
||||
-s 3:0,virtio-net,faketapdev,mac=52:54:00:b9:94:02 \
|
||||
-s 4:0,virtio-rnd \
|
||||
bhyve
|
@ -1,4 +0,0 @@
|
||||
bhyveload \
|
||||
-m 214 \
|
||||
-d /tmp/freebsd.img \
|
||||
bhyve
|
@ -1,26 +0,0 @@
|
||||
<domain type='bhyve'>
|
||||
<name>bhyve</name>
|
||||
<uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
|
||||
<memory>219136</memory>
|
||||
<vcpu>1</vcpu>
|
||||
<os>
|
||||
<type>hvm</type>
|
||||
</os>
|
||||
<devices>
|
||||
<disk type='file'>
|
||||
<driver name='file' type='raw'/>
|
||||
<source file='/tmp/freebsd.img'/>
|
||||
<target dev='hda' bus='sata'/>
|
||||
<address type='drive' controller='0' bus='0' target='2' unit='0'/>
|
||||
</disk>
|
||||
<interface type='bridge'>
|
||||
<mac address='52:54:00:b9:94:02'/>
|
||||
<model type='virtio'/>
|
||||
<source bridge="virbr0"/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
</interface>
|
||||
<rng model='virtio'>
|
||||
<backend model='random'/>
|
||||
</rng>
|
||||
</devices>
|
||||
</domain>
|
@ -243,12 +243,6 @@ mymain(void)
|
||||
DO_TEST_FAILURE("fs-9p-unsupported-accessmode");
|
||||
driver.bhyvecaps &= ~BHYVE_CAP_VIRTIO_9P;
|
||||
DO_TEST_FAILURE("fs-9p");
|
||||
DO_TEST("virtio-rnd");
|
||||
DO_TEST_FAILURE("virtio-rnd-backend-random-non-default-file");
|
||||
DO_TEST_FAILURE("virtio-rnd-backend-builtin");
|
||||
DO_TEST_FAILURE("virtio-rnd-transitional");
|
||||
driver.bhyvecaps &= ~BHYVE_CAP_VIRTIO_RND;
|
||||
DO_TEST_FAILURE("virtio-rnd");
|
||||
|
||||
/* Address allocation tests */
|
||||
DO_TEST("addr-single-sata-disk");
|
||||
|
@ -1,37 +0,0 @@
|
||||
<domain type='bhyve'>
|
||||
<name>bhyve</name>
|
||||
<uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
|
||||
<memory unit='KiB'>219136</memory>
|
||||
<currentMemory unit='KiB'>219136</currentMemory>
|
||||
<vcpu placement='static'>1</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64'>hvm</type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='file' type='raw'/>
|
||||
<source file='/tmp/freebsd.img'/>
|
||||
<target dev='hda' bus='sata'/>
|
||||
<address type='drive' controller='0' bus='0' target='2' unit='0'/>
|
||||
</disk>
|
||||
<controller type='pci' index='0' model='pci-root'/>
|
||||
<controller type='sata' index='0'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||
</controller>
|
||||
<interface type='bridge'>
|
||||
<mac address='52:54:00:b9:94:02'/>
|
||||
<source bridge='virbr0'/>
|
||||
<model type='virtio'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
</interface>
|
||||
<rng model='virtio'>
|
||||
<backend model='random'>/dev/random</backend>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
||||
</rng>
|
||||
</devices>
|
||||
</domain>
|
@ -114,7 +114,6 @@ mymain(void)
|
||||
DO_TEST_DIFFERENT("sound");
|
||||
DO_TEST_DIFFERENT("isa-controller");
|
||||
DO_TEST_DIFFERENT("fs-9p");
|
||||
DO_TEST_DIFFERENT("virtio-rnd");
|
||||
|
||||
/* Address allocation tests */
|
||||
DO_TEST_DIFFERENT("addr-single-sata-disk");
|
||||
|
@ -408,34 +408,6 @@ cpuTestHasFeature(const void *arg)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cpuTestValidateFeatures(const void *arg)
|
||||
{
|
||||
const struct data *data = arg;
|
||||
g_autoptr(virCPUDef) cpu = NULL;
|
||||
int result;
|
||||
|
||||
if (!(cpu = cpuTestLoadXML(data->arch, data->name)))
|
||||
return -1;
|
||||
|
||||
result = virCPUValidateFeatures(data->arch, cpu);
|
||||
|
||||
if (data->result == -1)
|
||||
virResetLastError();
|
||||
|
||||
if (data->result != result) {
|
||||
VIR_TEST_VERBOSE("\nExpected result %s, got %s",
|
||||
cpuTestBoolWithErrorStr(data->result),
|
||||
cpuTestBoolWithErrorStr(result));
|
||||
/* Pad to line up with test name ... in virTestRun */
|
||||
VIR_TEST_VERBOSE("%74s", "... ");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef enum {
|
||||
/* No JSON data from QEMU. */
|
||||
JSON_NONE,
|
||||
@ -1014,10 +986,6 @@ mymain(void)
|
||||
host "/" feature " (" #result ")", \
|
||||
host, feature, NULL, 0, NULL, 0, result)
|
||||
|
||||
#define DO_TEST_VALIDATEFEATURES(arch, name, result) \
|
||||
DO_TEST(arch, cpuTestValidateFeatures, name, \
|
||||
NULL, name, NULL, 0, NULL, 0, result)
|
||||
|
||||
#define DO_TEST_GUESTCPU(arch, host, cpu, models, result) \
|
||||
DO_TEST(arch, cpuTestGuestCPU, \
|
||||
host "/" cpu " (" #models ")", \
|
||||
@ -1267,9 +1235,6 @@ mymain(void)
|
||||
"Xeon-E5-2609-v3", "Xeon-E5-2650-v4");
|
||||
DO_TEST_CPUID_BASELINE(VIR_ARCH_X86_64, "Haswell+Skylake",
|
||||
"Xeon-E7-8890-v3", "Xeon-Gold-5115");
|
||||
|
||||
DO_TEST_VALIDATEFEATURES(VIR_ARCH_AARCH64, "guest", 0);
|
||||
|
||||
cleanup:
|
||||
#if WITH_QEMU
|
||||
qemuTestDriverFree(&driver);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user