]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer/Machine.pm
schema: fix description of migrate_downtime parameter
[qemu-server.git] / PVE / QemuServer / Machine.pm
CommitLineData
3392d6ca
SR
1package PVE::QemuServer::Machine;
2
3use strict;
4use warnings;
5
2ea5fb7e 6use PVE::QemuServer::Helpers;
3392d6ca 7use PVE::QemuServer::Monitor;
43569a32 8use PVE::JSONSchema qw(get_standard_option parse_property_string print_property_string);
3392d6ca 9
9471e48b
TL
10# Bump this for VM HW layout changes during a release (where the QEMU machine
11# version stays the same)
ac0077cc 12our $PVE_MACHINE_VERSION = {
b8fb1c03 13 '4.1' => 2,
ac0077cc 14};
9471e48b 15
8082eb8c
MF
16my $machine_fmt = {
17 type => {
18 default_key => 1,
19 description => "Specifies the QEMU machine type.",
20 type => 'string',
21 pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|virt(?:-\d+(\.\d+)+)?(\+pve\d+)?)',
22 maxLength => 40,
23 format_description => 'machine type',
24 optional => 1,
25 },
2db4c272
MF
26 viommu => {
27 type => 'string',
28 description => "Enable and set guest vIOMMU variant (Intel vIOMMU needs q35 to be set as"
29 ." machine type).",
30 enum => ['intel', 'virtio'],
31 optional => 1,
32 },
8082eb8c
MF
33};
34
35PVE::JSONSchema::register_format('pve-qemu-machine-fmt', $machine_fmt);
36
37PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
2db4c272 38 description => "Specify the QEMU machine.",
8082eb8c
MF
39 type => 'string',
40 optional => 1,
41 format => PVE::JSONSchema::get_format('pve-qemu-machine-fmt'),
42});
43
44sub parse_machine {
45 my ($value) = @_;
46
47 return if !$value;
48
49 my $res = parse_property_string($machine_fmt, $value);
50 return $res;
51}
52
53sub print_machine {
54 my ($machine_conf) = @_;
55 return print_property_string($machine_conf, $machine_fmt);
56}
57
2db4c272
MF
58sub assert_valid_machine_property {
59 my ($conf, $machine_conf) = @_;
60 my $q35 = $machine_conf->{type} && ($machine_conf->{type} =~ m/q35/) ? 1 : 0;
61 if ($machine_conf->{viommu} && $machine_conf->{viommu} eq "intel" && !$q35) {
62 die "to use Intel vIOMMU please set the machine type to q35\n";
63 }
64}
65
3392d6ca
SR
66sub machine_type_is_q35 {
67 my ($conf) = @_;
68
8082eb8c
MF
69 my $machine_conf = parse_machine($conf->{machine});
70 return $machine_conf->{type} && ($machine_conf->{type} =~ m/q35/) ? 1 : 0;
3392d6ca
SR
71}
72
da841554 73# In list context, also returns whether the current machine is deprecated or not.
ea71be24 74sub current_from_query_machines {
081eed3b 75 my ($machines) = @_;
3392d6ca 76
7d6a6292 77 my ($current, $default);
081eed3b
FE
78 for my $machine ($machines->@*) {
79 $default = $machine->{name} if $machine->{'is-default'};
3392d6ca 80
7d6a6292
FE
81 if ($machine->{'is-current'}) {
82 $current = $machine->{name};
83 # pve-version only exists for the current machine
84 $current .= "+$machine->{'pve-version'}" if $machine->{'pve-version'};
da841554 85 return wantarray ? ($current, $machine->{deprecated} ? 1 : 0) : $current;
7d6a6292
FE
86 }
87 }
9471e48b 88
da841554
FE
89 # fallback to the default machine if current is not supported by qemu - assume never deprecated
90 my $fallback = $default || 'pc';
91 return wantarray ? ($fallback, 0) : $fallback;
3392d6ca
SR
92}
93
da841554
FE
94# This only works if VM is running.
95# In list context, also returns whether the current machine is deprecated or not.
ea71be24
FE
96sub get_current_qemu_machine {
97 my ($vmid) = @_;
98
99 my $res = PVE::QemuServer::Monitor::mon_cmd($vmid, 'query-machines');
100
101 return current_from_query_machines($res);
102}
103
9471e48b
TL
104# returns a string with major.minor+pve<VERSION>, patch version-part is ignored
105# as it's seldom ressembling a real QEMU machine type, so it would be '0' 99% of
106# the time anyway.. This explicitly separates pveversion from the machine.
2ea5fb7e 107sub extract_version {
9471e48b
TL
108 my ($machine_type, $kvmversion) = @_;
109
d4be7f31
SR
110 if (defined($machine_type) && $machine_type =~
111 m/^(?:pc(?:-i440fx|-q35)?|virt)-(\d+)\.(\d+)(?:\.(\d+))?(\+pve\d+)?(?:\.pxe)?/)
112 {
9471e48b
TL
113 my $versionstr = "$1.$2";
114 $versionstr .= $4 if $4;
115 return $versionstr;
116 } elsif (defined($kvmversion)) {
117 if ($kvmversion =~ m/^(\d+)\.(\d+)/) {
ac0077cc
SR
118 my $pvever = get_pve_version($kvmversion);
119 return "$1.$2+pve$pvever";
9471e48b 120 }
3392d6ca
SR
121 }
122
d1c1af4b 123 return;
3392d6ca
SR
124}
125
2ea5fb7e 126sub machine_version {
9471e48b 127 my ($machine_type, $major, $minor, $pve) = @_;
3392d6ca 128
2ea5fb7e 129 return PVE::QemuServer::Helpers::min_version(
9471e48b 130 extract_version($machine_type), $major, $minor, $pve);
3392d6ca
SR
131}
132
ac0077cc
SR
133sub get_pve_version {
134 my ($verstr) = @_;
135
136 if ($verstr =~ m/^(\d+\.\d+)/) {
137 return $PVE_MACHINE_VERSION->{$1} // 0;
138 }
139
140 die "internal error: cannot get pve version for invalid string '$verstr'";
141}
142
143sub can_run_pve_machine_version {
144 my ($machine_version, $kvmversion) = @_;
145
d4be7f31 146 $machine_version =~ m/^(\d+)\.(\d+)(?:\+pve(\d+))?(?:\.pxe)?$/;
ac0077cc
SR
147 my $major = $1;
148 my $minor = $2;
149 my $pvever = $3;
150
151 $kvmversion =~ m/(\d+)\.(\d+)/;
152 return 0 if PVE::QemuServer::Helpers::version_cmp($1, $major, $2, $minor) < 0;
153
154 # if $pvever is missing or 0, we definitely support it as long as we didn't
155 # fail the QEMU version check above
156 return 1 if !$pvever;
157
158 my $max_supported = get_pve_version("$major.$minor");
159 return 1 if $max_supported >= $pvever;
160
161 return 0;
162}
163
3392d6ca
SR
164# dies if a) VM not running or not exisiting b) Version query failed
165# So, any defined return value is valid, any invalid state can be caught by eval
166sub runs_at_least_qemu_version {
167 my ($vmid, $major, $minor, $extra) = @_;
168
169 my $v = PVE::QemuServer::Monitor::mon_cmd($vmid, 'query-version');
170 die "could not query currently running version for VM $vmid\n" if !defined($v);
171 $v = $v->{qemu};
172
825ae5bc 173 return PVE::QemuServer::Helpers::version_cmp($v->{major}, $major, $v->{minor}, $minor, $v->{micro}, $extra) >= 0;
3392d6ca
SR
174}
175
176sub qemu_machine_pxe {
177 my ($vmid, $conf) = @_;
178
179 my $machine = get_current_qemu_machine($vmid);
180
8082eb8c
MF
181 my $machine_conf = parse_machine($conf->{machine});
182 if ($machine_conf->{type} && $machine_conf->{type} =~ m/\.pxe$/) {
3392d6ca
SR
183 $machine .= '.pxe';
184 }
185
186 return $machine;
187}
188
1891;