]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
Use default values from load_defaults() when none is specified in conf
[qemu-server.git] / PVE / QemuServer.pm
CommitLineData
1e3baf05
DM
1package PVE::QemuServer;
2
3use strict;
990fc5e2 4use warnings;
1e3baf05
DM
5use POSIX;
6use IO::Handle;
7use IO::Select;
8use IO::File;
9use IO::Dir;
10use IO::Socket::UNIX;
11use File::Basename;
12use File::Path;
13use File::stat;
14use Getopt::Long;
fc1ddcdc 15use Digest::SHA;
1e3baf05
DM
16use Fcntl ':flock';
17use Cwd 'abs_path';
18use IPC::Open3;
c971c4f2 19use JSON;
1e3baf05
DM
20use Fcntl;
21use PVE::SafeSyslog;
22use Storable qw(dclone);
23use PVE::Exception qw(raise raise_param_exc);
24use PVE::Storage;
4543ecf0 25use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
b7ba6b79 26use PVE::JSONSchema qw(get_standard_option);
1e3baf05
DM
27use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
28use PVE::INotify;
29use PVE::ProcFSTools;
ffda963f 30use PVE::QemuConfig;
26f11676 31use PVE::QMPClient;
91bd6c90 32use PVE::RPCEnvironment;
de9768f0 33use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr);
3f669af2 34use PVE::QemuServer::Memory;
d40e5e18 35use PVE::QemuServer::USB qw(parse_usb_device);
6b64503e 36use Time::HiRes qw(gettimeofday);
a783c78e 37use File::Copy qw(copy);
46630a5f 38use URI::Escape;
1e3baf05 39
2ddc0a5c
DC
40my $OVMF_CODE = '/usr/share/kvm/OVMF_CODE-pure-efi.fd';
41my $OVMF_VARS = '/usr/share/kvm/OVMF_VARS-pure-efi.fd';
2ddc0a5c 42
e5eaa028
WL
43my $qemu_snap_storage = {rbd => 1, sheepdog => 1};
44
7f0b5beb 45my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
1e3baf05 46
19672434 47# Note about locking: we use flock on the config file protect
1e3baf05
DM
48# against concurent actions.
49# Aditionaly, we have a 'lock' setting in the config file. This
22c377f0 50# can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
1e3baf05
DM
51# allowed when such lock is set. But you can ignore this kind of
52# lock with the --skiplock flag.
53
97d62eb7 54cfs_register_file('/qemu-server/',
1858638f
DM
55 \&parse_vm_config,
56 \&write_vm_config);
1e3baf05 57
3ea94c60
DM
58PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
59 description => "Some command save/restore state from this location.",
60 type => 'string',
61 maxLength => 128,
62 optional => 1,
63});
64
8abd398b
DM
65PVE::JSONSchema::register_standard_option('pve-snapshot-name', {
66 description => "The name of the snapshot.",
67 type => 'string', format => 'pve-configid',
68 maxLength => 40,
69});
70
c7d2b650
DM
71PVE::JSONSchema::register_standard_option('pve-qm-image-format', {
72 type => 'string',
73 enum => [qw(raw cow qcow qed qcow2 vmdk cloop)],
74 description => "The drive's backing file's data format.",
75 optional => 1,
76});
77
1e3baf05
DM
78#no warnings 'redefine';
79
c8effec3
AD
80sub cgroups_write {
81 my ($controller, $vmid, $option, $value) = @_;
82
3a515a88
DM
83 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
84 PVE::ProcFSTools::write_proc_entry($path, $value);
c8effec3
AD
85
86}
87
1e3baf05
DM
88my $nodename = PVE::INotify::nodename();
89
90mkdir "/etc/pve/nodes/$nodename";
91my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
92mkdir $confdir;
93
94my $var_run_tmpdir = "/var/run/qemu-server";
95mkdir $var_run_tmpdir;
96
97my $lock_dir = "/var/lock/qemu-server";
98mkdir $lock_dir;
99
100my $pcisysfs = "/sys/bus/pci";
101
8930da74
DM
102my $cpu_vendor_list = {
103 # Intel CPUs
104 486 => 'GenuineIntel',
105 pentium => 'GenuineIntel',
106 pentium2 => 'GenuineIntel',
107 pentium3 => 'GenuineIntel',
108 coreduo => 'GenuineIntel',
109 core2duo => 'GenuineIntel',
110 Conroe => 'GenuineIntel',
111 Penryn => 'GenuineIntel',
112 Nehalem => 'GenuineIntel',
113 Westmere => 'GenuineIntel',
114 SandyBridge => 'GenuineIntel',
115 IvyBridge => 'GenuineIntel',
116 Haswell => 'GenuineIntel',
117 'Haswell-noTSX' => 'GenuineIntel',
118 Broadwell => 'GenuineIntel',
119 'Broadwell-noTSX' => 'GenuineIntel',
3db920fc 120 'Skylake-Client' => 'GenuineIntel',
8930da74
DM
121
122 # AMD CPUs
123 athlon => 'AuthenticAMD',
124 phenom => 'AuthenticAMD',
125 Opteron_G1 => 'AuthenticAMD',
126 Opteron_G2 => 'AuthenticAMD',
127 Opteron_G3 => 'AuthenticAMD',
128 Opteron_G4 => 'AuthenticAMD',
129 Opteron_G5 => 'AuthenticAMD',
130
131 # generic types, use vendor from host node
132 host => 'default',
133 kvm32 => 'default',
134 kvm64 => 'default',
135 qemu32 => 'default',
136 qemu64 => 'default',
137};
138
ff6ffe20 139my $cpu_fmt = {
16a91d65
WB
140 cputype => {
141 description => "Emulated CPU type.",
142 type => 'string',
7f694a71 143 enum => [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
16a91d65
WB
144 default => 'kvm64',
145 default_key => 1,
146 },
147 hidden => {
148 description => "Do not identify as a KVM virtual machine.",
149 type => 'boolean',
150 optional => 1,
151 default => 0
152 },
153};
154
ec3582b5
WB
155my $watchdog_fmt = {
156 model => {
157 default_key => 1,
158 type => 'string',
159 enum => [qw(i6300esb ib700)],
160 description => "Watchdog type to emulate.",
161 default => 'i6300esb',
162 optional => 1,
163 },
164 action => {
165 type => 'string',
166 enum => [qw(reset shutdown poweroff pause debug none)],
167 description => "The action to perform if after activation the guest fails to poll the watchdog in time.",
168 optional => 1,
169 },
170};
171PVE::JSONSchema::register_format('pve-qm-watchdog', $watchdog_fmt);
172
1e3baf05
DM
173my $confdesc = {
174 onboot => {
175 optional => 1,
176 type => 'boolean',
177 description => "Specifies whether a VM will be started during system bootup.",
178 default => 0,
179 },
180 autostart => {
181 optional => 1,
182 type => 'boolean',
183 description => "Automatic restart after crash (currently ignored).",
184 default => 0,
185 },
2ff09f52
DA
186 hotplug => {
187 optional => 1,
b3c2bdd1
DM
188 type => 'string', format => 'pve-hotplug-features',
189 description => "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
190 default => 'network,disk,usb',
2ff09f52 191 },
1e3baf05
DM
192 reboot => {
193 optional => 1,
194 type => 'boolean',
195 description => "Allow reboot. If set to '0' the VM exit on reboot.",
196 default => 1,
197 },
198 lock => {
199 optional => 1,
200 type => 'string',
201 description => "Lock/unlock the VM.",
22c377f0 202 enum => [qw(migrate backup snapshot rollback)],
1e3baf05
DM
203 },
204 cpulimit => {
205 optional => 1,
c6f773b8 206 type => 'number',
52261945
DM
207 description => "Limit of CPU usage.",
208 verbose_description => "Limit of CPU usage.\n\nNOTE: If the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
1e3baf05 209 minimum => 0,
c6f773b8 210 maximum => 128,
52261945 211 default => 0,
1e3baf05
DM
212 },
213 cpuunits => {
214 optional => 1,
215 type => 'integer',
52261945 216 description => "CPU weight for a VM.",
237239bf
PA
217 verbose_description => "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.",
218 minimum => 2,
219 maximum => 262144,
613d76a1 220 default => 1024,
1e3baf05
DM
221 },
222 memory => {
223 optional => 1,
224 type => 'integer',
7878afeb 225 description => "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
1e3baf05
DM
226 minimum => 16,
227 default => 512,
228 },
13a48620
DA
229 balloon => {
230 optional => 1,
231 type => 'integer',
8b1accf7
DM
232 description => "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
233 minimum => 0,
234 },
235 shares => {
236 optional => 1,
237 type => 'integer',
238 description => "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
239 minimum => 0,
240 maximum => 50000,
241 default => 1000,
13a48620 242 },
1e3baf05
DM
243 keyboard => {
244 optional => 1,
245 type => 'string',
aea47dd6
DC
246 description => "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.".
247 "It should not be necessary to set it.",
e95fe75f 248 enum => PVE::Tools::kvmkeymaplist(),
aea47dd6 249 default => undef,
1e3baf05
DM
250 },
251 name => {
252 optional => 1,
7fabe17d 253 type => 'string', format => 'dns-name',
1e3baf05
DM
254 description => "Set a name for the VM. Only used on the configuration web interface.",
255 },
cdd20088
AD
256 scsihw => {
257 optional => 1,
258 type => 'string',
52261945 259 description => "SCSI controller model",
6731a4cf 260 enum => [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
cdd20088
AD
261 default => 'lsi',
262 },
1e3baf05
DM
263 description => {
264 optional => 1,
265 type => 'string',
0581fe4f 266 description => "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
1e3baf05
DM
267 },
268 ostype => {
269 optional => 1,
270 type => 'string',
0cb9971e 271 enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 win10 l24 l26 solaris)],
52261945
DM
272 description => "Specify guest operating system.",
273 verbose_description => <<EODESC,
274Specify guest operating system. This is used to enable special
275optimization/features for specific operating systems:
276
277[horizontal]
278other;; unspecified OS
279wxp;; Microsoft Windows XP
280w2k;; Microsoft Windows 2000
281w2k3;; Microsoft Windows 2003
282w2k8;; Microsoft Windows 2008
283wvista;; Microsoft Windows Vista
284win7;; Microsoft Windows 7
44c2a647
TL
285win8;; Microsoft Windows 8/2012/2012r2
286win10;; Microsoft Windows 10/2016
52261945
DM
287l24;; Linux 2.4 Kernel
288l26;; Linux 2.6/3.X Kernel
289solaris;; Solaris/OpenSolaris/OpenIndiania kernel
1e3baf05
DM
290EODESC
291 },
292 boot => {
293 optional => 1,
294 type => 'string',
295 description => "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
296 pattern => '[acdn]{1,4}',
32baffb4 297 default => 'cdn',
1e3baf05
DM
298 },
299 bootdisk => {
300 optional => 1,
301 type => 'string', format => 'pve-qm-bootdisk',
302 description => "Enable booting from specified disk.",
03e480fc 303 pattern => '(ide|sata|scsi|virtio)\d+',
1e3baf05
DM
304 },
305 smp => {
306 optional => 1,
307 type => 'integer',
308 description => "The number of CPUs. Please use option -sockets instead.",
309 minimum => 1,
310 default => 1,
311 },
312 sockets => {
313 optional => 1,
314 type => 'integer',
315 description => "The number of CPU sockets.",
316 minimum => 1,
317 default => 1,
318 },
319 cores => {
320 optional => 1,
321 type => 'integer',
322 description => "The number of cores per socket.",
323 minimum => 1,
324 default => 1,
325 },
8a010eae
AD
326 numa => {
327 optional => 1,
328 type => 'boolean',
1917695c 329 description => "Enable/disable NUMA.",
8a010eae
AD
330 default => 0,
331 },
7023f3ea
AD
332 hugepages => {
333 optional => 1,
334 type => 'string',
335 description => "Enable/disable hugepages memory.",
336 enum => [qw(any 2 1024)],
337 },
de9d1e55 338 vcpus => {
3bd18e48
AD
339 optional => 1,
340 type => 'integer',
de9d1e55 341 description => "Number of hotplugged vcpus.",
3bd18e48 342 minimum => 1,
de9d1e55 343 default => 0,
3bd18e48 344 },
1e3baf05
DM
345 acpi => {
346 optional => 1,
347 type => 'boolean',
348 description => "Enable/disable ACPI.",
349 default => 1,
350 },
bc84dcca 351 agent => {
ab6a046f
AD
352 optional => 1,
353 type => 'boolean',
354 description => "Enable/disable Qemu GuestAgent.",
be79c214 355 default => 0,
ab6a046f 356 },
1e3baf05
DM
357 kvm => {
358 optional => 1,
359 type => 'boolean',
360 description => "Enable/disable KVM hardware virtualization.",
361 default => 1,
362 },
363 tdf => {
364 optional => 1,
365 type => 'boolean',
8c559505
DM
366 description => "Enable/disable time drift fix.",
367 default => 0,
1e3baf05 368 },
19672434 369 localtime => {
1e3baf05
DM
370 optional => 1,
371 type => 'boolean',
372 description => "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
373 },
374 freeze => {
375 optional => 1,
376 type => 'boolean',
377 description => "Freeze CPU at startup (use 'c' monitor command to start execution).",
378 },
379 vga => {
380 optional => 1,
381 type => 'string',
52261945
DM
382 description => "Select the VGA type.",
383 verbose_description => "Select the VGA type. If you want to use high resolution" .
1917695c
TL
384 " modes (>= 1280x1024x16) then you should use the options " .
385 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
386 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
387 "display sever. For win* OS you can select how many independent " .
388 "displays you want, Linux guests can add displays them self. " .
389 "You can also run without any graphic card, using a serial device" .
390 " as terminal.",
2fa3151e 391 enum => [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
1e3baf05 392 },
0ea9541d
DM
393 watchdog => {
394 optional => 1,
395 type => 'string', format => 'pve-qm-watchdog',
52261945
DM
396 description => "Create a virtual hardware watchdog device.",
397 verbose_description => "Create a virtual hardware watchdog device. Once enabled" .
1917695c
TL
398 " (by a guest action), the watchdog must be periodically polled " .
399 "by an agent inside the guest or else the watchdog will reset " .
400 "the guest (or execute the respective action specified)",
0ea9541d 401 },
1e3baf05
DM
402 startdate => {
403 optional => 1,
19672434 404 type => 'string',
1e3baf05
DM
405 typetext => "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
406 description => "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
407 pattern => '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
408 default => 'now',
409 },
43574f73 410 startup => get_standard_option('pve-startup-order'),
68eda3ab
AD
411 template => {
412 optional => 1,
413 type => 'boolean',
414 description => "Enable/disable Template.",
415 default => 0,
416 },
1e3baf05
DM
417 args => {
418 optional => 1,
419 type => 'string',
52261945
DM
420 description => "Arbitrary arguments passed to kvm.",
421 verbose_description => <<EODESCR,
c7a8aad6 422Arbitrary arguments passed to kvm, for example:
1e3baf05
DM
423
424args: -no-reboot -no-hpet
c7a8aad6
FG
425
426NOTE: this option is for experts only.
1e3baf05
DM
427EODESCR
428 },
429 tablet => {
430 optional => 1,
431 type => 'boolean',
432 default => 1,
52261945
DM
433 description => "Enable/disable the USB tablet device.",
434 verbose_description => "Enable/disable the USB tablet device. This device is " .
1917695c
TL
435 "usually needed to allow absolute mouse positioning with VNC. " .
436 "Else the mouse runs out of sync with normal VNC clients. " .
437 "If you're running lots of console-only guests on one host, " .
438 "you may consider disabling this to save some context switches. " .
439 "This is turned off by default if you use spice (-vga=qxl).",
1e3baf05
DM
440 },
441 migrate_speed => {
442 optional => 1,
443 type => 'integer',
444 description => "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
445 minimum => 0,
446 default => 0,
447 },
448 migrate_downtime => {
449 optional => 1,
04432191 450 type => 'number',
1e3baf05
DM
451 description => "Set maximum tolerated downtime (in seconds) for migrations.",
452 minimum => 0,
04432191 453 default => 0.1,
1e3baf05
DM
454 },
455 cdrom => {
456 optional => 1,
b799312f 457 type => 'string', format => 'pve-qm-ide',
8485b9ba 458 typetext => '<volume>',
1e3baf05
DM
459 description => "This is an alias for option -ide2",
460 },
461 cpu => {
462 optional => 1,
463 description => "Emulated CPU type.",
464 type => 'string',
ff6ffe20 465 format => $cpu_fmt,
1e3baf05 466 },
b7ba6b79
DM
467 parent => get_standard_option('pve-snapshot-name', {
468 optional => 1,
469 description => "Parent snapshot name. This is used internally, and should not be modified.",
470 }),
982c7f12
DM
471 snaptime => {
472 optional => 1,
473 description => "Timestamp for snapshots.",
474 type => 'integer',
475 minimum => 0,
476 },
18bfb361
DM
477 vmstate => {
478 optional => 1,
479 type => 'string', format => 'pve-volume-id',
480 description => "Reference to a volume which stores the VM state. This is used internally for snapshots.",
481 },
253624c7
FG
482 vmstatestorage => get_standard_option('pve-storage-id', {
483 description => "Default storage for VM state volumes/files.",
484 optional => 1,
485 }),
3bafc510
DM
486 machine => {
487 description => "Specific the Qemu machine type.",
488 type => 'string',
7bac824e 489 pattern => '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
3bafc510
DM
490 maxLength => 40,
491 optional => 1,
492 },
2796e7d5
DM
493 smbios1 => {
494 description => "Specify SMBIOS type 1 fields.",
495 type => 'string', format => 'pve-qm-smbios1',
2796e7d5
DM
496 maxLength => 256,
497 optional => 1,
498 },
cb0e4540
AG
499 protection => {
500 optional => 1,
501 type => 'boolean',
52261945 502 description => "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
cb0e4540
AG
503 default => 0,
504 },
3edb45e7 505 bios => {
a783c78e 506 optional => 1,
3edb45e7
DM
507 type => 'string',
508 enum => [ qw(seabios ovmf) ],
509 description => "Select BIOS implementation.",
510 default => 'seabios',
a783c78e 511 },
1e3baf05
DM
512};
513
514# what about other qemu settings ?
515#cpu => 'string',
516#machine => 'string',
517#fda => 'file',
518#fdb => 'file',
519#mtdblock => 'file',
520#sd => 'file',
521#pflash => 'file',
522#snapshot => 'bool',
523#bootp => 'file',
524##tftp => 'dir',
525##smb => 'dir',
526#kernel => 'file',
527#append => 'string',
528#initrd => 'file',
529##soundhw => 'string',
530
531while (my ($k, $v) = each %$confdesc) {
532 PVE::JSONSchema::register_standard_option("pve-qm-$k", $v);
533}
534
535my $MAX_IDE_DISKS = 4;
f62db2a4 536my $MAX_SCSI_DISKS = 14;
a2650619 537my $MAX_VIRTIO_DISKS = 16;
cdb0931f 538my $MAX_SATA_DISKS = 6;
1e3baf05 539my $MAX_USB_DEVICES = 5;
5bdcf937 540my $MAX_NETS = 32;
1e3baf05 541my $MAX_UNUSED_DISKS = 8;
5cffb2d2 542my $MAX_HOSTPCI_DEVICES = 4;
bae179aa 543my $MAX_SERIAL_PORTS = 4;
1989a89c 544my $MAX_PARALLEL_PORTS = 3;
2ed5d572
AD
545my $MAX_NUMA = 8;
546
ffc0d8c7
WB
547my $numa_fmt = {
548 cpus => {
549 type => "string",
550 pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
52261945 551 description => "CPUs accessing this NUMA node.",
ffc0d8c7
WB
552 format_description => "id[-id];...",
553 },
554 memory => {
555 type => "number",
52261945 556 description => "Amount of memory this NUMA node provides.",
ffc0d8c7
WB
557 optional => 1,
558 },
559 hostnodes => {
560 type => "string",
561 pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
52261945 562 description => "Host NUMA nodes to use.",
ffc0d8c7
WB
563 format_description => "id[-id];...",
564 optional => 1,
565 },
566 policy => {
567 type => 'string',
568 enum => [qw(preferred bind interleave)],
52261945 569 description => "NUMA allocation policy.",
ffc0d8c7
WB
570 optional => 1,
571 },
572};
573PVE::JSONSchema::register_format('pve-qm-numanode', $numa_fmt);
2ed5d572
AD
574my $numadesc = {
575 optional => 1,
ffc0d8c7 576 type => 'string', format => $numa_fmt,
52261945 577 description => "NUMA topology.",
2ed5d572
AD
578};
579PVE::JSONSchema::register_standard_option("pve-qm-numanode", $numadesc);
580
581for (my $i = 0; $i < $MAX_NUMA; $i++) {
582 $confdesc->{"numa$i"} = $numadesc;
583}
1e3baf05
DM
584
585my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
55034103
KT
586 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
587 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
6b64503e 588my $nic_model_list_txt = join(' ', sort @$nic_model_list);
1e3baf05 589
52261945
DM
590my $net_fmt_bridge_descr = <<__EOD__;
591Bridge to attach the network device to. The Proxmox VE standard bridge
592is called 'vmbr0'.
593
594If you do not specify a bridge, we create a kvm user (NATed) network
595device, which provides DHCP and DNS services. The following addresses
596are used:
597
598 10.0.2.2 Gateway
599 10.0.2.3 DNS Server
600 10.0.2.4 SMB Server
601
602The DHCP server assign addresses to the guest starting from 10.0.2.15.
603__EOD__
604
cd9c34d1
WB
605my $net_fmt = {
606 macaddr => {
607 type => 'string',
608 pattern => qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
52261945 609 description => "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
cd9c34d1
WB
610 format_description => "XX:XX:XX:XX:XX:XX",
611 optional => 1,
612 },
7f694a71
DM
613 model => {
614 type => 'string',
52261945 615 description => "Network Card Model. The 'virtio' model provides the best performance with very low CPU overhead. If your guest does not support this driver, it is usually best to use 'e1000'.",
7f694a71
DM
616 enum => $nic_model_list,
617 default_key => 1,
618 },
619 (map { $_ => { keyAlias => 'model', alias => 'macaddr' }} @$nic_model_list),
cd9c34d1
WB
620 bridge => {
621 type => 'string',
52261945 622 description => $net_fmt_bridge_descr,
cd9c34d1
WB
623 format_description => 'bridge',
624 optional => 1,
625 },
626 queues => {
627 type => 'integer',
628 minimum => 0, maximum => 16,
629 description => 'Number of packet queues to be used on the device.',
cd9c34d1
WB
630 optional => 1,
631 },
632 rate => {
633 type => 'number',
634 minimum => 0,
52261945 635 description => "Rate limit in mbps (megabytes per second) as floating point number.",
cd9c34d1
WB
636 optional => 1,
637 },
638 tag => {
639 type => 'integer',
9f41a659 640 minimum => 1, maximum => 4094,
cd9c34d1 641 description => 'VLAN tag to apply to packets on this interface.',
cd9c34d1
WB
642 optional => 1,
643 },
644 trunks => {
645 type => 'string',
646 pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
647 description => 'VLAN trunks to pass through this interface.',
7f694a71 648 format_description => 'vlanid[;vlanid...]',
cd9c34d1
WB
649 optional => 1,
650 },
651 firewall => {
652 type => 'boolean',
653 description => 'Whether this interface should be protected by the firewall.',
cd9c34d1
WB
654 optional => 1,
655 },
656 link_down => {
657 type => 'boolean',
52261945 658 description => 'Whether this interface should be disconnected (like pulling the plug).',
cd9c34d1
WB
659 optional => 1,
660 },
661};
52261945 662
1e3baf05
DM
663my $netdesc = {
664 optional => 1,
7f694a71 665 type => 'string', format => $net_fmt,
52261945 666 description => "Specify network devices.",
1e3baf05 667};
52261945 668
1e3baf05
DM
669PVE::JSONSchema::register_standard_option("pve-qm-net", $netdesc);
670
671for (my $i = 0; $i < $MAX_NETS; $i++) {
672 $confdesc->{"net$i"} = $netdesc;
673}
674
ffa42b86
DC
675PVE::JSONSchema::register_format('pve-volume-id-or-qm-path', \&verify_volume_id_or_qm_path);
676sub verify_volume_id_or_qm_path {
822c8a07
WB
677 my ($volid, $noerr) = @_;
678
ffa42b86
DC
679 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m|^/|) {
680 return $volid;
681 }
682
683 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
822c8a07
WB
684 $volid = eval { PVE::JSONSchema::check_format('pve-volume-id', $volid, '') };
685 if ($@) {
686 return undef if $noerr;
687 die $@;
688 }
689 return $volid;
690}
691
1e3baf05 692my $drivename_hash;
19672434 693
0541eeb8
WB
694my %drivedesc_base = (
695 volume => { alias => 'file' },
696 file => {
93c0971c 697 type => 'string',
ffa42b86 698 format => 'pve-volume-id-or-qm-path',
0541eeb8
WB
699 default_key => 1,
700 format_description => 'volume',
701 description => "The drive's backing volume.",
702 },
703 media => {
704 type => 'string',
0541eeb8
WB
705 enum => [qw(cdrom disk)],
706 description => "The drive's media type.",
707 default => 'disk',
708 optional => 1
709 },
710 cyls => {
711 type => 'integer',
0541eeb8
WB
712 description => "Force the drive's physical geometry to have a specific cylinder count.",
713 optional => 1
714 },
715 heads => {
716 type => 'integer',
0541eeb8
WB
717 description => "Force the drive's physical geometry to have a specific head count.",
718 optional => 1
719 },
720 secs => {
721 type => 'integer',
0541eeb8
WB
722 description => "Force the drive's physical geometry to have a specific sector count.",
723 optional => 1
724 },
725 trans => {
726 type => 'string',
0541eeb8
WB
727 enum => [qw(none lba auto)],
728 description => "Force disk geometry bios translation mode.",
729 optional => 1,
730 },
731 snapshot => {
732 type => 'boolean',
0541eeb8
WB
733 description => "Whether the drive should be included when making snapshots.",
734 optional => 1,
735 },
736 cache => {
737 type => 'string',
0541eeb8
WB
738 enum => [qw(none writethrough writeback unsafe directsync)],
739 description => "The drive's cache mode",
740 optional => 1,
741 },
c7d2b650 742 format => get_standard_option('pve-qm-image-format'),
0541eeb8 743 size => {
47c28a68
WB
744 type => 'string',
745 format => 'disk-size',
7f694a71 746 format_description => 'DiskSize',
0541eeb8
WB
747 description => "Disk size. This is purely informational and has no effect.",
748 optional => 1,
749 },
750 backup => {
751 type => 'boolean',
0541eeb8
WB
752 description => "Whether the drive should be included when making backups.",
753 optional => 1,
754 },
8557d01f 755 replicate => {
9edac22f 756 type => 'boolean',
3ab7663a 757 description => 'Whether the drive should considered for replication jobs.',
9edac22f
WL
758 optional => 1,
759 default => 1,
760 },
6e9d2550
AD
761 rerror => {
762 type => 'string',
763 enum => [qw(ignore report stop)],
764 description => 'Read error action.',
765 optional => 1,
766 },
0541eeb8
WB
767 werror => {
768 type => 'string',
0541eeb8
WB
769 enum => [qw(enospc ignore report stop)],
770 description => 'Write error action.',
771 optional => 1,
772 },
773 aio => {
774 type => 'string',
0541eeb8
WB
775 enum => [qw(native threads)],
776 description => 'AIO type to use.',
777 optional => 1,
778 },
779 discard => {
780 type => 'string',
0541eeb8
WB
781 enum => [qw(ignore on)],
782 description => 'Controls whether to pass discard/trim requests to the underlying storage.',
783 optional => 1,
784 },
785 detect_zeroes => {
786 type => 'boolean',
787 description => 'Controls whether to detect and try to optimize writes of zeroes.',
788 optional => 1,
789 },
790 serial => {
791 type => 'string',
46630a5f 792 format => 'urlencoded',
0541eeb8 793 format_description => 'serial',
ba8fc5d1
WB
794 maxLength => 20*3, # *3 since it's %xx url enoded
795 description => "The drive's reported serial number, url-encoded, up to 20 bytes long.",
0541eeb8
WB
796 optional => 1,
797 }
798);
799
0541eeb8
WB
800my %iothread_fmt = ( iothread => {
801 type => 'boolean',
0541eeb8
WB
802 description => "Whether to use iothreads for this drive",
803 optional => 1,
804});
805
806my %model_fmt = (
807 model => {
808 type => 'string',
46630a5f 809 format => 'urlencoded',
0541eeb8 810 format_description => 'model',
ba8fc5d1
WB
811 maxLength => 40*3, # *3 since it's %xx url enoded
812 description => "The drive's reported model name, url-encoded, up to 40 bytes long.",
0541eeb8
WB
813 optional => 1,
814 },
815);
816
817my %queues_fmt = (
818 queues => {
819 type => 'integer',
0541eeb8
WB
820 description => "Number of queues.",
821 minimum => 2,
822 optional => 1
823 }
824);
825
8e3c33ab
FG
826my %scsiblock_fmt = (
827 scsiblock => {
828 type => 'boolean',
829 description => "whether to use scsi-block for full passthrough of host block device\n\nWARNING: can lead to I/O errors in combination with low memory or high memory fragmentation on host",
830 optional => 1,
831 default => 0,
832 },
833);
834
0541eeb8 835my $add_throttle_desc = sub {
9196a8ec
WB
836 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
837 my $d = {
0541eeb8 838 type => $type,
7f694a71 839 format_description => $unit,
9196a8ec 840 description => "Maximum $what in $longunit.",
0541eeb8
WB
841 optional => 1,
842 };
9196a8ec
WB
843 $d->{minimum} = $minimum if defined($minimum);
844 $drivedesc_base{$key} = $d;
0541eeb8
WB
845};
846# throughput: (leaky bucket)
d3f3f1b3
DM
847$add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
848$add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
849$add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
850$add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
851$add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
852$add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
853$add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
854$add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
855$add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
0541eeb8
WB
856
857# pools: (pool of IO before throttling starts taking effect)
d3f3f1b3
DM
858$add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
859$add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
860$add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
861$add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
862$add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
863$add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
9196a8ec
WB
864
865# burst lengths
fb8e95a2
WB
866$add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
867$add_throttle_desc->('bps_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
868$add_throttle_desc->('bps_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
869$add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
870$add_throttle_desc->('iops_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
871$add_throttle_desc->('iops_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
872
873# legacy support
874$drivedesc_base{'bps_rd_length'} = { alias => 'bps_rd_max_length' };
875$drivedesc_base{'bps_wr_length'} = { alias => 'bps_wr_max_length' };
876$drivedesc_base{'iops_rd_length'} = { alias => 'iops_rd_max_length' };
877$drivedesc_base{'iops_wr_length'} = { alias => 'iops_wr_max_length' };
0541eeb8
WB
878
879my $ide_fmt = {
880 %drivedesc_base,
0541eeb8
WB
881 %model_fmt,
882};
b799312f 883PVE::JSONSchema::register_format("pve-qm-ide", $ide_fmt);
0541eeb8 884
1e3baf05
DM
885my $idedesc = {
886 optional => 1,
0541eeb8 887 type => 'string', format => $ide_fmt,
3c770faa 888 description => "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
1e3baf05
DM
889};
890PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc);
891
0541eeb8
WB
892my $scsi_fmt = {
893 %drivedesc_base,
894 %iothread_fmt,
895 %queues_fmt,
8e3c33ab 896 %scsiblock_fmt,
0541eeb8 897};
1e3baf05
DM
898my $scsidesc = {
899 optional => 1,
0541eeb8 900 type => 'string', format => $scsi_fmt,
3c770faa 901 description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
1e3baf05
DM
902};
903PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
904
0541eeb8
WB
905my $sata_fmt = {
906 %drivedesc_base,
0541eeb8 907};
cdb0931f
DA
908my $satadesc = {
909 optional => 1,
0541eeb8 910 type => 'string', format => $sata_fmt,
3c770faa 911 description => "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
cdb0931f
DA
912};
913PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc);
914
0541eeb8
WB
915my $virtio_fmt = {
916 %drivedesc_base,
917 %iothread_fmt,
0541eeb8 918};
1e3baf05
DM
919my $virtiodesc = {
920 optional => 1,
0541eeb8 921 type => 'string', format => $virtio_fmt,
3c770faa 922 description => "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
1e3baf05
DM
923};
924PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc);
925
0541eeb8
WB
926my $alldrive_fmt = {
927 %drivedesc_base,
0541eeb8
WB
928 %iothread_fmt,
929 %model_fmt,
930 %queues_fmt,
8e3c33ab 931 %scsiblock_fmt,
0541eeb8
WB
932};
933
6470743f
DC
934my $efidisk_fmt = {
935 volume => { alias => 'file' },
936 file => {
937 type => 'string',
938 format => 'pve-volume-id-or-qm-path',
939 default_key => 1,
940 format_description => 'volume',
941 description => "The drive's backing volume.",
942 },
c7d2b650 943 format => get_standard_option('pve-qm-image-format'),
6470743f
DC
944 size => {
945 type => 'string',
946 format => 'disk-size',
947 format_description => 'DiskSize',
948 description => "Disk size. This is purely informational and has no effect.",
949 optional => 1,
950 },
951};
952
953my $efidisk_desc = {
954 optional => 1,
955 type => 'string', format => $efidisk_fmt,
956 description => "Configure a Disk for storing EFI vars",
957};
958
959PVE::JSONSchema::register_standard_option("pve-qm-efidisk", $efidisk_desc);
960
ff6ffe20 961my $usb_fmt = {
a6b9aee4
DC
962 host => {
963 default_key => 1,
964 type => 'string', format => 'pve-qm-usb-device',
965 format_description => 'HOSTUSBDEVICE|spice',
52261945
DM
966 description => <<EODESCR,
967The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
968
969 'bus-port(.port)*' (decimal numbers) or
970 'vendor_id:product_id' (hexadeciaml numbers) or
971 'spice'
972
973You can use the 'lsusb -t' command to list existing usb devices.
974
975NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
976
977The value 'spice' can be used to add a usb redirection devices for spice.
978EODESCR
a6b9aee4
DC
979 },
980 usb3 => {
981 optional => 1,
982 type => 'boolean',
52261945
DM
983 description => "Specifies whether if given host option is a USB3 device or port (this does currently not work reliably with spice redirection and is then ignored).",
984 default => 0,
a6b9aee4
DC
985 },
986};
987
1e3baf05
DM
988my $usbdesc = {
989 optional => 1,
ff6ffe20 990 type => 'string', format => $usb_fmt,
52261945 991 description => "Configure an USB device (n is 0 to 4).",
1e3baf05
DM
992};
993PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
994
1f4f447b
WB
995# NOTE: the match-groups of this regex are used in parse_hostpci
996my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
997my $hostpci_fmt = {
998 host => {
999 default_key => 1,
1000 type => 'string',
1001 pattern => qr/$PCIRE(;$PCIRE)*/,
1002 format_description => 'HOSTPCIID[;HOSTPCIID2...]',
52261945
DM
1003 description => <<EODESCR,
1004Host PCI device pass through. The PCI ID of a host's PCI device or a list
1005of PCI virtual functions of the host. HOSTPCIID syntax is:
1006
1007'bus:dev.func' (hexadecimal numbers)
1008
1009You can us the 'lspci' command to list existing PCI devices.
52261945 1010EODESCR
1f4f447b
WB
1011 },
1012 rombar => {
1013 type => 'boolean',
52261945 1014 description => "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1f4f447b
WB
1015 optional => 1,
1016 default => 1,
1017 },
456a6fec
AD
1018 romfile => {
1019 type => 'string',
1020 pattern => '[^,;]+',
1021 format_description => 'string',
1022 description => "Custom pci device rom filename (must be located in /usr/share/kvm/).",
1023 optional => 1,
1024 },
1f4f447b
WB
1025 pcie => {
1026 type => 'boolean',
52261945 1027 description => "Choose the PCI-express bus (needs the 'q35' machine model).",
1f4f447b
WB
1028 optional => 1,
1029 default => 0,
1030 },
1031 'x-vga' => {
1032 type => 'boolean',
52261945 1033 description => "Enable vfio-vga device support.",
1f4f447b
WB
1034 optional => 1,
1035 default => 0,
1036 },
1037};
1038PVE::JSONSchema::register_format('pve-qm-hostpci', $hostpci_fmt);
1039
040b06b7
DA
1040my $hostpcidesc = {
1041 optional => 1,
1042 type => 'string', format => 'pve-qm-hostpci',
52261945 1043 description => "Map host PCI devices into guest.",
faab5306
DM
1044 verbose_description => <<EODESCR,
1045Map host PCI devices into guest.
1046
1047NOTE: This option allows direct access to host hardware. So it is no longer
1048possible to migrate such machines - use with special care.
1049
1050CAUTION: Experimental! User reported problems with this option.
1051EODESCR
040b06b7
DA
1052};
1053PVE::JSONSchema::register_standard_option("pve-qm-hostpci", $hostpcidesc);
1054
bae179aa
DA
1055my $serialdesc = {
1056 optional => 1,
ca0cef26 1057 type => 'string',
1b0b51ed 1058 pattern => '(/dev/.+|socket)',
52261945
DM
1059 description => "Create a serial device inside the VM (n is 0 to 3)",
1060 verbose_description => <<EODESCR,
52261945
DM
1061Create a serial device inside the VM (n is 0 to 3), and pass through a
1062host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1063host side (use 'qm terminal' to open a terminal connection).
bae179aa 1064
8a61e0fd 1065NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
bae179aa 1066
52261945 1067CAUTION: Experimental! User reported problems with this option.
bae179aa
DA
1068EODESCR
1069};
bae179aa 1070
1989a89c
DA
1071my $paralleldesc= {
1072 optional => 1,
ca0cef26 1073 type => 'string',
9ecc8431 1074 pattern => '/dev/parport\d+|/dev/usb/lp\d+',
52261945
DM
1075 description => "Map host parallel devices (n is 0 to 2).",
1076 verbose_description => <<EODESCR,
19672434 1077Map host parallel devices (n is 0 to 2).
1989a89c 1078
8a61e0fd 1079NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1989a89c 1080
52261945 1081CAUTION: Experimental! User reported problems with this option.
1989a89c
DA
1082EODESCR
1083};
1989a89c
DA
1084
1085for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1086 $confdesc->{"parallel$i"} = $paralleldesc;
1087}
1088
bae179aa
DA
1089for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1090 $confdesc->{"serial$i"} = $serialdesc;
1091}
1092
040b06b7
DA
1093for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1094 $confdesc->{"hostpci$i"} = $hostpcidesc;
1095}
1e3baf05
DM
1096
1097for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1098 $drivename_hash->{"ide$i"} = 1;
1099 $confdesc->{"ide$i"} = $idedesc;
1100}
1101
cdb0931f
DA
1102for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1103 $drivename_hash->{"sata$i"} = 1;
1104 $confdesc->{"sata$i"} = $satadesc;
1105}
1106
1e3baf05
DM
1107for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1108 $drivename_hash->{"scsi$i"} = 1;
1109 $confdesc->{"scsi$i"} = $scsidesc ;
1110}
1111
1112for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1113 $drivename_hash->{"virtio$i"} = 1;
1114 $confdesc->{"virtio$i"} = $virtiodesc;
1115}
1116
6470743f
DC
1117$drivename_hash->{efidisk0} = 1;
1118$confdesc->{efidisk0} = $efidisk_desc;
1119
1e3baf05
DM
1120for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1121 $confdesc->{"usb$i"} = $usbdesc;
1122}
1123
1124my $unuseddesc = {
1125 optional => 1,
1126 type => 'string', format => 'pve-volume-id',
52261945 1127 description => "Reference to unused volumes. This is used internally, and should not be modified manually.",
1e3baf05
DM
1128};
1129
1130for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1131 $confdesc->{"unused$i"} = $unuseddesc;
1132}
1133
1134my $kvm_api_version = 0;
1135
1136sub kvm_version {
1137
1138 return $kvm_api_version if $kvm_api_version;
1139
6b64503e 1140 my $fh = IO::File->new("</dev/kvm") ||
1e3baf05
DM
1141 return 0;
1142
6b64503e 1143 if (my $v = $fh->ioctl(KVM_GET_API_VERSION(), 0)) {
1e3baf05
DM
1144 $kvm_api_version = $v;
1145 }
1146
1147 $fh->close();
1148
1149 return $kvm_api_version;
1150}
1151
1152my $kvm_user_version;
1153
1154sub kvm_user_version {
1155
1156 return $kvm_user_version if $kvm_user_version;
1157
1158 $kvm_user_version = 'unknown';
1159
09b11429
TL
1160 my $code = sub {
1161 my $line = shift;
1162 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1163 $kvm_user_version = $2;
1164 }
1165 };
19672434 1166
09b11429
TL
1167 eval { run_command("kvm -version", outfunc => $code); };
1168 warn $@ if $@;
1e3baf05
DM
1169
1170 return $kvm_user_version;
1171
1172}
1173
1174my $kernel_has_vhost_net = -c '/dev/vhost-net';
1175
74479ee9 1176sub valid_drive_names {
1e3baf05 1177 # order is important - used to autoselect boot disk
19672434 1178 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1e3baf05 1179 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
cdb0931f 1180 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
6470743f
DC
1181 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1182 'efidisk0');
1e3baf05
DM
1183}
1184
74479ee9 1185sub is_valid_drivename {
1e3baf05
DM
1186 my $dev = shift;
1187
6b64503e 1188 return defined($drivename_hash->{$dev});
1e3baf05
DM
1189}
1190
1191sub option_exists {
1192 my $key = shift;
1193 return defined($confdesc->{$key});
19672434 1194}
1e3baf05
DM
1195
1196sub nic_models {
1197 return $nic_model_list;
1198}
1199
1200sub os_list_description {
1201
1202 return {
1203 other => 'Other',
1204 wxp => 'Windows XP',
1205 w2k => 'Windows 2000',
1206 w2k3 =>, 'Windows 2003',
1207 w2k8 => 'Windows 2008',
1208 wvista => 'Windows Vista',
1209 win7 => 'Windows 7',
a70ebde3 1210 win8 => 'Windows 8/2012',
0cb9971e 1211 win10 => 'Windows 10/2016',
1e3baf05
DM
1212 l24 => 'Linux 2.4',
1213 l26 => 'Linux 2.6',
19672434 1214 };
1e3baf05
DM
1215}
1216
1e3baf05
DM
1217my $cdrom_path;
1218
1219sub get_cdrom_path {
1220
1221 return $cdrom_path if $cdrom_path;
1222
1223 return $cdrom_path = "/dev/cdrom" if -l "/dev/cdrom";
1224 return $cdrom_path = "/dev/cdrom1" if -l "/dev/cdrom1";
1225 return $cdrom_path = "/dev/cdrom2" if -l "/dev/cdrom2";
1226}
1227
1228sub get_iso_path {
1229 my ($storecfg, $vmid, $cdrom) = @_;
1230
1231 if ($cdrom eq 'cdrom') {
1232 return get_cdrom_path();
1233 } elsif ($cdrom eq 'none') {
1234 return '';
1235 } elsif ($cdrom =~ m|^/|) {
1236 return $cdrom;
1237 } else {
6b64503e 1238 return PVE::Storage::path($storecfg, $cdrom);
1e3baf05
DM
1239 }
1240}
1241
1242# try to convert old style file names to volume IDs
1243sub filename_to_volume_id {
1244 my ($vmid, $file, $media) = @_;
1245
1246 if (!($file eq 'none' || $file eq 'cdrom' ||
1247 $file =~ m|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
19672434 1248
1e3baf05 1249 return undef if $file =~ m|/|;
19672434 1250
1e3baf05
DM
1251 if ($media && $media eq 'cdrom') {
1252 $file = "local:iso/$file";
1253 } else {
1254 $file = "local:$vmid/$file";
1255 }
1256 }
1257
1258 return $file;
1259}
1260
1261sub verify_media_type {
1262 my ($opt, $vtype, $media) = @_;
1263
1264 return if !$media;
1265
1266 my $etype;
1267 if ($media eq 'disk') {
a125592c 1268 $etype = 'images';
1e3baf05
DM
1269 } elsif ($media eq 'cdrom') {
1270 $etype = 'iso';
1271 } else {
1272 die "internal error";
1273 }
1274
1275 return if ($vtype eq $etype);
19672434 1276
1e3baf05
DM
1277 raise_param_exc({ $opt => "unexpected media type ($vtype != $etype)" });
1278}
1279
1280sub cleanup_drive_path {
1281 my ($opt, $storecfg, $drive) = @_;
1282
1283 # try to convert filesystem paths to volume IDs
1284
1285 if (($drive->{file} !~ m/^(cdrom|none)$/) &&
1286 ($drive->{file} !~ m|^/dev/.+|) &&
1287 ($drive->{file} !~ m/^([^:]+):(.+)$/) &&
19672434 1288 ($drive->{file} !~ m/^\d+$/)) {
1e3baf05
DM
1289 my ($vtype, $volid) = PVE::Storage::path_to_volume_id($storecfg, $drive->{file});
1290 raise_param_exc({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1291 $drive->{media} = 'cdrom' if !$drive->{media} && $vtype eq 'iso';
1292 verify_media_type($opt, $vtype, $drive->{media});
1293 $drive->{file} = $volid;
1294 }
1295
1296 $drive->{media} = 'cdrom' if !$drive->{media} && $drive->{file} =~ m/^(cdrom|none)$/;
1297}
1298
b3c2bdd1
DM
1299sub parse_hotplug_features {
1300 my ($data) = @_;
1301
1302 my $res = {};
1303
1304 return $res if $data eq '0';
a1b7d579 1305
b3c2bdd1
DM
1306 $data = $confdesc->{hotplug}->{default} if $data eq '1';
1307
45827685 1308 foreach my $feature (PVE::Tools::split_list($data)) {
b3c2bdd1
DM
1309 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1310 $res->{$1} = 1;
1311 } else {
596a0a20 1312 die "invalid hotplug feature '$feature'\n";
b3c2bdd1
DM
1313 }
1314 }
1315 return $res;
1316}
1317
1318PVE::JSONSchema::register_format('pve-hotplug-features', \&pve_verify_hotplug_features);
1319sub pve_verify_hotplug_features {
1320 my ($value, $noerr) = @_;
1321
1322 return $value if parse_hotplug_features($value);
1323
1324 return undef if $noerr;
1325
1326 die "unable to parse hotplug option\n";
1327}
1328
1e3baf05
DM
1329# ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1330# [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
036e0e2b 1331# [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
6e47c3b4
WB
1332# [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1333# [,iothread=on][,serial=serial][,model=model]
1e3baf05
DM
1334
1335sub parse_drive {
1336 my ($key, $data) = @_;
1337
0541eeb8 1338 my ($interface, $index);
19672434 1339
0541eeb8
WB
1340 if ($key =~ m/^([^\d]+)(\d+)$/) {
1341 $interface = $1;
1342 $index = $2;
1e3baf05
DM
1343 } else {
1344 return undef;
1345 }
1346
0541eeb8
WB
1347 my $desc = $key =~ /^unused\d+$/ ? $alldrive_fmt
1348 : $confdesc->{$key}->{format};
1349 if (!$desc) {
1350 warn "invalid drive key: $key\n";
1351 return undef;
1352 }
1353 my $res = eval { PVE::JSONSchema::parse_property_string($desc, $data) };
1354 return undef if !$res;
1355 $res->{interface} = $interface;
1356 $res->{index} = $index;
1357
1358 my $error = 0;
1359 foreach my $opt (qw(bps bps_rd bps_wr)) {
1360 if (my $bps = defined(delete $res->{$opt})) {
1361 if (defined($res->{"m$opt"})) {
1362 warn "both $opt and m$opt specified\n";
1363 ++$error;
1364 next;
1e3baf05 1365 }
0541eeb8 1366 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1e3baf05
DM
1367 }
1368 }
9196a8ec
WB
1369
1370 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1371 for my $requirement (
fb8e95a2
WB
1372 [mbps_max => 'mbps'],
1373 [mbps_rd_max => 'mbps_rd'],
1374 [mbps_wr_max => 'mbps_wr'],
1375 [miops_max => 'miops'],
1376 [miops_rd_max => 'miops_rd'],
1377 [miops_wr_max => 'miops_wr'],
9196a8ec
WB
1378 [bps_max_length => 'mbps_max'],
1379 [bps_rd_max_length => 'mbps_rd_max'],
1380 [bps_wr_max_length => 'mbps_wr_max'],
1381 [iops_max_length => 'iops_max'],
1382 [iops_rd_max_length => 'iops_rd_max'],
1383 [iops_wr_max_length => 'iops_wr_max']) {
1384 my ($option, $requires) = @$requirement;
1385 if ($res->{$option} && !$res->{$requires}) {
1386 warn "$option requires $requires\n";
1387 ++$error;
1388 }
1389 }
1390
0541eeb8 1391 return undef if $error;
be190583 1392
9bf371a6
DM
1393 return undef if $res->{mbps_rd} && $res->{mbps};
1394 return undef if $res->{mbps_wr} && $res->{mbps};
affd2f88
AD
1395 return undef if $res->{iops_rd} && $res->{iops};
1396 return undef if $res->{iops_wr} && $res->{iops};
74edd76b 1397
1e3baf05
DM
1398 if ($res->{media} && ($res->{media} eq 'cdrom')) {
1399 return undef if $res->{snapshot} || $res->{trans} || $res->{format};
19672434 1400 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
1e3baf05
DM
1401 return undef if $res->{interface} eq 'virtio';
1402 }
1403
0541eeb8
WB
1404 if (my $size = $res->{size}) {
1405 return undef if !defined($res->{size} = PVE::JSONSchema::parse_size($size));
1e3baf05
DM
1406 }
1407
1408 return $res;
1409}
1410
1e3baf05
DM
1411sub print_drive {
1412 my ($vmid, $drive) = @_;
0541eeb8
WB
1413 my $data = { %$drive };
1414 delete $data->{$_} for qw(index interface);
1415 return PVE::JSONSchema::print_property_string($data, $alldrive_fmt);
1e3baf05
DM
1416}
1417
28ef82d3
DM
1418sub scsi_inquiry {
1419 my($fh, $noerr) = @_;
1420
1421 my $SG_IO = 0x2285;
1422 my $SG_GET_VERSION_NUM = 0x2282;
1423
1424 my $versionbuf = "\x00" x 8;
1425 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1426 if (!$ret) {
1427 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1428 return undef;
1429 }
97d62eb7 1430 my $version = unpack("I", $versionbuf);
28ef82d3
DM
1431 if ($version < 30000) {
1432 die "scsi generic interface too old\n" if !$noerr;
1433 return undef;
1434 }
97d62eb7 1435
28ef82d3
DM
1436 my $buf = "\x00" x 36;
1437 my $sensebuf = "\x00" x 8;
f334aa3e 1438 my $cmd = pack("C x3 C x1", 0x12, 36);
97d62eb7 1439
28ef82d3
DM
1440 # see /usr/include/scsi/sg.h
1441 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1442
97d62eb7
DM
1443 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1444 length($sensebuf), 0, length($buf), $buf,
28ef82d3
DM
1445 $cmd, $sensebuf, 6000);
1446
1447 $ret = ioctl($fh, $SG_IO, $packet);
1448 if (!$ret) {
1449 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1450 return undef;
1451 }
97d62eb7 1452
28ef82d3
DM
1453 my @res = unpack($sg_io_hdr_t, $packet);
1454 if ($res[17] || $res[18]) {
1455 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1456 return undef;
1457 }
1458
1459 my $res = {};
09984754 1460 (my $byte0, my $byte1, $res->{vendor},
28ef82d3
DM
1461 $res->{product}, $res->{revision}) = unpack("C C x6 A8 A16 A4", $buf);
1462
09984754
DM
1463 $res->{removable} = $byte1 & 128 ? 1 : 0;
1464 $res->{type} = $byte0 & 31;
1465
28ef82d3
DM
1466 return $res;
1467}
1468
1469sub path_is_scsi {
1470 my ($path) = @_;
1471
1472 my $fh = IO::File->new("+<$path") || return undef;
1473 my $res = scsi_inquiry($fh, 1);
1474 close($fh);
1475
1476 return $res;
1477}
1478
db656e5f
DM
1479sub machine_type_is_q35 {
1480 my ($conf) = @_;
b467f79a 1481
db656e5f
DM
1482 return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0;
1483}
1484
1485sub print_tabletdevice_full {
1486 my ($conf) = @_;
b467f79a 1487
db656e5f
DM
1488 my $q35 = machine_type_is_q35($conf);
1489
1490 # we use uhci for old VMs because tablet driver was buggy in older qemu
1491 my $usbbus = $q35 ? "ehci" : "uhci";
b467f79a 1492
db656e5f
DM
1493 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1494}
1495
ca916ecc 1496sub print_drivedevice_full {
5bdcf937 1497 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
ca916ecc
DA
1498
1499 my $device = '';
1500 my $maxdev = 0;
19672434 1501
ca916ecc 1502 if ($drive->{interface} eq 'virtio') {
5bdcf937 1503 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}", $bridges);
2ed36a41 1504 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
51f492cd 1505 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread};
2ed36a41 1506 } elsif ($drive->{interface} eq 'scsi') {
6731a4cf 1507
ee034f5c 1508 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
2ed36a41
DM
1509 my $unit = $drive->{index} % $maxdev;
1510 my $devicetype = 'hd';
69bcf246
WB
1511 my $path = '';
1512 if (drive_is_cdrom($drive)) {
1513 $devicetype = 'cd';
29b19529 1514 } else {
69bcf246
WB
1515 if ($drive->{file} =~ m|^/|) {
1516 $path = $drive->{file};
1517 if (my $info = path_is_scsi($path)) {
8e3c33ab 1518 if ($info->{type} == 0 && $drive->{scsiblock}) {
69bcf246
WB
1519 $devicetype = 'block';
1520 } elsif ($info->{type} == 1) { # tape
1521 $devicetype = 'generic';
1522 }
1523 }
1524 } else {
1525 $path = PVE::Storage::path($storecfg, $drive->{file});
1526 }
1527
1528 if($path =~ m/^iscsi\:\/\//){
1529 $devicetype = 'generic';
1530 }
1531 }
1532
1533 if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)){
1534 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1535 } else {
1536 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1537 }
cdd20088 1538
2ed36a41
DM
1539 } elsif ($drive->{interface} eq 'ide'){
1540 $maxdev = 2;
1541 my $controller = int($drive->{index} / $maxdev);
1542 my $unit = $drive->{index} % $maxdev;
1543 my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
1544
7ebe888a 1545 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
0f2812c2 1546 if ($devicetype eq 'hd' && (my $model = $drive->{model})) {
46630a5f 1547 $model = URI::Escape::uri_unescape($model);
0f2812c2
WB
1548 $device .= ",model=$model";
1549 }
cdb0931f
DA
1550 } elsif ($drive->{interface} eq 'sata'){
1551 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1552 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1553 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
2ed36a41
DM
1554 } elsif ($drive->{interface} eq 'usb') {
1555 die "implement me";
1556 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1557 } else {
1558 die "unsupported interface type";
ca916ecc
DA
1559 }
1560
3b408e82
DM
1561 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
1562
ca916ecc
DA
1563 return $device;
1564}
1565
15b21acc 1566sub get_initiator_name {
46f58b5f 1567 my $initiator;
15b21acc 1568
46f58b5f
DM
1569 my $fh = IO::File->new('/etc/iscsi/initiatorname.iscsi') || return undef;
1570 while (defined(my $line = <$fh>)) {
1571 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
15b21acc
MR
1572 $initiator = $1;
1573 last;
1574 }
46f58b5f
DM
1575 $fh->close();
1576
15b21acc
MR
1577 return $initiator;
1578}
1579
1e3baf05
DM
1580sub print_drive_full {
1581 my ($storecfg, $vmid, $drive) = @_;
1582
d81f0f09
DM
1583 my $path;
1584 my $volid = $drive->{file};
1585 my $format;
1586
1587 if (drive_is_cdrom($drive)) {
1588 $path = get_iso_path($storecfg, $vmid, $volid);
1589 } else {
1590 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
1591 if ($storeid) {
1592 $path = PVE::Storage::path($storecfg, $volid);
1593 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
1594 $format = qemu_img_format($scfg, $volname);
1595 } else {
1596 $path = $volid;
5b61bff2 1597 $format = "raw";
d81f0f09
DM
1598 }
1599 }
1600
1e3baf05 1601 my $opts = '';
fb8e95a2 1602 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard);
1e3baf05
DM
1603 foreach my $o (@qemu_drive_options) {
1604 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
19672434 1605 }
fb8e95a2
WB
1606 foreach my $type (['', '-total'], [_rd => '-read'], [_wr => '-write']) {
1607 my ($dir, $qmpname) = @$type;
1608 if (my $v = $drive->{"mbps$dir"}) {
1609 $opts .= ",throttling.bps$qmpname=".int($v*1024*1024);
1610 }
1611 if (my $v = $drive->{"mbps${dir}_max"}) {
1612 $opts .= ",throttling.bps$qmpname-max=".int($v*1024*1024);
1613 }
1614 if (my $v = $drive->{"bps${dir}_max_length"}) {
1615 $opts .= ",throttling.bps$qmpname-max-length=$v";
1616 }
1617 if (my $v = $drive->{"iops${dir}"}) {
1618 $opts .= ",throttling.iops$qmpname=$v";
1619 }
1620 if (my $v = $drive->{"iops${dir}_max"}) {
8aca1654 1621 $opts .= ",throttling.iops$qmpname-max=$v";
fb8e95a2
WB
1622 }
1623 if (my $v = $drive->{"iops${dir}_max_length"}) {
8aca1654 1624 $opts .= ",throttling.iops$qmpname-max-length=$v";
fb8e95a2
WB
1625 }
1626 }
1627
46630a5f
WB
1628 if (my $serial = $drive->{serial}) {
1629 $serial = URI::Escape::uri_unescape($serial);
1630 $opts .= ",serial=$serial";
1631 }
1e3baf05 1632
d81f0f09
DM
1633 $opts .= ",format=$format" if $format && !$drive->{format};
1634
b2ee900e
WB
1635 my $cache_direct = 0;
1636
1637 if (my $cache = $drive->{cache}) {
1638 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1639 } elsif (!drive_is_cdrom($drive)) {
1640 $opts .= ",cache=none";
1641 $cache_direct = 1;
1642 }
1643
1644 # aio native works only with O_DIRECT
1645 if (!$drive->{aio}) {
1646 if($cache_direct) {
1647 $opts .= ",aio=native";
1648 } else {
1649 $opts .= ",aio=threads";
1650 }
1651 }
11490cf2 1652
6e47c3b4
WB
1653 if (!drive_is_cdrom($drive)) {
1654 my $detectzeroes;
7d4e30f3 1655 if (defined($drive->{detect_zeroes}) && !$drive->{detect_zeroes}) {
6e47c3b4
WB
1656 $detectzeroes = 'off';
1657 } elsif ($drive->{discard}) {
1658 $detectzeroes = $drive->{discard} eq 'on' ? 'unmap' : 'on';
1659 } else {
1660 # This used to be our default with discard not being specified:
1661 $detectzeroes = 'on';
1662 }
1663 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1664 }
f1e05305 1665
1e3baf05
DM
1666 my $pathinfo = $path ? "file=$path," : '';
1667
3ebfcc86 1668 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1e3baf05
DM
1669}
1670
cc4d6182 1671sub print_netdevice_full {
ba9e1000 1672 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
cc4d6182
DA
1673
1674 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
1675
1676 my $device = $net->{model};
1677 if ($net->{model} eq 'virtio') {
1678 $device = 'virtio-net-pci';
1679 };
1680
5bdcf937 1681 my $pciaddr = print_pci_addr("$netid", $bridges);
5e2068d2 1682 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
a9410357
AD
1683 if ($net->{queues} && $net->{queues} > 1 && $net->{model} eq 'virtio'){
1684 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1685 my $vectors = $net->{queues} * 2 + 2;
1686 $tmpstr .= ",vectors=$vectors,mq=on";
1687 }
cc4d6182 1688 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex} ;
ba9e1000
DM
1689
1690 if ($use_old_bios_files) {
1691 my $romfile;
1692 if ($device eq 'virtio-net-pci') {
1693 $romfile = 'pxe-virtio.rom';
1694 } elsif ($device eq 'e1000') {
1695 $romfile = 'pxe-e1000.rom';
1696 } elsif ($device eq 'ne2k') {
1697 $romfile = 'pxe-ne2k_pci.rom';
1698 } elsif ($device eq 'pcnet') {
1699 $romfile = 'pxe-pcnet.rom';
1700 } elsif ($device eq 'rtl8139') {
1701 $romfile = 'pxe-rtl8139.rom';
1702 }
1703 $tmpstr .= ",romfile=$romfile" if $romfile;
1704 }
1705
cc4d6182
DA
1706 return $tmpstr;
1707}
1708
1709sub print_netdev_full {
208ba94e 1710 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
cc4d6182
DA
1711
1712 my $i = '';
1713 if ($netid =~ m/^net(\d+)$/) {
1714 $i = int($1);
1715 }
1716
1717 die "got strange net id '$i'\n" if $i >= ${MAX_NETS};
1718
1719 my $ifname = "tap${vmid}i$i";
1720
1721 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1722 die "interface name '$ifname' is too long (max 15 character)\n"
1723 if length($ifname) >= 16;
1724
1725 my $vhostparam = '';
1726 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model} eq 'virtio';
1727
1728 my $vmname = $conf->{name} || "vm$vmid";
1729
a9410357 1730 my $netdev = "";
208ba94e 1731 my $script = $hotplug ? "pve-bridge-hotplug" : "pve-bridge";
a9410357 1732
cc4d6182 1733 if ($net->{bridge}) {
208ba94e 1734 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
cc4d6182 1735 } else {
a9410357 1736 $netdev = "type=user,id=$netid,hostname=$vmname";
cc4d6182 1737 }
a9410357
AD
1738
1739 $netdev .= ",queues=$net->{queues}" if ($net->{queues} && $net->{model} eq 'virtio');
1740
1741 return $netdev;
cc4d6182 1742}
1e3baf05 1743
0efb537e
AD
1744
1745sub print_cpu_device {
1746 my ($conf, $id) = @_;
1747
74c02ef7
PA
1748 my $kvm = $conf->{kvm} // 1;
1749 my $cpu = $kvm ? "kvm64" : "qemu64";
0efb537e
AD
1750 if (my $cputype = $conf->{cpu}) {
1751 my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
1752 or die "Cannot parse cpu description: $cputype\n";
1753 $cpu = $cpuconf->{cputype};
1754 }
1755
0efb537e
AD
1756 my $cores = $conf->{cores} || 1;
1757
1758 my $current_core = ($id - 1) % $cores;
7032e08c 1759 my $current_socket = int(($id - 1 - $current_core)/$cores);
0efb537e
AD
1760
1761 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1762}
1763
1e3baf05
DM
1764sub drive_is_cdrom {
1765 my ($drive) = @_;
1766
1767 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
1768
1769}
1770
ffc0d8c7
WB
1771sub parse_number_sets {
1772 my ($set) = @_;
1773 my $res = [];
1774 foreach my $part (split(/;/, $set)) {
1775 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1776 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1777 push @$res, [ $1, $2 ];
2ed5d572 1778 } else {
ffc0d8c7 1779 die "invalid range: $part\n";
2ed5d572
AD
1780 }
1781 }
ffc0d8c7
WB
1782 return $res;
1783}
2ed5d572 1784
ffc0d8c7
WB
1785sub parse_numa {
1786 my ($data) = @_;
1787
1788 my $res = PVE::JSONSchema::parse_property_string($numa_fmt, $data);
1789 $res->{cpus} = parse_number_sets($res->{cpus}) if defined($res->{cpus});
1790 $res->{hostnodes} = parse_number_sets($res->{hostnodes}) if defined($res->{hostnodes});
2ed5d572
AD
1791 return $res;
1792}
1793
040b06b7
DA
1794sub parse_hostpci {
1795 my ($value) = @_;
1796
1797 return undef if !$value;
1798
1f4f447b 1799 my $res = PVE::JSONSchema::parse_property_string($hostpci_fmt, $value);
0cea6a01 1800
1f4f447b
WB
1801 my @idlist = split(/;/, $res->{host});
1802 delete $res->{host};
1803 foreach my $id (@idlist) {
1804 if ($id =~ /^$PCIRE$/) {
a3139f90
WB
1805 if (defined($2)) {
1806 push @{$res->{pciid}}, { id => $1, function => $2 };
1807 } else {
1808 my $pcidevices = lspci($1);
1809 $res->{pciid} = $pcidevices->{$1};
1810 }
0cea6a01 1811 } else {
1f4f447b
WB
1812 # should have been caught by parse_property_string already
1813 die "failed to parse PCI id: $id\n";
0cea6a01 1814 }
040b06b7 1815 }
040b06b7
DA
1816 return $res;
1817}
1818
1e3baf05
DM
1819# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1820sub parse_net {
1821 my ($data) = @_;
1822
cd9c34d1
WB
1823 my $res = eval { PVE::JSONSchema::parse_property_string($net_fmt, $data) };
1824 if ($@) {
1825 warn $@;
1826 return undef;
1e3baf05 1827 }
b5b99790
WB
1828 if (!defined($res->{macaddr})) {
1829 my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
1830 $res->{macaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
1831 }
1e3baf05
DM
1832 return $res;
1833}
1834
1835sub print_net {
1836 my $net = shift;
1837
cd9c34d1 1838 return PVE::JSONSchema::print_property_string($net, $net_fmt);
1e3baf05
DM
1839}
1840
1841sub add_random_macs {
1842 my ($settings) = @_;
1843
1844 foreach my $opt (keys %$settings) {
1845 next if $opt !~ m/^net(\d+)$/;
1846 my $net = parse_net($settings->{$opt});
1847 next if !$net;
1848 $settings->{$opt} = print_net($net);
1849 }
1850}
1851
055d554d
DM
1852sub vm_is_volid_owner {
1853 my ($storecfg, $vmid, $volid) = @_;
1854
1855 if ($volid !~ m|^/|) {
1856 my ($path, $owner);
1857 eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
1858 if ($owner && ($owner == $vmid)) {
1859 return 1;
1860 }
1861 }
1862
1863 return undef;
1864}
1865
3dc38fbb
WB
1866sub split_flagged_list {
1867 my $text = shift || '';
1868 $text =~ s/[,;]/ /g;
1869 $text =~ s/^\s+//;
1870 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1871}
1872
1873sub join_flagged_list {
1874 my ($how, $lst) = @_;
1875 join $how, map { $lst->{$_} . $_ } keys %$lst;
1876}
1877
055d554d 1878sub vmconfig_delete_pending_option {
3dc38fbb 1879 my ($conf, $key, $force) = @_;
055d554d
DM
1880
1881 delete $conf->{pending}->{$key};
3dc38fbb
WB
1882 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
1883 $pending_delete_hash->{$key} = $force ? '!' : '';
1884 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
055d554d
DM
1885}
1886
1887sub vmconfig_undelete_pending_option {
1888 my ($conf, $key) = @_;
1889
3dc38fbb 1890 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
055d554d
DM
1891 delete $pending_delete_hash->{$key};
1892
3dc38fbb
WB
1893 if (%$pending_delete_hash) {
1894 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
055d554d
DM
1895 } else {
1896 delete $conf->{pending}->{delete};
1897 }
1898}
1899
1900sub vmconfig_register_unused_drive {
1901 my ($storecfg, $vmid, $conf, $drive) = @_;
1902
1903 if (!drive_is_cdrom($drive)) {
1904 my $volid = $drive->{file};
1905 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
8793d495 1906 PVE::QemuConfig->add_unused_volume($conf, $volid, $vmid);
055d554d
DM
1907 }
1908 }
1909}
1910
c750e90a
DM
1911sub vmconfig_cleanup_pending {
1912 my ($conf) = @_;
1913
1914 # remove pending changes when nothing changed
1915 my $changes;
1916 foreach my $opt (keys %{$conf->{pending}}) {
1917 if (defined($conf->{$opt}) && ($conf->{pending}->{$opt} eq $conf->{$opt})) {
1918 $changes = 1;
1919 delete $conf->{pending}->{$opt};
1920 }
1921 }
1922
3dc38fbb 1923 my $current_delete_hash = split_flagged_list($conf->{pending}->{delete});
c750e90a 1924 my $pending_delete_hash = {};
3dc38fbb 1925 while (my ($opt, $force) = each %$current_delete_hash) {
c750e90a 1926 if (defined($conf->{$opt})) {
3dc38fbb 1927 $pending_delete_hash->{$opt} = $force;
c750e90a
DM
1928 } else {
1929 $changes = 1;
1930 }
1931 }
1932
3dc38fbb
WB
1933 if (%$pending_delete_hash) {
1934 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
c750e90a
DM
1935 } else {
1936 delete $conf->{pending}->{delete};
1937 }
1938
1939 return $changes;
1940}
1941
bd27e851 1942# smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
ff6ffe20 1943my $smbios1_fmt = {
bd27e851
WB
1944 uuid => {
1945 type => 'string',
1946 pattern => '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1947 format_description => 'UUID',
52261945 1948 description => "Set SMBIOS1 UUID.",
bd27e851
WB
1949 optional => 1,
1950 },
1951 version => {
1952 type => 'string',
1953 pattern => '\S+',
7f694a71 1954 format_description => 'string',
52261945 1955 description => "Set SMBIOS1 version.",
bd27e851
WB
1956 optional => 1,
1957 },
1958 serial => {
1959 type => 'string',
1960 pattern => '\S+',
7f694a71 1961 format_description => 'string',
52261945 1962 description => "Set SMBIOS1 serial number.",
bd27e851
WB
1963 optional => 1,
1964 },
1965 manufacturer => {
1966 type => 'string',
1967 pattern => '\S+',
7f694a71 1968 format_description => 'string',
52261945 1969 description => "Set SMBIOS1 manufacturer.",
bd27e851
WB
1970 optional => 1,
1971 },
1972 product => {
1973 type => 'string',
1974 pattern => '\S+',
7f694a71 1975 format_description => 'string',
52261945 1976 description => "Set SMBIOS1 product ID.",
bd27e851
WB
1977 optional => 1,
1978 },
1979 sku => {
1980 type => 'string',
1981 pattern => '\S+',
7f694a71 1982 format_description => 'string',
52261945 1983 description => "Set SMBIOS1 SKU string.",
bd27e851
WB
1984 optional => 1,
1985 },
1986 family => {
1987 type => 'string',
1988 pattern => '\S+',
7f694a71 1989 format_description => 'string',
52261945 1990 description => "Set SMBIOS1 family string.",
bd27e851
WB
1991 optional => 1,
1992 },
2796e7d5
DM
1993};
1994
2796e7d5
DM
1995sub parse_smbios1 {
1996 my ($data) = @_;
1997
ff6ffe20 1998 my $res = eval { PVE::JSONSchema::parse_property_string($smbios1_fmt, $data) };
bd27e851 1999 warn $@ if $@;
2796e7d5
DM
2000 return $res;
2001}
2002
cd11416f
DM
2003sub print_smbios1 {
2004 my ($smbios1) = @_;
ff6ffe20 2005 return PVE::JSONSchema::print_property_string($smbios1, $smbios1_fmt);
cd11416f
DM
2006}
2007
ff6ffe20 2008PVE::JSONSchema::register_format('pve-qm-smbios1', $smbios1_fmt);
2796e7d5 2009
1e3baf05
DM
2010PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
2011sub verify_bootdisk {
2012 my ($value, $noerr) = @_;
2013
74479ee9 2014 return $value if is_valid_drivename($value);
1e3baf05
DM
2015
2016 return undef if $noerr;
2017
2018 die "invalid boot disk '$value'\n";
2019}
2020
0ea9541d
DM
2021sub parse_watchdog {
2022 my ($value) = @_;
2023
2024 return undef if !$value;
2025
ec3582b5
WB
2026 my $res = eval { PVE::JSONSchema::parse_property_string($watchdog_fmt, $value) };
2027 warn $@ if $@;
0ea9541d
DM
2028 return $res;
2029}
2030
1e3baf05
DM
2031PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
2032sub verify_usb_device {
2033 my ($value, $noerr) = @_;
2034
2035 return $value if parse_usb_device($value);
2036
2037 return undef if $noerr;
19672434 2038
1e3baf05
DM
2039 die "unable to parse usb device\n";
2040}
2041
1e3baf05
DM
2042# add JSON properties for create and set function
2043sub json_config_properties {
2044 my $prop = shift;
2045
2046 foreach my $opt (keys %$confdesc) {
18bfb361 2047 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1e3baf05
DM
2048 $prop->{$opt} = $confdesc->{$opt};
2049 }
2050
2051 return $prop;
2052}
2053
2054sub check_type {
2055 my ($key, $value) = @_;
2056
2057 die "unknown setting '$key'\n" if !$confdesc->{$key};
2058
2059 my $type = $confdesc->{$key}->{type};
2060
6b64503e 2061 if (!defined($value)) {
1e3baf05
DM
2062 die "got undefined value\n";
2063 }
2064
2065 if ($value =~ m/[\n\r]/) {
2066 die "property contains a line feed\n";
2067 }
2068
2069 if ($type eq 'boolean') {
19672434
DM
2070 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2071 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2072 die "type check ('boolean') failed - got '$value'\n";
1e3baf05
DM
2073 } elsif ($type eq 'integer') {
2074 return int($1) if $value =~ m/^(\d+)$/;
2075 die "type check ('integer') failed - got '$value'\n";
04432191
AD
2076 } elsif ($type eq 'number') {
2077 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2078 die "type check ('number') failed - got '$value'\n";
1e3baf05
DM
2079 } elsif ($type eq 'string') {
2080 if (my $fmt = $confdesc->{$key}->{format}) {
1e3baf05 2081 PVE::JSONSchema::check_format($fmt, $value);
19672434
DM
2082 return $value;
2083 }
1e3baf05 2084 $value =~ s/^\"(.*)\"$/$1/;
19672434 2085 return $value;
1e3baf05
DM
2086 } else {
2087 die "internal error"
2088 }
2089}
2090
040b06b7
DA
2091sub check_iommu_support{
2092 #fixme : need to check IOMMU support
2093 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2094
2095 my $iommu=1;
2096 return $iommu;
2097
2098}
2099
1e3baf05
DM
2100sub touch_config {
2101 my ($vmid) = @_;
2102
ffda963f 2103 my $conf = PVE::QemuConfig->config_file($vmid);
1e3baf05
DM
2104 utime undef, undef, $conf;
2105}
2106
1e3baf05 2107sub destroy_vm {
15cc8784 2108 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1e3baf05 2109
ffda963f 2110 my $conffile = PVE::QemuConfig->config_file($vmid);
1e3baf05 2111
ffda963f 2112 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 2113
ffda963f 2114 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 2115
5e67a2d2
DC
2116 if ($conf->{template}) {
2117 # check if any base image is still used by a linked clone
2118 foreach_drive($conf, sub {
2119 my ($ds, $drive) = @_;
2120
2121 return if drive_is_cdrom($drive);
2122
2123 my $volid = $drive->{file};
2124
2125 return if !$volid || $volid =~ m|^/|;
2126
2127 die "base volume '$volid' is still in use by linked cloned\n"
2128 if PVE::Storage::volume_is_base_and_used($storecfg, $volid);
2129
2130 });
2131 }
2132
19672434 2133 # only remove disks owned by this VM
1e3baf05
DM
2134 foreach_drive($conf, sub {
2135 my ($ds, $drive) = @_;
2136
6b64503e 2137 return if drive_is_cdrom($drive);
1e3baf05
DM
2138
2139 my $volid = $drive->{file};
ed221350 2140
ff1a2432 2141 return if !$volid || $volid =~ m|^/|;
1e3baf05 2142
6b64503e 2143 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
ff1a2432 2144 return if !$path || !$owner || ($owner != $vmid);
1e3baf05 2145
31b52247
FG
2146 eval {
2147 PVE::Storage::vdisk_free($storecfg, $volid);
2148 };
2149 warn "Could not remove disk '$volid', check manually: $@" if $@;
2150
1e3baf05 2151 });
19672434 2152
a6af7b3e 2153 if ($keep_empty_config) {
9c502e26 2154 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
a6af7b3e
DM
2155 } else {
2156 unlink $conffile;
2157 }
1e3baf05
DM
2158
2159 # also remove unused disk
2160 eval {
6b64503e 2161 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1e3baf05
DM
2162
2163 eval {
6b64503e 2164 PVE::Storage::foreach_volid($dl, sub {
1e3baf05 2165 my ($volid, $sid, $volname, $d) = @_;
6b64503e 2166 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05
DM
2167 });
2168 };
2169 warn $@ if $@;
2170
2171 };
2172 warn $@ if $@;
2173}
2174
1e3baf05
DM
2175sub parse_vm_config {
2176 my ($filename, $raw) = @_;
2177
2178 return undef if !defined($raw);
2179
554ac7e7 2180 my $res = {
fc1ddcdc 2181 digest => Digest::SHA::sha1_hex($raw),
0d18dcfc 2182 snapshots => {},
0d732d16 2183 pending => {},
554ac7e7 2184 };
1e3baf05 2185
19672434 2186 $filename =~ m|/qemu-server/(\d+)\.conf$|
1e3baf05
DM
2187 || die "got strange filename '$filename'";
2188
2189 my $vmid = $1;
2190
0d18dcfc 2191 my $conf = $res;
b0ec896e 2192 my $descr;
e297c490 2193 my $section = '';
0581fe4f 2194
0d18dcfc
DM
2195 my @lines = split(/\n/, $raw);
2196 foreach my $line (@lines) {
1e3baf05 2197 next if $line =~ m/^\s*$/;
be190583 2198
eab09f4e 2199 if ($line =~ m/^\[PENDING\]\s*$/i) {
e297c490 2200 $section = 'pending';
b0ec896e
DM
2201 if (defined($descr)) {
2202 $descr =~ s/\s+$//;
2203 $conf->{description} = $descr;
2204 }
2205 $descr = undef;
e297c490 2206 $conf = $res->{$section} = {};
eab09f4e
AD
2207 next;
2208
0d732d16 2209 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
e297c490 2210 $section = $1;
b0ec896e
DM
2211 if (defined($descr)) {
2212 $descr =~ s/\s+$//;
2213 $conf->{description} = $descr;
2214 }
2215 $descr = undef;
e297c490 2216 $conf = $res->{snapshots}->{$section} = {};
0d18dcfc
DM
2217 next;
2218 }
1e3baf05 2219
0581fe4f 2220 if ($line =~ m/^\#(.*)\s*$/) {
b0ec896e 2221 $descr = '' if !defined($descr);
0581fe4f
DM
2222 $descr .= PVE::Tools::decode_text($1) . "\n";
2223 next;
2224 }
2225
1e3baf05 2226 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
b0ec896e 2227 $descr = '' if !defined($descr);
0581fe4f 2228 $descr .= PVE::Tools::decode_text($2);
0d18dcfc
DM
2229 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2230 $conf->{snapstate} = $1;
1e3baf05
DM
2231 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2232 my $key = $1;
2233 my $value = $2;
0d18dcfc 2234 $conf->{$key} = $value;
ef824322 2235 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
e297c490 2236 my $value = $1;
ef824322
DM
2237 if ($section eq 'pending') {
2238 $conf->{delete} = $value; # we parse this later
2239 } else {
2240 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
eab09f4e 2241 }
1e3baf05
DM
2242 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2243 my $key = $1;
2244 my $value = $2;
2245 eval { $value = check_type($key, $value); };
2246 if ($@) {
2247 warn "vm $vmid - unable to parse value of '$key' - $@";
2248 } else {
b799312f 2249 $key = 'ide2' if $key eq 'cdrom';
1e3baf05 2250 my $fmt = $confdesc->{$key}->{format};
b799312f 2251 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
1e3baf05
DM
2252 my $v = parse_drive($key, $value);
2253 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
2254 $v->{file} = $volid;
6b64503e 2255 $value = print_drive($vmid, $v);
1e3baf05
DM
2256 } else {
2257 warn "vm $vmid - unable to parse value of '$key'\n";
2258 next;
2259 }
2260 }
2261
b799312f 2262 $conf->{$key} = $value;
1e3baf05
DM
2263 }
2264 }
2265 }
2266
b0ec896e
DM
2267 if (defined($descr)) {
2268 $descr =~ s/\s+$//;
2269 $conf->{description} = $descr;
2270 }
0d18dcfc 2271 delete $res->{snapstate}; # just to be sure
1e3baf05
DM
2272
2273 return $res;
2274}
2275
1858638f
DM
2276sub write_vm_config {
2277 my ($filename, $conf) = @_;
1e3baf05 2278
0d18dcfc
DM
2279 delete $conf->{snapstate}; # just to be sure
2280
1858638f
DM
2281 if ($conf->{cdrom}) {
2282 die "option ide2 conflicts with cdrom\n" if $conf->{ide2};
2283 $conf->{ide2} = $conf->{cdrom};
2284 delete $conf->{cdrom};
2285 }
1e3baf05
DM
2286
2287 # we do not use 'smp' any longer
1858638f
DM
2288 if ($conf->{sockets}) {
2289 delete $conf->{smp};
2290 } elsif ($conf->{smp}) {
2291 $conf->{sockets} = $conf->{smp};
2292 delete $conf->{cores};
2293 delete $conf->{smp};
1e3baf05
DM
2294 }
2295
ee2f90b1 2296 my $used_volids = {};
0d18dcfc 2297
ee2f90b1 2298 my $cleanup_config = sub {
ef824322 2299 my ($cref, $pending, $snapname) = @_;
1858638f 2300
ee2f90b1
DM
2301 foreach my $key (keys %$cref) {
2302 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
ef824322 2303 $key eq 'snapstate' || $key eq 'pending';
ee2f90b1 2304 my $value = $cref->{$key};
ef824322
DM
2305 if ($key eq 'delete') {
2306 die "propertry 'delete' is only allowed in [PENDING]\n"
2307 if !$pending;
2308 # fixme: check syntax?
2309 next;
2310 }
ee2f90b1
DM
2311 eval { $value = check_type($key, $value); };
2312 die "unable to parse value of '$key' - $@" if $@;
1858638f 2313
ee2f90b1
DM
2314 $cref->{$key} = $value;
2315
74479ee9 2316 if (!$snapname && is_valid_drivename($key)) {
ed221350 2317 my $drive = parse_drive($key, $value);
ee2f90b1
DM
2318 $used_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
2319 }
1e3baf05 2320 }
ee2f90b1
DM
2321 };
2322
2323 &$cleanup_config($conf);
ef824322
DM
2324
2325 &$cleanup_config($conf->{pending}, 1);
2326
ee2f90b1 2327 foreach my $snapname (keys %{$conf->{snapshots}}) {
ef824322
DM
2328 die "internal error" if $snapname eq 'pending';
2329 &$cleanup_config($conf->{snapshots}->{$snapname}, undef, $snapname);
1e3baf05
DM
2330 }
2331
1858638f
DM
2332 # remove 'unusedX' settings if we re-add a volume
2333 foreach my $key (keys %$conf) {
2334 my $value = $conf->{$key};
ee2f90b1 2335 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1858638f 2336 delete $conf->{$key};
1e3baf05 2337 }
1858638f 2338 }
be190583 2339
0d18dcfc 2340 my $generate_raw_config = sub {
b0ec896e 2341 my ($conf, $pending) = @_;
0581fe4f 2342
0d18dcfc
DM
2343 my $raw = '';
2344
2345 # add description as comment to top of file
b0ec896e
DM
2346 if (defined(my $descr = $conf->{description})) {
2347 if ($descr) {
2348 foreach my $cl (split(/\n/, $descr)) {
2349 $raw .= '#' . PVE::Tools::encode_text($cl) . "\n";
2350 }
2351 } else {
2352 $raw .= "#\n" if $pending;
2353 }
0d18dcfc
DM
2354 }
2355
2356 foreach my $key (sort keys %$conf) {
ef824322 2357 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
0d18dcfc
DM
2358 $raw .= "$key: $conf->{$key}\n";
2359 }
2360 return $raw;
2361 };
0581fe4f 2362
0d18dcfc 2363 my $raw = &$generate_raw_config($conf);
ef824322
DM
2364
2365 if (scalar(keys %{$conf->{pending}})){
2366 $raw .= "\n[PENDING]\n";
b0ec896e 2367 $raw .= &$generate_raw_config($conf->{pending}, 1);
ef824322
DM
2368 }
2369
0d18dcfc
DM
2370 foreach my $snapname (sort keys %{$conf->{snapshots}}) {
2371 $raw .= "\n[$snapname]\n";
2372 $raw .= &$generate_raw_config($conf->{snapshots}->{$snapname});
1858638f 2373 }
1e3baf05 2374
1858638f
DM
2375 return $raw;
2376}
1e3baf05 2377
19672434 2378sub load_defaults {
1e3baf05
DM
2379
2380 my $res = {};
2381
2382 # we use static defaults from our JSON schema configuration
2383 foreach my $key (keys %$confdesc) {
2384 if (defined(my $default = $confdesc->{$key}->{default})) {
2385 $res->{$key} = $default;
2386 }
2387 }
19672434 2388
1e3baf05
DM
2389 my $conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
2390 $res->{keyboard} = $conf->{keyboard} if $conf->{keyboard};
2391
2392 return $res;
2393}
2394
2395sub config_list {
2396 my $vmlist = PVE::Cluster::get_vmlist();
2397 my $res = {};
2398 return $res if !$vmlist || !$vmlist->{ids};
2399 my $ids = $vmlist->{ids};
2400
1e3baf05
DM
2401 foreach my $vmid (keys %$ids) {
2402 my $d = $ids->{$vmid};
2403 next if !$d->{node} || $d->{node} ne $nodename;
5ee957cc 2404 next if !$d->{type} || $d->{type} ne 'qemu';
1e3baf05
DM
2405 $res->{$vmid}->{exists} = 1;
2406 }
2407 return $res;
2408}
2409
64e13401
DM
2410# test if VM uses local resources (to prevent migration)
2411sub check_local_resources {
2412 my ($conf, $noerr) = @_;
2413
2414 my $loc_res = 0;
19672434 2415
e0ab7331
DM
2416 $loc_res = 1 if $conf->{hostusb}; # old syntax
2417 $loc_res = 1 if $conf->{hostpci}; # old syntax
64e13401 2418
0d29ab3b 2419 foreach my $k (keys %$conf) {
49ca581d 2420 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
d44712fc
EK
2421 # sockets are safe: they will recreated be on the target side post-migrate
2422 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2fe1a152 2423 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
64e13401
DM
2424 }
2425
2426 die "VM uses local resources\n" if $loc_res && !$noerr;
2427
2428 return $loc_res;
2429}
2430
719893a9 2431# check if used storages are available on all nodes (use by migrate)
47152e2e
DM
2432sub check_storage_availability {
2433 my ($storecfg, $conf, $node) = @_;
2434
2435 foreach_drive($conf, sub {
2436 my ($ds, $drive) = @_;
2437
2438 my $volid = $drive->{file};
2439 return if !$volid;
2440
2441 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
2442 return if !$sid;
2443
2444 # check if storage is available on both nodes
2445 my $scfg = PVE::Storage::storage_check_node($storecfg, $sid);
2446 PVE::Storage::storage_check_node($storecfg, $sid, $node);
2447 });
2448}
2449
719893a9
DM
2450# list nodes where all VM images are available (used by has_feature API)
2451sub shared_nodes {
2452 my ($conf, $storecfg) = @_;
2453
2454 my $nodelist = PVE::Cluster::get_nodelist();
2455 my $nodehash = { map { $_ => 1 } @$nodelist };
2456 my $nodename = PVE::INotify::nodename();
be190583 2457
719893a9
DM
2458 foreach_drive($conf, sub {
2459 my ($ds, $drive) = @_;
2460
2461 my $volid = $drive->{file};
2462 return if !$volid;
2463
2464 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
2465 if ($storeid) {
2466 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
2467 if ($scfg->{disable}) {
2468 $nodehash = {};
2469 } elsif (my $avail = $scfg->{nodes}) {
2470 foreach my $node (keys %$nodehash) {
2471 delete $nodehash->{$node} if !$avail->{$node};
2472 }
2473 } elsif (!$scfg->{shared}) {
2474 foreach my $node (keys %$nodehash) {
2475 delete $nodehash->{$node} if $node ne $nodename
2476 }
2477 }
2478 }
2479 });
2480
2481 return $nodehash
2482}
2483
1e3baf05
DM
2484sub check_cmdline {
2485 my ($pidfile, $pid) = @_;
2486
6b64503e
DM
2487 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
2488 if (defined($fh)) {
1e3baf05
DM
2489 my $line = <$fh>;
2490 $fh->close;
2491 return undef if !$line;
6b64503e 2492 my @param = split(/\0/, $line);
1e3baf05
DM
2493
2494 my $cmd = $param[0];
06094efd 2495 return if !$cmd || ($cmd !~ m|kvm$| && $cmd !~ m|qemu-system-x86_64$|);
1e3baf05
DM
2496
2497 for (my $i = 0; $i < scalar (@param); $i++) {
2498 my $p = $param[$i];
2499 next if !$p;
2500 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2501 my $p = $param[$i+1];
2502 return 1 if $p && ($p eq $pidfile);
2503 return undef;
2504 }
2505 }
2506 }
2507 return undef;
2508}
2509
2510sub check_running {
7e8dcf2c 2511 my ($vmid, $nocheck, $node) = @_;
1e3baf05 2512
ffda963f 2513 my $filename = PVE::QemuConfig->config_file($vmid, $node);
1e3baf05
DM
2514
2515 die "unable to find configuration file for VM $vmid - no such machine\n"
e6c3b671 2516 if !$nocheck && ! -f $filename;
1e3baf05 2517
e6c3b671 2518 my $pidfile = pidfile_name($vmid);
1e3baf05 2519
e6c3b671
DM
2520 if (my $fd = IO::File->new("<$pidfile")) {
2521 my $st = stat($fd);
1e3baf05 2522 my $line = <$fd>;
6b64503e 2523 close($fd);
1e3baf05
DM
2524
2525 my $mtime = $st->mtime;
2526 if ($mtime > time()) {
2527 warn "file '$filename' modified in future\n";
2528 }
2529
2530 if ($line =~ m/^(\d+)$/) {
2531 my $pid = $1;
e6c3b671
DM
2532 if (check_cmdline($pidfile, $pid)) {
2533 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
2534 return $pid;
2535 }
2536 }
1e3baf05
DM
2537 }
2538 }
2539
2540 return undef;
2541}
2542
2543sub vzlist {
19672434 2544
1e3baf05
DM
2545 my $vzlist = config_list();
2546
6b64503e 2547 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1e3baf05 2548
19672434 2549 while (defined(my $de = $fd->read)) {
1e3baf05
DM
2550 next if $de !~ m/^(\d+)\.pid$/;
2551 my $vmid = $1;
6b64503e
DM
2552 next if !defined($vzlist->{$vmid});
2553 if (my $pid = check_running($vmid)) {
1e3baf05
DM
2554 $vzlist->{$vmid}->{pid} = $pid;
2555 }
2556 }
2557
2558 return $vzlist;
2559}
2560
1e3baf05
DM
2561sub disksize {
2562 my ($storecfg, $conf) = @_;
2563
2564 my $bootdisk = $conf->{bootdisk};
2565 return undef if !$bootdisk;
74479ee9 2566 return undef if !is_valid_drivename($bootdisk);
1e3baf05
DM
2567
2568 return undef if !$conf->{$bootdisk};
2569
2570 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
2571 return undef if !defined($drive);
2572
2573 return undef if drive_is_cdrom($drive);
2574
2575 my $volid = $drive->{file};
2576 return undef if !$volid;
2577
24afaca0 2578 return $drive->{size};
1e3baf05
DM
2579}
2580
2581my $last_proc_pid_stat;
2582
03a33f30
DM
2583# get VM status information
2584# This must be fast and should not block ($full == false)
2585# We only query KVM using QMP if $full == true (this can be slow)
1e3baf05 2586sub vmstatus {
03a33f30 2587 my ($opt_vmid, $full) = @_;
1e3baf05
DM
2588
2589 my $res = {};
2590
19672434 2591 my $storecfg = PVE::Storage::config();
1e3baf05
DM
2592
2593 my $list = vzlist();
3618ee99
EK
2594 my $defaults = load_defaults();
2595
694fcad4 2596 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1e3baf05 2597
ae4915a2
DM
2598 my $cpucount = $cpuinfo->{cpus} || 1;
2599
1e3baf05
DM
2600 foreach my $vmid (keys %$list) {
2601 next if $opt_vmid && ($vmid ne $opt_vmid);
2602
ffda963f 2603 my $cfspath = PVE::QemuConfig->cfs_config_path($vmid);
1e3baf05
DM
2604 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
2605
2606 my $d = {};
2607 $d->{pid} = $list->{$vmid}->{pid};
2608
2609 # fixme: better status?
2610 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
2611
af990afe
DM
2612 my $size = disksize($storecfg, $conf);
2613 if (defined($size)) {
2614 $d->{disk} = 0; # no info available
1e3baf05
DM
2615 $d->{maxdisk} = $size;
2616 } else {
2617 $d->{disk} = 0;
2618 $d->{maxdisk} = 0;
2619 }
2620
3618ee99
EK
2621 $d->{cpus} = ($conf->{sockets} || $defaults->{sockets})
2622 * ($conf->{cores} || $defaults->{cores});
ae4915a2 2623 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
d7c8364b 2624 $d->{cpus} = $conf->{vcpus} if $conf->{vcpus};
ae4915a2 2625
1e3baf05 2626 $d->{name} = $conf->{name} || "VM $vmid";
3618ee99
EK
2627 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024)
2628 : $defaults->{memory}*(1024*1024);
1e3baf05 2629
8b1accf7 2630 if ($conf->{balloon}) {
4bdb0514 2631 $d->{balloon_min} = $conf->{balloon}*(1024*1024);
3618ee99
EK
2632 $d->{shares} = defined($conf->{shares}) ? $conf->{shares}
2633 : $defaults->{shares};
8b1accf7
DM
2634 }
2635
1e3baf05
DM
2636 $d->{uptime} = 0;
2637 $d->{cpu} = 0;
1e3baf05
DM
2638 $d->{mem} = 0;
2639
2640 $d->{netout} = 0;
2641 $d->{netin} = 0;
2642
2643 $d->{diskread} = 0;
2644 $d->{diskwrite} = 0;
2645
ffda963f 2646 $d->{template} = PVE::QemuConfig->is_template($conf);
4d8c851b 2647
1e3baf05
DM
2648 $res->{$vmid} = $d;
2649 }
2650
2651 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
2652 foreach my $dev (keys %$netdev) {
2653 next if $dev !~ m/^tap([1-9]\d*)i/;
2654 my $vmid = $1;
2655 my $d = $res->{$vmid};
2656 next if !$d;
19672434 2657
1e3baf05
DM
2658 $d->{netout} += $netdev->{$dev}->{receive};
2659 $d->{netin} += $netdev->{$dev}->{transmit};
604ea644
AD
2660
2661 if ($full) {
2662 $d->{nics}->{$dev}->{netout} = $netdev->{$dev}->{receive};
2663 $d->{nics}->{$dev}->{netin} = $netdev->{$dev}->{transmit};
2664 }
2665
1e3baf05
DM
2666 }
2667
1e3baf05
DM
2668 my $ctime = gettimeofday;
2669
2670 foreach my $vmid (keys %$list) {
2671
2672 my $d = $res->{$vmid};
2673 my $pid = $d->{pid};
2674 next if !$pid;
2675
694fcad4
DM
2676 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
2677 next if !$pstat; # not running
19672434 2678
694fcad4 2679 my $used = $pstat->{utime} + $pstat->{stime};
1e3baf05 2680
694fcad4 2681 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1e3baf05 2682
694fcad4 2683 if ($pstat->{vsize}) {
6b64503e 2684 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1e3baf05
DM
2685 }
2686
2687 my $old = $last_proc_pid_stat->{$pid};
2688 if (!$old) {
19672434
DM
2689 $last_proc_pid_stat->{$pid} = {
2690 time => $ctime,
1e3baf05
DM
2691 used => $used,
2692 cpu => 0,
1e3baf05
DM
2693 };
2694 next;
2695 }
2696
7f0b5beb 2697 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1e3baf05
DM
2698
2699 if ($dtime > 1000) {
2700 my $dutime = $used - $old->{used};
2701
ae4915a2 2702 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1e3baf05 2703 $last_proc_pid_stat->{$pid} = {
19672434 2704 time => $ctime,
1e3baf05
DM
2705 used => $used,
2706 cpu => $d->{cpu},
1e3baf05
DM
2707 };
2708 } else {
2709 $d->{cpu} = $old->{cpu};
1e3baf05
DM
2710 }
2711 }
2712
f5eb281a 2713 return $res if !$full;
03a33f30
DM
2714
2715 my $qmpclient = PVE::QMPClient->new();
2716
64e7fcf2
DM
2717 my $ballooncb = sub {
2718 my ($vmid, $resp) = @_;
2719
2720 my $info = $resp->{'return'};
38babf81
DM
2721 return if !$info->{max_mem};
2722
64e7fcf2
DM
2723 my $d = $res->{$vmid};
2724
38babf81
DM
2725 # use memory assigned to VM
2726 $d->{maxmem} = $info->{max_mem};
2727 $d->{balloon} = $info->{actual};
2728
2729 if (defined($info->{total_mem}) && defined($info->{free_mem})) {
2730 $d->{mem} = $info->{total_mem} - $info->{free_mem};
2731 $d->{freemem} = $info->{free_mem};
64e7fcf2
DM
2732 }
2733
604ea644 2734 $d->{ballooninfo} = $info;
64e7fcf2
DM
2735 };
2736
03a33f30
DM
2737 my $blockstatscb = sub {
2738 my ($vmid, $resp) = @_;
2739 my $data = $resp->{'return'} || [];
2740 my $totalrdbytes = 0;
2741 my $totalwrbytes = 0;
604ea644 2742
03a33f30
DM
2743 for my $blockstat (@$data) {
2744 $totalrdbytes = $totalrdbytes + $blockstat->{stats}->{rd_bytes};
2745 $totalwrbytes = $totalwrbytes + $blockstat->{stats}->{wr_bytes};
604ea644
AD
2746
2747 $blockstat->{device} =~ s/drive-//;
2748 $res->{$vmid}->{blockstat}->{$blockstat->{device}} = $blockstat->{stats};
03a33f30
DM
2749 }
2750 $res->{$vmid}->{diskread} = $totalrdbytes;
2751 $res->{$vmid}->{diskwrite} = $totalwrbytes;
2752 };
2753
2754 my $statuscb = sub {
2755 my ($vmid, $resp) = @_;
64e7fcf2 2756
03a33f30 2757 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
64e7fcf2
DM
2758 # this fails if ballon driver is not loaded, so this must be
2759 # the last commnand (following command are aborted if this fails).
38babf81 2760 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
03a33f30
DM
2761
2762 my $status = 'unknown';
2763 if (!defined($status = $resp->{'return'}->{status})) {
2764 warn "unable to get VM status\n";
2765 return;
2766 }
2767
2768 $res->{$vmid}->{qmpstatus} = $resp->{'return'}->{status};
2769 };
2770
2771 foreach my $vmid (keys %$list) {
2772 next if $opt_vmid && ($vmid ne $opt_vmid);
2773 next if !$res->{$vmid}->{pid}; # not running
2774 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2775 }
2776
b017fbda 2777 $qmpclient->queue_execute(undef, 2);
03a33f30
DM
2778
2779 foreach my $vmid (keys %$list) {
2780 next if $opt_vmid && ($vmid ne $opt_vmid);
2781 $res->{$vmid}->{qmpstatus} = $res->{$vmid}->{status} if !$res->{$vmid}->{qmpstatus};
2782 }
2783
1e3baf05
DM
2784 return $res;
2785}
2786
2787sub foreach_drive {
b74ff047 2788 my ($conf, $func, @param) = @_;
1e3baf05 2789
74479ee9
FG
2790 foreach my $ds (valid_drive_names()) {
2791 next if !defined($conf->{$ds});
1e3baf05 2792
6b64503e 2793 my $drive = parse_drive($ds, $conf->{$ds});
1e3baf05
DM
2794 next if !$drive;
2795
b74ff047 2796 &$func($ds, $drive, @param);
1e3baf05
DM
2797 }
2798}
2799
d5769dc2 2800sub foreach_volid {
b6adff33 2801 my ($conf, $func, @param) = @_;
be190583 2802
d5769dc2
DM
2803 my $volhash = {};
2804
2805 my $test_volid = sub {
39019f75 2806 my ($volid, $is_cdrom, $replicate, $snapname) = @_;
d5769dc2
DM
2807
2808 return if !$volid;
be190583 2809
392f8b5d
DM
2810 $volhash->{$volid}->{cdrom} //= 1;
2811 $volhash->{$volid}->{cdrom} = 0 if !$is_cdrom;
2812
2813 $volhash->{$volid}->{replicate} //= 0;
2814 $volhash->{$volid}->{replicate} = 1 if $replicate;
39019f75
DM
2815
2816 $volhash->{$volid}->{referenced_in_config} //= 0;
2817 $volhash->{$volid}->{referenced_in_config} = 1 if !defined($snapname);
2818
2819 $volhash->{$volid}->{referenced_in_snapshot}->{$snapname} = 1
2820 if defined($snapname);
d5769dc2
DM
2821 };
2822
ed221350 2823 foreach_drive($conf, sub {
d5769dc2 2824 my ($ds, $drive) = @_;
39019f75 2825 $test_volid->($drive->{file}, drive_is_cdrom($drive), $drive->{replicate} // 1, undef);
d5769dc2
DM
2826 });
2827
2828 foreach my $snapname (keys %{$conf->{snapshots}}) {
2829 my $snap = $conf->{snapshots}->{$snapname};
39019f75 2830 $test_volid->($snap->{vmstate}, 0, 1, $snapname);
ed221350 2831 foreach_drive($snap, sub {
d5769dc2 2832 my ($ds, $drive) = @_;
39019f75 2833 $test_volid->($drive->{file}, drive_is_cdrom($drive), $drive->{replicate} // 1, $snapname);
d5769dc2
DM
2834 });
2835 }
2836
2837 foreach my $volid (keys %$volhash) {
b6adff33 2838 &$func($volid, $volhash->{$volid}, @param);
d5769dc2
DM
2839 }
2840}
2841
86b8228b
DM
2842sub vga_conf_has_spice {
2843 my ($vga) = @_;
2844
590e698c
DM
2845 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2846
2847 return $1 || 1;
86b8228b
DM
2848}
2849
1e3baf05 2850sub config_to_command {
67812f9c 2851 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
1e3baf05
DM
2852
2853 my $cmd = [];
8c559505
DM
2854 my $globalFlags = [];
2855 my $machineFlags = [];
2856 my $rtcFlags = [];
519ed28c 2857 my $cpuFlags = [];
5bdcf937 2858 my $devices = [];
b78ebef7 2859 my $pciaddr = '';
5bdcf937 2860 my $bridges = {};
1e3baf05
DM
2861 my $kvmver = kvm_user_version();
2862 my $vernum = 0; # unknown
b42d3cf9 2863 my $ostype = $conf->{ostype};
4317f69f 2864 my $winversion = windows_version($ostype);
74c02ef7 2865 my $kvm = $conf->{kvm} // 1;
4317f69f 2866
bfcd9b7e
PA
2867 die "KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.\n" if (!$cpuinfo->{hvm} && $kvm);
2868
a3c52213
DM
2869 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2870 $vernum = $1*1000000+$2*1000;
2871 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1e3baf05
DM
2872 $vernum = $1*1000000+$2*1000+$3;
2873 }
2874
a3c52213 2875 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1e3baf05
DM
2876
2877 my $have_ovz = -f '/proc/vz/vestat';
2878
db656e5f 2879 my $q35 = machine_type_is_q35($conf);
4d3f29ed 2880 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
23f73120 2881 my $machine_type = $forcemachine || $conf->{machine};
249c4a6c
AD
2882 my $use_old_bios_files = undef;
2883 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
db656e5f 2884
f08e17c7
AD
2885 my $cpuunits = defined($conf->{cpuunits}) ?
2886 $conf->{cpuunits} : $defaults->{cpuunits};
2887
1e3baf05
DM
2888 push @$cmd, '/usr/bin/kvm';
2889
2890 push @$cmd, '-id', $vmid;
2891
2892 my $use_virtio = 0;
2893
c971c4f2
AD
2894 my $qmpsocket = qmp_socket($vmid);
2895 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2896 push @$cmd, '-mon', "chardev=qmp,mode=control";
2897
1e3baf05 2898
6b64503e 2899 push @$cmd, '-pidfile' , pidfile_name($vmid);
19672434 2900
1e3baf05
DM
2901 push @$cmd, '-daemonize';
2902
2796e7d5
DM
2903 if ($conf->{smbios1}) {
2904 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2905 }
2906
3edb45e7 2907 if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
4dcce9ee 2908 die "uefi base image not found\n" if ! -f $OVMF_CODE;
2ddc0a5c 2909
4dcce9ee 2910 my $path;
2bfbee03 2911 my $format = 'raw';
4dcce9ee
TL
2912 if (my $efidisk = $conf->{efidisk0}) {
2913 my $d = PVE::JSONSchema::parse_property_string($efidisk_fmt, $efidisk);
2ddc0a5c
DC
2914 my ($storeid, $volname) = PVE::Storage::parse_volume_id($d->{file}, 1);
2915 if ($storeid) {
2916 $path = PVE::Storage::path($storecfg, $d->{file});
2ddc0a5c
DC
2917 } else {
2918 $path = $d->{file};
2ddc0a5c 2919 }
2bfbee03 2920 $format = $d->{format} if $d->{format};
2ddc0a5c 2921 } else {
4dcce9ee
TL
2922 warn "no efidisk configured! Using temporary efivars disk.\n";
2923 $path = "/tmp/$vmid-ovmf.fd";
2924 PVE::Tools::file_copy($OVMF_VARS, $path, -s $OVMF_VARS);
2ddc0a5c 2925 }
4dcce9ee
TL
2926
2927 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$OVMF_CODE";
2bfbee03 2928 push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0,file=$path";
a783c78e
AD
2929 }
2930
da8b4189 2931
d40e5e18
DC
2932 # add usb controllers
2933 my @usbcontrollers = PVE::QemuServer::USB::get_usb_controllers($conf, $bridges, $q35, $usbdesc->{format}, $MAX_USB_DEVICES);
2934 push @$devices, @usbcontrollers if @usbcontrollers;
5acbfe9e 2935 my $vga = $conf->{vga};
2fa3151e 2936
590e698c
DM
2937 my $qxlnum = vga_conf_has_spice($vga);
2938 $vga = 'qxl' if $qxlnum;
2fa3151e 2939
5acbfe9e 2940 if (!$vga) {
a2a5cd64
TL
2941 if (qemu_machine_feature_enabled($machine_type, $kvmver, 2, 9)) {
2942 $vga = (!$winversion || $winversion >= 6) ? 'std' : 'cirrus';
2943 } else {
2944 $vga = ($winversion >= 6) ? 'std' : 'cirrus';
2945 }
5acbfe9e
DM
2946 }
2947
1e3baf05 2948 # enable absolute mouse coordinates (needed by vnc)
5acbfe9e
DM
2949 my $tablet;
2950 if (defined($conf->{tablet})) {
2951 $tablet = $conf->{tablet};
2952 } else {
2953 $tablet = $defaults->{tablet};
590e698c 2954 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
ef5e2be2 2955 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
5acbfe9e
DM
2956 }
2957
db656e5f 2958 push @$devices, '-device', print_tabletdevice_full($conf) if $tablet;
b467f79a 2959
16a91d65 2960 my $kvm_off = 0;
4317f69f
AD
2961 my $gpu_passthrough;
2962
1e3baf05 2963 # host pci devices
040b06b7 2964 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2e3b7e2a
AD
2965 my $d = parse_hostpci($conf->{"hostpci$i"});
2966 next if !$d;
2967
2968 my $pcie = $d->{pcie};
2969 if($pcie){
2970 die "q35 machine model is not enabled" if !$q35;
2971 $pciaddr = print_pcie_addr("hostpci$i");
2972 }else{
2973 $pciaddr = print_pci_addr("hostpci$i", $bridges);
2974 }
2975
1f4f447b 2976 my $rombar = defined($d->{rombar}) && !$d->{rombar} ? ',rombar=0' : '';
9009150b 2977 my $romfile = $d->{romfile};
456a6fec 2978
1f4f447b
WB
2979 my $xvga = '';
2980 if ($d->{'x-vga'}) {
2981 $xvga = ',x-vga=on';
16a91d65 2982 $kvm_off = 1;
137483c0 2983 $vga = 'none';
4317f69f
AD
2984 $gpu_passthrough = 1;
2985
230a4382
AD
2986 if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
2987 $xvga = "";
2988 }
137483c0 2989 }
4543ecf0
AD
2990 my $pcidevices = $d->{pciid};
2991 my $multifunction = 1 if @$pcidevices > 1;
2e3b7e2a 2992
4543ecf0
AD
2993 my $j=0;
2994 foreach my $pcidevice (@$pcidevices) {
2e3b7e2a 2995
4543ecf0
AD
2996 my $id = "hostpci$i";
2997 $id .= ".$j" if $multifunction;
2998 my $addr = $pciaddr;
2999 $addr .= ".$j" if $multifunction;
6ea8cd3b 3000 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
4543ecf0
AD
3001
3002 if($j == 0){
3003 $devicestr .= "$rombar$xvga";
3004 $devicestr .= ",multifunction=on" if $multifunction;
456a6fec 3005 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
4543ecf0
AD
3006 }
3007
3008 push @$devices, '-device', $devicestr;
3009 $j++;
3010 }
1e3baf05
DM
3011 }
3012
3013 # usb devices
d40e5e18
DC
3014 my @usbdevices = PVE::QemuServer::USB::get_usb_devices($conf, $usbdesc->{format}, $MAX_USB_DEVICES);
3015 push @$devices, @usbdevices if @usbdevices;
1e3baf05 3016 # serial devices
bae179aa 3017 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
34978be3 3018 if (my $path = $conf->{"serial$i"}) {
9f9d2fb2
DM
3019 if ($path eq 'socket') {
3020 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
3021 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
3022 push @$devices, '-device', "isa-serial,chardev=serial$i";
3023 } else {
3024 die "no such serial device\n" if ! -c $path;
3025 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
3026 push @$devices, '-device', "isa-serial,chardev=serial$i";
3027 }
34978be3 3028 }
1e3baf05
DM
3029 }
3030
3031 # parallel devices
1989a89c 3032 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
34978be3 3033 if (my $path = $conf->{"parallel$i"}) {
19672434 3034 die "no such parallel device\n" if ! -c $path;
32e69805 3035 my $devtype = $path =~ m!^/dev/usb/lp! ? 'tty' : 'parport';
4c5dbaf6 3036 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
5bdcf937 3037 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
34978be3 3038 }
1e3baf05
DM
3039 }
3040
3041 my $vmname = $conf->{name} || "vm$vmid";
3042
3043 push @$cmd, '-name', $vmname;
19672434 3044
1e3baf05
DM
3045 my $sockets = 1;
3046 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3047 $sockets = $conf->{sockets} if $conf->{sockets};
3048
3049 my $cores = $conf->{cores} || 1;
3bd18e48 3050
de9d1e55 3051 my $maxcpus = $sockets * $cores;
76267728 3052
de9d1e55 3053 my $vcpus = $conf->{vcpus} ? $conf->{vcpus} : $maxcpus;
76267728 3054
de9d1e55
AD
3055 my $allowed_vcpus = $cpuinfo->{cpus};
3056
6965d5d1 3057 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
de9d1e55
AD
3058 if ($allowed_vcpus < $maxcpus);
3059
69c81430 3060 if($hotplug_features->{cpu} && qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 7)) {
1e3baf05 3061
69c81430
AD
3062 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3063 for (my $i = 2; $i <= $vcpus; $i++) {
3064 my $cpustr = print_cpu_device($conf,$i);
3065 push @$cmd, '-device', $cpustr;
3066 }
3067
3068 } else {
3069
3070 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3071 }
1e3baf05
DM
3072 push @$cmd, '-nodefaults';
3073
32baffb4 3074 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
3b408e82 3075
0888fdce
DM
3076 my $bootindex_hash = {};
3077 my $i = 1;
3078 foreach my $o (split(//, $bootorder)) {
3079 $bootindex_hash->{$o} = $i*100;
3080 $i++;
afdb31d5 3081 }
3b408e82 3082
dbea4415 3083 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
1e3baf05 3084
6b64503e 3085 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
1e3baf05 3086
6b64503e 3087 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
1e3baf05 3088
ef5e2be2 3089 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
1e3baf05 3090
b7be4ba9
AD
3091 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3092 my $socket = vnc_socket($vmid);
3093 push @$cmd, '-vnc', "unix:$socket,x509,password";
3094 } else {
3095 push @$cmd, '-nographic';
3096 }
3097
1e3baf05 3098 # time drift fix
6b64503e 3099 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
1e3baf05 3100
8c559505 3101 my $useLocaltime = $conf->{localtime};
1e3baf05 3102
4317f69f
AD
3103 if ($winversion >= 5) { # windows
3104 $useLocaltime = 1 if !defined($conf->{localtime});
7a131888 3105
4317f69f
AD
3106 # use time drift fix when acpi is enabled
3107 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
3108 $tdf = 1 if !defined($conf->{tdf});
462e8d19 3109 }
4317f69f 3110 }
462e8d19 3111
4317f69f
AD
3112 if ($winversion >= 6) {
3113 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3114 push @$cmd, '-no-hpet';
1e3baf05
DM
3115 }
3116
8c559505
DM
3117 push @$rtcFlags, 'driftfix=slew' if $tdf;
3118
74c02ef7 3119 if (!$kvm) {
8c559505 3120 push @$machineFlags, 'accel=tcg';
7f0b5beb 3121 }
1e3baf05 3122
952958bc
DM
3123 if ($machine_type) {
3124 push @$machineFlags, "type=${machine_type}";
3bafc510
DM
3125 }
3126
8c559505
DM
3127 if ($conf->{startdate}) {
3128 push @$rtcFlags, "base=$conf->{startdate}";
3129 } elsif ($useLocaltime) {
3130 push @$rtcFlags, 'base=localtime';
3131 }
1e3baf05 3132
74c02ef7 3133 my $cpu = $kvm ? "kvm64" : "qemu64";
16a91d65 3134 if (my $cputype = $conf->{cpu}) {
ff6ffe20 3135 my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
16a91d65
WB
3136 or die "Cannot parse cpu description: $cputype\n";
3137 $cpu = $cpuconf->{cputype};
3138 $kvm_off = 1 if $cpuconf->{hidden};
3139 }
519ed28c 3140
4dc339e7
AD
3141 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3142
d853f40a
DM
3143 push @$cpuFlags , '-x2apic'
3144 if $conf->{ostype} && $conf->{ostype} eq 'solaris';
519ed28c 3145
2e1a5389
AD
3146 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3147
0dc48c3d
AD
3148 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3149
117a0414
AD
3150 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
3151
74c02ef7
PA
3152 push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
3153 push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
117a0414
AD
3154 }
3155
74c02ef7 3156 add_hyperv_enlightenments($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios}, $gpu_passthrough) if $kvm;
4317f69f 3157
74c02ef7 3158 push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm;
dac7c619 3159
16a91d65
WB
3160 push @$cpuFlags, 'kvm=off' if $kvm_off;
3161
8930da74
DM
3162 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3163 die "internal error"; # should not happen
3164
3165 push @$cpuFlags, "vendor=${cpu_vendor}"
3166 if $cpu_vendor ne 'default';
3167
be190583 3168 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
519ed28c 3169
dac7c619 3170 push @$cmd, '-cpu', $cpu;
519ed28c 3171
0567a4d5
AD
3172 PVE::QemuServer::Memory::config($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3173
1e3baf05
DM
3174 push @$cmd, '-S' if $conf->{freeze};
3175
3176 # set keyboard layout
3177 my $kb = $conf->{keyboard} || $defaults->{keyboard};
3178 push @$cmd, '-k', $kb if $kb;
3179
3180 # enable sound
3181 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3182 #push @$cmd, '-soundhw', 'es1370';
3183 #push @$cmd, '-soundhw', $soundhw if $soundhw;
ab6a046f 3184
bc84dcca 3185 if($conf->{agent}) {
7a6c2150 3186 my $qgasocket = qmp_socket($vmid, 1);
ab6a046f
AD
3187 my $pciaddr = print_pci_addr("qga0", $bridges);
3188 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3189 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3190 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3191 }
3192
1d794448 3193 my $spice_port;
2fa3151e 3194
590e698c
DM
3195 if ($qxlnum) {
3196 if ($qxlnum > 1) {
ac087616 3197 if ($winversion){
590e698c
DM
3198 for(my $i = 1; $i < $qxlnum; $i++){
3199 my $pciaddr = print_pci_addr("vga$i", $bridges);
3200 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3201 }
3202 } else {
3203 # assume other OS works like Linux
3204 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3205 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2fa3151e
AD
3206 }
3207 }
3208
1011b570 3209 my $pciaddr = print_pci_addr("spice", $bridges);
95a4b4a9 3210
af0eba7e
WB
3211 my $nodename = PVE::INotify::nodename();
3212 my $pfamily = PVE::Tools::get_host_address_family($nodename);
91152441
WB
3213 my @nodeaddrs = PVE::Tools::getaddrinfo_all('localhost', family => $pfamily);
3214 die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
3215 my $localhost = PVE::Network::addr_to_ip($nodeaddrs[0]->{addr});
3216 $spice_port = PVE::Tools::next_spice_port($pfamily, $localhost);
943340a6 3217
91152441 3218 push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
1011b570 3219
d2da6d9b
AD
3220 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3221 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3222 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
1011b570
DM
3223 }
3224
8d9ae0d2
DM
3225 # enable balloon by default, unless explicitly disabled
3226 if (!defined($conf->{balloon}) || $conf->{balloon}) {
3227 $pciaddr = print_pci_addr("balloon0", $bridges);
3228 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3229 }
1e3baf05 3230
0ea9541d
DM
3231 if ($conf->{watchdog}) {
3232 my $wdopts = parse_watchdog($conf->{watchdog});
5bdcf937 3233 $pciaddr = print_pci_addr("watchdog", $bridges);
0a40e8ea 3234 my $watchdog = $wdopts->{model} || 'i6300esb';
5bdcf937
AD
3235 push @$devices, '-device', "$watchdog$pciaddr";
3236 push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
0ea9541d
DM
3237 }
3238
1e3baf05 3239 my $vollist = [];
941e0c42 3240 my $scsicontroller = {};
26ee04b6 3241 my $ahcicontroller = {};
cdd20088 3242 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : $defaults->{scsihw};
1e3baf05 3243
5881b913
DM
3244 # Add iscsi initiator name if available
3245 if (my $initiator = get_initiator_name()) {
3246 push @$devices, '-iscsi', "initiator-name=$initiator";
3247 }
3248
1e3baf05
DM
3249 foreach_drive($conf, sub {
3250 my ($ds, $drive) = @_;
3251
ff1a2432 3252 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
1e3baf05 3253 push @$vollist, $drive->{file};
ff1a2432 3254 }
afdb31d5 3255
4dcce9ee
TL
3256 # ignore efidisk here, already added in bios/fw handling code above
3257 return if $drive->{interface} eq 'efidisk';
3258
1e3baf05 3259 $use_virtio = 1 if $ds =~ m/^virtio/;
3b408e82
DM
3260
3261 if (drive_is_cdrom ($drive)) {
3262 if ($bootindex_hash->{d}) {
3263 $drive->{bootindex} = $bootindex_hash->{d};
3264 $bootindex_hash->{d} += 1;
3265 }
3266 } else {
3267 if ($bootindex_hash->{c}) {
3268 $drive->{bootindex} = $bootindex_hash->{c} if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
3269 $bootindex_hash->{c} += 1;
3270 }
3271 }
3272
51f492cd
AD
3273 if($drive->{interface} eq 'virtio'){
3274 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread};
3275 }
3276
941e0c42 3277 if ($drive->{interface} eq 'scsi') {
cdd20088 3278
ee034f5c 3279 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
6731a4cf 3280
6731a4cf 3281 $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges);
a1b7d579 3282 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ? "virtio-scsi-pci" : $scsihw;
fc8b40fd
AD
3283
3284 my $iothread = '';
3285 if($conf->{scsihw} && $conf->{scsihw} eq "virtio-scsi-single" && $drive->{iothread}){
3286 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3287 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
e7a5104d
DC
3288 } elsif ($drive->{iothread}) {
3289 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
fc8b40fd
AD
3290 }
3291
6e11f143
AD
3292 my $queues = '';
3293 if($conf->{scsihw} && $conf->{scsihw} eq "virtio-scsi-single" && $drive->{queues}){
3294 $queues = ",num_queues=$drive->{queues}";
3295 }
3296
3297 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
cdd20088 3298 $scsicontroller->{$controller}=1;
941e0c42 3299 }
3b408e82 3300
26ee04b6
DA
3301 if ($drive->{interface} eq 'sata') {
3302 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
5bdcf937
AD
3303 $pciaddr = print_pci_addr("ahci$controller", $bridges);
3304 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
26ee04b6
DA
3305 $ahcicontroller->{$controller}=1;
3306 }
46f58b5f 3307
15b21acc
MR
3308 my $drive_cmd = print_drive_full($storecfg, $vmid, $drive);
3309 push @$devices, '-drive',$drive_cmd;
46f58b5f 3310 push @$devices, '-device', print_drivedevice_full($storecfg, $conf, $vmid, $drive, $bridges);
1e3baf05
DM
3311 });
3312
cc4d6182 3313 for (my $i = 0; $i < $MAX_NETS; $i++) {
5f0c4c32 3314 next if !$conf->{"net$i"};
cc4d6182
DA
3315 my $d = parse_net($conf->{"net$i"});
3316 next if !$d;
1e3baf05 3317
cc4d6182 3318 $use_virtio = 1 if $d->{model} eq 'virtio';
1e3baf05 3319
cc4d6182
DA
3320 if ($bootindex_hash->{n}) {
3321 $d->{bootindex} = $bootindex_hash->{n};
3322 $bootindex_hash->{n} += 1;
3323 }
1e3baf05 3324
cc4d6182 3325 my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i");
5bdcf937
AD
3326 push @$devices, '-netdev', $netdevfull;
3327
ba9e1000 3328 my $netdevicefull = print_netdevice_full($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
5bdcf937
AD
3329 push @$devices, '-device', $netdevicefull;
3330 }
1e3baf05 3331
db656e5f
DM
3332 if (!$q35) {
3333 # add pci bridges
fc79e813
AD
3334 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
3335 $bridges->{1} = 1;
3336 $bridges->{2} = 1;
3337 }
3338
6731a4cf
AD
3339 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3340
f8e83f05
AD
3341 while (my ($k, $v) = each %$bridges) {
3342 $pciaddr = print_pci_addr("pci.$k");
3343 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3344 }
19672434
DM
3345 }
3346
1e3baf05
DM
3347 # add custom args
3348 if ($conf->{args}) {
3ada46c9 3349 my $aa = PVE::Tools::split_args($conf->{args});
1e3baf05
DM
3350 push @$cmd, @$aa;
3351 }
3352
5bdcf937 3353 push @$cmd, @$devices;
be190583 3354 push @$cmd, '-rtc', join(',', @$rtcFlags)
8c559505 3355 if scalar(@$rtcFlags);
be190583 3356 push @$cmd, '-machine', join(',', @$machineFlags)
8c559505
DM
3357 if scalar(@$machineFlags);
3358 push @$cmd, '-global', join(',', @$globalFlags)
3359 if scalar(@$globalFlags);
3360
1d794448 3361 return wantarray ? ($cmd, $vollist, $spice_port) : $cmd;
1e3baf05 3362}
19672434 3363
1e3baf05
DM
3364sub vnc_socket {
3365 my ($vmid) = @_;
3366 return "${var_run_tmpdir}/$vmid.vnc";
3367}
3368
943340a6 3369sub spice_port {
1011b570 3370 my ($vmid) = @_;
943340a6 3371
1d794448 3372 my $res = vm_mon_cmd($vmid, 'query-spice');
943340a6
DM
3373
3374 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
1011b570
DM
3375}
3376
c971c4f2 3377sub qmp_socket {
693d12a2
AD
3378 my ($vmid, $qga) = @_;
3379 my $sockettype = $qga ? 'qga' : 'qmp';
3380 return "${var_run_tmpdir}/$vmid.$sockettype";
c971c4f2
AD
3381}
3382
1e3baf05
DM
3383sub pidfile_name {
3384 my ($vmid) = @_;
3385 return "${var_run_tmpdir}/$vmid.pid";
3386}
3387
86fdcfb2
DA
3388sub vm_devices_list {
3389 my ($vmid) = @_;
3390
ceea9078 3391 my $res = vm_mon_cmd($vmid, 'query-pci');
ceea9078
DM
3392 my $devices = {};
3393 foreach my $pcibus (@$res) {
3394 foreach my $device (@{$pcibus->{devices}}) {
6e62a21f 3395 next if !$device->{'qdev_id'};
200644a7 3396 if ($device->{'pci_bridge'}) {
200644a7
AD
3397 $devices->{$device->{'qdev_id'}} = 1;
3398 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices}}) {
3399 next if !$bridge_device->{'qdev_id'};
3400 $devices->{$bridge_device->{'qdev_id'}} = 1;
3401 $devices->{$device->{'qdev_id'}}++;
3402 }
3403 } else {
200644a7
AD
3404 $devices->{$device->{'qdev_id'}} = 1;
3405 }
f78cc802
AD
3406 }
3407 }
3408
3409 my $resblock = vm_mon_cmd($vmid, 'query-block');
3410 foreach my $block (@$resblock) {
3411 if($block->{device} =~ m/^drive-(\S+)/){
3412 $devices->{$1} = 1;
1dc4f496
DM
3413 }
3414 }
86fdcfb2 3415
3d7389fe
DM
3416 my $resmice = vm_mon_cmd($vmid, 'query-mice');
3417 foreach my $mice (@$resmice) {
3418 if ($mice->{name} eq 'QEMU HID Tablet') {
3419 $devices->{tablet} = 1;
3420 last;
3421 }
3422 }
3423
deb091c5
DC
3424 # for usb devices there is no query-usb
3425 # but we can iterate over the entries in
3426 # qom-list path=/machine/peripheral
3427 my $resperipheral = vm_mon_cmd($vmid, 'qom-list', path => '/machine/peripheral');
3428 foreach my $per (@$resperipheral) {
3429 if ($per->{name} =~ m/^usb\d+$/) {
3430 $devices->{$per->{name}} = 1;
3431 }
3432 }
3433
1dc4f496 3434 return $devices;
86fdcfb2
DA
3435}
3436
ec21aa11 3437sub vm_deviceplug {
f19d1c47 3438 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
ae57f6b3 3439
db656e5f
DM
3440 my $q35 = machine_type_is_q35($conf);
3441
95d6343b
DA
3442 my $devices_list = vm_devices_list($vmid);
3443 return 1 if defined($devices_list->{$deviceid});
3444
fee46675
DM
3445 qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3446
3d7389fe 3447 if ($deviceid eq 'tablet') {
fee46675 3448
3d7389fe 3449 qemu_deviceadd($vmid, print_tabletdevice_full($conf));
3d7389fe 3450
4eb68604
DC
3451 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3452
f745762b
DC
3453 die "usb hotplug currently not reliable\n";
3454 # since we can't reliably hot unplug all added usb devices
3455 # and usb passthrough disables live migration
3456 # we disable usb hotplugging for now
4eb68604
DC
3457 qemu_deviceadd($vmid, PVE::QemuServer::USB::print_usbdevice_full($conf, $deviceid, $device));
3458
fee46675 3459 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
40f28a9f 3460
22de899a
AD
3461 qemu_iothread_add($vmid, $deviceid, $device);
3462
fee46675 3463 qemu_driveadd($storecfg, $vmid, $device);
cdd20088 3464 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
fee46675 3465
5e5dcb73 3466 qemu_deviceadd($vmid, $devicefull);
fee46675
DM
3467 eval { qemu_deviceaddverify($vmid, $deviceid); };
3468 if (my $err = $@) {
63c2da2f
DM
3469 eval { qemu_drivedel($vmid, $deviceid); };
3470 warn $@ if $@;
fee46675 3471 die $err;
5e5dcb73 3472 }
cfc817c7 3473
2733141c 3474 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
fee46675 3475
fc8b40fd 3476
cdd20088 3477 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
cfc817c7 3478 my $pciaddr = print_pci_addr($deviceid);
a1b7d579 3479 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ? "virtio-scsi-pci" : $scsihw;
2733141c
AD
3480
3481 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
fee46675 3482
fc8b40fd
AD
3483 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread}) {
3484 qemu_iothread_add($vmid, $deviceid, $device);
3485 $devicefull .= ",iothread=iothread-$deviceid";
3486 }
3487
6e11f143
AD
3488 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues}) {
3489 $devicefull .= ",num_queues=$device->{queues}";
3490 }
3491
cfc817c7 3492 qemu_deviceadd($vmid, $devicefull);
fee46675 3493 qemu_deviceaddverify($vmid, $deviceid);
cfc817c7 3494
fee46675
DM
3495 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3496
3497 qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
3498 qemu_driveadd($storecfg, $vmid, $device);
a1b7d579 3499
fee46675
DM
3500 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
3501 eval { qemu_deviceadd($vmid, $devicefull); };
3502 if (my $err = $@) {
63c2da2f
DM
3503 eval { qemu_drivedel($vmid, $deviceid); };
3504 warn $@ if $@;
fee46675 3505 die $err;
a4f091a0 3506 }
a4f091a0 3507
fee46675
DM
3508 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3509
2630d2a9 3510 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
8718099c
AD
3511
3512 my $machine_type = PVE::QemuServer::qemu_machine_pxe($vmid, $conf);
3513 my $use_old_bios_files = undef;
3514 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
3515
3516 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
2630d2a9 3517 qemu_deviceadd($vmid, $netdevicefull);
fee46675
DM
3518 eval { qemu_deviceaddverify($vmid, $deviceid); };
3519 if (my $err = $@) {
3520 eval { qemu_netdevdel($vmid, $deviceid); };
3521 warn $@ if $@;
3522 die $err;
2630d2a9 3523 }
2630d2a9 3524
fee46675 3525 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
b467f79a 3526
40f28a9f
AD
3527 my $bridgeid = $2;
3528 my $pciaddr = print_pci_addr($deviceid);
3529 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
a1b7d579 3530
40f28a9f 3531 qemu_deviceadd($vmid, $devicefull);
fee46675
DM
3532 qemu_deviceaddverify($vmid, $deviceid);
3533
3534 } else {
a1b7d579 3535 die "can't hotplug device '$deviceid'\n";
40f28a9f
AD
3536 }
3537
5e5dcb73 3538 return 1;
a4dea331
DA
3539}
3540
3eec5767 3541# fixme: this should raise exceptions on error!
ec21aa11 3542sub vm_deviceunplug {
f19d1c47 3543 my ($vmid, $conf, $deviceid) = @_;
873c2d69 3544
95d6343b
DA
3545 my $devices_list = vm_devices_list($vmid);
3546 return 1 if !defined($devices_list->{$deviceid});
3547
63c2da2f
DM
3548 die "can't unplug bootdisk" if $conf->{bootdisk} && $conf->{bootdisk} eq $deviceid;
3549
3d7389fe 3550 if ($deviceid eq 'tablet') {
63c2da2f 3551
3d7389fe 3552 qemu_devicedel($vmid, $deviceid);
3d7389fe 3553
4eb68604
DC
3554 } elsif ($deviceid =~ m/^usb\d+$/) {
3555
f745762b
DC
3556 die "usb hotplug currently not reliable\n";
3557 # when unplugging usb devices this way,
3558 # there may be remaining usb controllers/hubs
3559 # so we disable it for now
4eb68604
DC
3560 qemu_devicedel($vmid, $deviceid);
3561 qemu_devicedelverify($vmid, $deviceid);
3562
63c2da2f 3563 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
f19d1c47 3564
5e5dcb73 3565 qemu_devicedel($vmid, $deviceid);
63c2da2f
DM
3566 qemu_devicedelverify($vmid, $deviceid);
3567 qemu_drivedel($vmid, $deviceid);
22de899a
AD
3568 qemu_iothread_del($conf, $vmid, $deviceid);
3569
2733141c 3570 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
a1b7d579 3571
63c2da2f 3572 qemu_devicedel($vmid, $deviceid);
8ce30dde 3573 qemu_devicedelverify($vmid, $deviceid);
fc8b40fd 3574 qemu_iothread_del($conf, $vmid, $deviceid);
a1b7d579 3575
63c2da2f 3576 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
cfc817c7 3577
8bcf3068
AD
3578 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3579 my $device = parse_drive($deviceid, $conf->{$deviceid});
3580 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread};
3581
63c2da2f
DM
3582 qemu_devicedel($vmid, $deviceid);
3583 qemu_drivedel($vmid, $deviceid);
a1b7d579 3584 qemu_deletescsihw($conf, $vmid, $deviceid);
8ce30dde 3585
63c2da2f 3586 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
a4f091a0 3587
2630d2a9 3588 qemu_devicedel($vmid, $deviceid);
63c2da2f
DM
3589 qemu_devicedelverify($vmid, $deviceid);
3590 qemu_netdevdel($vmid, $deviceid);
3591
3592 } else {
3593 die "can't unplug device '$deviceid'\n";
2630d2a9
DA
3594 }
3595
5e5dcb73
DA
3596 return 1;
3597}
3598
3599sub qemu_deviceadd {
3600 my ($vmid, $devicefull) = @_;
873c2d69 3601
d695b5b7
AD
3602 $devicefull = "driver=".$devicefull;
3603 my %options = split(/[=,]/, $devicefull);
f19d1c47 3604
d695b5b7 3605 vm_mon_cmd($vmid, "device_add" , %options);
5e5dcb73 3606}
afdb31d5 3607
5e5dcb73 3608sub qemu_devicedel {
fee46675 3609 my ($vmid, $deviceid) = @_;
63c2da2f 3610
5a77d8c1 3611 my $ret = vm_mon_cmd($vmid, "device_del", id => $deviceid);
5e5dcb73
DA
3612}
3613
22de899a
AD
3614sub qemu_iothread_add {
3615 my($vmid, $deviceid, $device) = @_;
3616
3617 if ($device->{iothread}) {
3618 my $iothreads = vm_iothreads_list($vmid);
3619 qemu_objectadd($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3620 }
3621}
3622
3623sub qemu_iothread_del {
3624 my($conf, $vmid, $deviceid) = @_;
3625
3626 my $device = parse_drive($deviceid, $conf->{$deviceid});
3627 if ($device->{iothread}) {
3628 my $iothreads = vm_iothreads_list($vmid);
3629 qemu_objectdel($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3630 }
3631}
3632
4d3f29ed
AD
3633sub qemu_objectadd {
3634 my($vmid, $objectid, $qomtype) = @_;
3635
3636 vm_mon_cmd($vmid, "object-add", id => $objectid, "qom-type" => $qomtype);
3637
3638 return 1;
3639}
3640
3641sub qemu_objectdel {
3642 my($vmid, $objectid) = @_;
3643
3644 vm_mon_cmd($vmid, "object-del", id => $objectid);
3645
3646 return 1;
3647}
3648
5e5dcb73 3649sub qemu_driveadd {
fee46675 3650 my ($storecfg, $vmid, $device) = @_;
5e5dcb73
DA
3651
3652 my $drive = print_drive_full($storecfg, $vmid, $device);
7a69fc3c 3653 $drive =~ s/\\/\\\\/g;
8ead5ec7 3654 my $ret = vm_human_monitor_command($vmid, "drive_add auto \"$drive\"");
fee46675 3655
5e5dcb73 3656 # If the command succeeds qemu prints: "OK"
fee46675
DM
3657 return 1 if $ret =~ m/OK/s;
3658
3659 die "adding drive failed: $ret\n";
5e5dcb73 3660}
afdb31d5 3661
5e5dcb73
DA
3662sub qemu_drivedel {
3663 my($vmid, $deviceid) = @_;
873c2d69 3664
7b7c6d1b 3665 my $ret = vm_human_monitor_command($vmid, "drive_del drive-$deviceid");
5e5dcb73 3666 $ret =~ s/^\s+//;
a1b7d579 3667
63c2da2f 3668 return 1 if $ret eq "";
a1b7d579 3669
63c2da2f 3670 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
a1b7d579
DM
3671 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3672
63c2da2f 3673 die "deleting drive $deviceid failed : $ret\n";
5e5dcb73 3674}
f19d1c47 3675
5e5dcb73 3676sub qemu_deviceaddverify {
fee46675 3677 my ($vmid, $deviceid) = @_;
873c2d69 3678
5e5dcb73
DA
3679 for (my $i = 0; $i <= 5; $i++) {
3680 my $devices_list = vm_devices_list($vmid);
3681 return 1 if defined($devices_list->{$deviceid});
3682 sleep 1;
afdb31d5 3683 }
fee46675
DM
3684
3685 die "error on hotplug device '$deviceid'\n";
5e5dcb73 3686}
afdb31d5 3687
5e5dcb73
DA
3688
3689sub qemu_devicedelverify {
63c2da2f
DM
3690 my ($vmid, $deviceid) = @_;
3691
a1b7d579 3692 # need to verify that the device is correctly removed as device_del
63c2da2f 3693 # is async and empty return is not reliable
5e5dcb73 3694
5e5dcb73
DA
3695 for (my $i = 0; $i <= 5; $i++) {
3696 my $devices_list = vm_devices_list($vmid);
3697 return 1 if !defined($devices_list->{$deviceid});
3698 sleep 1;
afdb31d5 3699 }
63c2da2f
DM
3700
3701 die "error on hot-unplugging device '$deviceid'\n";
873c2d69
DA
3702}
3703
cdd20088 3704sub qemu_findorcreatescsihw {
cfc817c7
DA
3705 my ($storecfg, $conf, $vmid, $device) = @_;
3706
ee034f5c 3707 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
2733141c
AD
3708
3709 my $scsihwid="$controller_prefix$controller";
cfc817c7
DA
3710 my $devices_list = vm_devices_list($vmid);
3711
cdd20088 3712 if(!defined($devices_list->{$scsihwid})) {
fc8b40fd 3713 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
cfc817c7 3714 }
fee46675 3715
cfc817c7
DA
3716 return 1;
3717}
3718
8ce30dde
AD
3719sub qemu_deletescsihw {
3720 my ($conf, $vmid, $opt) = @_;
3721
3722 my $device = parse_drive($opt, $conf->{$opt});
3723
a1511b3c 3724 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
2733141c
AD
3725 vm_deviceunplug($vmid, $conf, "virtioscsi$device->{index}");
3726 return 1;
3727 }
3728
ee034f5c 3729 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
8ce30dde
AD
3730
3731 my $devices_list = vm_devices_list($vmid);
3732 foreach my $opt (keys %{$devices_list}) {
74479ee9 3733 if (PVE::QemuServer::is_valid_drivename($opt)) {
8ce30dde
AD
3734 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3735 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3736 return 1;
3737 }
3738 }
3739 }
3740
3741 my $scsihwid="scsihw$controller";
3742
3743 vm_deviceunplug($vmid, $conf, $scsihwid);
3744
3745 return 1;
3746}
3747
281fedb3 3748sub qemu_add_pci_bridge {
40f28a9f
AD
3749 my ($storecfg, $conf, $vmid, $device) = @_;
3750
3751 my $bridges = {};
281fedb3
DM
3752
3753 my $bridgeid;
3754
40f28a9f
AD
3755 print_pci_addr($device, $bridges);
3756
3757 while (my ($k, $v) = each %$bridges) {
3758 $bridgeid = $k;
3759 }
fee46675 3760 return 1 if !defined($bridgeid) || $bridgeid < 1;
281fedb3 3761
40f28a9f
AD
3762 my $bridge = "pci.$bridgeid";
3763 my $devices_list = vm_devices_list($vmid);
3764
281fedb3 3765 if (!defined($devices_list->{$bridge})) {
fee46675 3766 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
40f28a9f 3767 }
281fedb3 3768
40f28a9f
AD
3769 return 1;
3770}
3771
25088687
DM
3772sub qemu_set_link_status {
3773 my ($vmid, $device, $up) = @_;
3774
a1b7d579 3775 vm_mon_cmd($vmid, "set_link", name => $device,
25088687
DM
3776 up => $up ? JSON::true : JSON::false);
3777}
3778
2630d2a9
DA
3779sub qemu_netdevadd {
3780 my ($vmid, $conf, $device, $deviceid) = @_;
3781
208ba94e 3782 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
73aa03b8 3783 my %options = split(/[=,]/, $netdev);
2630d2a9 3784
73aa03b8
AD
3785 vm_mon_cmd($vmid, "netdev_add", %options);
3786 return 1;
2630d2a9
DA
3787}
3788
3789sub qemu_netdevdel {
3790 my ($vmid, $deviceid) = @_;
3791
89c1e0f4 3792 vm_mon_cmd($vmid, "netdev_del", id => $deviceid);
2630d2a9
DA
3793}
3794
16521d63
DC
3795sub qemu_usb_hotplug {
3796 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3797
3798 return if !$device;
3799
3800 # remove the old one first
3801 vm_deviceunplug($vmid, $conf, $deviceid);
3802
3803 # check if xhci controller is necessary and available
3804 if ($device->{usb3}) {
3805
3806 my $devicelist = vm_devices_list($vmid);
3807
3808 if (!$devicelist->{xhci}) {
3809 my $pciaddr = print_pci_addr("xhci");
3810 qemu_deviceadd($vmid, "nec-usb-xhci,id=xhci$pciaddr");
3811 }
3812 }
3813 my $d = parse_usb_device($device->{host});
3814 $d->{usb3} = $device->{usb3};
3815
3816 # add the new one
3817 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3818}
3819
838776ab 3820sub qemu_cpu_hotplug {
8edc9c08 3821 my ($vmid, $conf, $vcpus) = @_;
838776ab 3822
1e881b75
AD
3823 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3824
8edc9c08
AD
3825 my $sockets = 1;
3826 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3827 $sockets = $conf->{sockets} if $conf->{sockets};
3828 my $cores = $conf->{cores} || 1;
3829 my $maxcpus = $sockets * $cores;
838776ab 3830
8edc9c08 3831 $vcpus = $maxcpus if !$vcpus;
3a11fadb 3832
8edc9c08
AD
3833 die "you can't add more vcpus than maxcpus\n"
3834 if $vcpus > $maxcpus;
3a11fadb 3835
8edc9c08 3836 my $currentvcpus = $conf->{vcpus} || $maxcpus;
1e881b75 3837
eba3e64d 3838 if ($vcpus < $currentvcpus) {
1e881b75
AD
3839
3840 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3841
3842 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3843 qemu_devicedel($vmid, "cpu$i");
3844 my $retry = 0;
3845 my $currentrunningvcpus = undef;
3846 while (1) {
3847 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3848 last if scalar(@{$currentrunningvcpus}) == $i-1;
961af8a3 3849 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
1e881b75
AD
3850 $retry++;
3851 sleep 1;
3852 }
3853 #update conf after each succesfull cpu unplug
3854 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3855 PVE::QemuConfig->write_config($vmid, $conf);
3856 }
3857 } else {
961af8a3 3858 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
1e881b75
AD
3859 }
3860
3861 return;
3862 }
838776ab 3863
8edc9c08 3864 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
961af8a3 3865 die "vcpus in running vm does not match its configuration\n"
8edc9c08 3866 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
838776ab 3867
eba3e64d
AD
3868 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3869
3870 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3871 my $cpustr = print_cpu_device($conf, $i);
3872 qemu_deviceadd($vmid, $cpustr);
3873
3874 my $retry = 0;
3875 my $currentrunningvcpus = undef;
3876 while (1) {
3877 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3878 last if scalar(@{$currentrunningvcpus}) == $i;
961af8a3 3879 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
eba3e64d
AD
3880 sleep 1;
3881 $retry++;
3882 }
3883 #update conf after each succesfull cpu hotplug
3884 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3885 PVE::QemuConfig->write_config($vmid, $conf);
3886 }
3887 } else {
3888
3889 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3890 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3891 }
838776ab
AD
3892 }
3893}
3894
affd2f88 3895sub qemu_block_set_io_throttle {
277ca170
WB
3896 my ($vmid, $deviceid,
3897 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
9196a8ec
WB
3898 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3899 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3900 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
affd2f88 3901
f3f323a3
AD
3902 return if !check_running($vmid) ;
3903
277ca170
WB
3904 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3905 bps => int($bps),
3906 bps_rd => int($bps_rd),
3907 bps_wr => int($bps_wr),
3908 iops => int($iops),
3909 iops_rd => int($iops_rd),
3910 iops_wr => int($iops_wr),
3911 bps_max => int($bps_max),
3912 bps_rd_max => int($bps_rd_max),
3913 bps_wr_max => int($bps_wr_max),
3914 iops_max => int($iops_max),
3915 iops_rd_max => int($iops_rd_max),
9196a8ec
WB
3916 iops_wr_max => int($iops_wr_max),
3917 bps_max_length => int($bps_max_length),
3918 bps_rd_max_length => int($bps_rd_max_length),
3919 bps_wr_max_length => int($bps_wr_max_length),
3920 iops_max_length => int($iops_max_length),
3921 iops_rd_max_length => int($iops_rd_max_length),
3922 iops_wr_max_length => int($iops_wr_max_length),
277ca170 3923 );
f3f323a3 3924
affd2f88
AD
3925}
3926
f5eb281a 3927# old code, only used to shutdown old VM after update
dab36e1e
DM
3928sub __read_avail {
3929 my ($fh, $timeout) = @_;
3930
3931 my $sel = new IO::Select;
3932 $sel->add($fh);
3933
3934 my $res = '';
3935 my $buf;
3936
3937 my @ready;
3938 while (scalar (@ready = $sel->can_read($timeout))) {
3939 my $count;
3940 if ($count = $fh->sysread($buf, 8192)) {
3941 if ($buf =~ /^(.*)\(qemu\) $/s) {
3942 $res .= $1;
3943 last;
3944 } else {
3945 $res .= $buf;
3946 }
3947 } else {
3948 if (!defined($count)) {
3949 die "$!\n";
3950 }
3951 last;
3952 }
3953 }
3954
3955 die "monitor read timeout\n" if !scalar(@ready);
f5eb281a 3956
dab36e1e
DM
3957 return $res;
3958}
3959
f5eb281a 3960# old code, only used to shutdown old VM after update
dab36e1e
DM
3961sub vm_monitor_command {
3962 my ($vmid, $cmdstr, $nocheck) = @_;
f5eb281a 3963
dab36e1e
DM
3964 my $res;
3965
3966 eval {
3967 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3968
3969 my $sname = "${var_run_tmpdir}/$vmid.mon";
3970
3971 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3972 die "unable to connect to VM $vmid socket - $!\n";
3973
3974 my $timeout = 3;
3975
3976 # hack: migrate sometime blocks the monitor (when migrate_downtime
3977 # is set)
3978 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3979 $timeout = 60*60; # 1 hour
3980 }
3981
3982 # read banner;
3983 my $data = __read_avail($sock, $timeout);
3984
3985 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3986 die "got unexpected qemu monitor banner\n";
3987 }
3988
3989 my $sel = new IO::Select;
3990 $sel->add($sock);
3991
3992 if (!scalar(my @ready = $sel->can_write($timeout))) {
3993 die "monitor write error - timeout";
3994 }
3995
3996 my $fullcmd = "$cmdstr\r";
3997
3998 # syslog('info', "VM $vmid monitor command: $cmdstr");
3999
4000 my $b;
4001 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4002 die "monitor write error - $!";
4003 }
4004
4005 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
4006
4007 $timeout = 20;
4008
4009 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4010 $timeout = 60*60; # 1 hour
4011 } elsif ($cmdstr =~ m/^(eject|change)/) {
4012 $timeout = 60; # note: cdrom mount command is slow
4013 }
4014 if ($res = __read_avail($sock, $timeout)) {
4015
4016 my @lines = split("\r?\n", $res);
f5eb281a 4017
dab36e1e 4018 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
f5eb281a 4019
dab36e1e
DM
4020 $res = join("\n", @lines);
4021 $res .= "\n";
4022 }
4023 };
4024
4025 my $err = $@;
4026
4027 if ($err) {
4028 syslog("err", "VM $vmid monitor command failed - $err");
4029 die $err;
4030 }
f5eb281a 4031
dab36e1e
DM
4032 return $res;
4033}
4034
c1175c92
AD
4035sub qemu_block_resize {
4036 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4037
ed221350 4038 my $running = check_running($vmid);
c1175c92 4039
7246e8f9 4040 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
c1175c92
AD
4041
4042 return if !$running;
4043
4044 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4045
4046}
4047
1ab0057c
AD
4048sub qemu_volume_snapshot {
4049 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4050
ed221350 4051 my $running = check_running($vmid);
1ab0057c 4052
e5eaa028
WL
4053 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4054 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4055 } else {
4056 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4057 }
1ab0057c
AD
4058}
4059
fc46aff9
AD
4060sub qemu_volume_snapshot_delete {
4061 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4062
ed221350 4063 my $running = check_running($vmid);
fc46aff9 4064
1ef7592f
AD
4065 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4066 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4067 } else {
4068 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4069 }
fc46aff9
AD
4070}
4071
264e519f
DM
4072sub set_migration_caps {
4073 my ($vmid) = @_;
a89fded1 4074
8b8345f3 4075 my $cap_ref = [];
a89fded1
AD
4076
4077 my $enabled_cap = {
8b8345f3 4078 "auto-converge" => 1,
0b0a47e8 4079 "xbzrle" => 1,
8b8345f3
DM
4080 "x-rdma-pin-all" => 0,
4081 "zero-blocks" => 0,
b62532e4 4082 "compress" => 0
a89fded1
AD
4083 };
4084
8b8345f3 4085 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
a89fded1 4086
8b8345f3 4087 for my $supported_capability (@$supported_capabilities) {
b463a3ce
SP
4088 push @$cap_ref, {
4089 capability => $supported_capability->{capability},
22430fa2
DM
4090 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4091 };
a89fded1
AD
4092 }
4093
8b8345f3
DM
4094 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4095}
a89fded1 4096
81d95ae1 4097my $fast_plug_option = {
7498eb64 4098 'lock' => 1,
81d95ae1 4099 'name' => 1,
a1b7d579 4100 'onboot' => 1,
81d95ae1
DM
4101 'shares' => 1,
4102 'startup' => 1,
b0ec896e 4103 'description' => 1,
ec647db4 4104 'protection' => 1,
8cad5e9b 4105 'vmstatestorage' => 1,
81d95ae1
DM
4106};
4107
3a11fadb
DM
4108# hotplug changes in [PENDING]
4109# $selection hash can be used to only apply specified options, for
4110# example: { cores => 1 } (only apply changed 'cores')
4111# $errors ref is used to return error messages
c427973b 4112sub vmconfig_hotplug_pending {
3a11fadb 4113 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
c427973b 4114
8e90138a 4115 my $defaults = load_defaults();
c427973b
DM
4116
4117 # commit values which do not have any impact on running VM first
3a11fadb
DM
4118 # Note: those option cannot raise errors, we we do not care about
4119 # $selection and always apply them.
4120
4121 my $add_error = sub {
4122 my ($opt, $msg) = @_;
4123 $errors->{$opt} = "hotplug problem - $msg";
4124 };
c427973b
DM
4125
4126 my $changes = 0;
4127 foreach my $opt (keys %{$conf->{pending}}) { # add/change
81d95ae1 4128 if ($fast_plug_option->{$opt}) {
c427973b
DM
4129 $conf->{$opt} = $conf->{pending}->{$opt};
4130 delete $conf->{pending}->{$opt};
4131 $changes = 1;
4132 }
4133 }
4134
4135 if ($changes) {
ffda963f
FG
4136 PVE::QemuConfig->write_config($vmid, $conf);
4137 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
c427973b
DM
4138 }
4139
b3c2bdd1 4140 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
c427973b 4141
3dc38fbb
WB
4142 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4143 while (my ($opt, $force) = each %$pending_delete_hash) {
3a11fadb 4144 next if $selection && !$selection->{$opt};
3a11fadb 4145 eval {
51a6f637
AD
4146 if ($opt eq 'hotplug') {
4147 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4148 } elsif ($opt eq 'tablet') {
b3c2bdd1 4149 die "skip\n" if !$hotplug_features->{usb};
3a11fadb
DM
4150 if ($defaults->{tablet}) {
4151 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4152 } else {
4153 vm_deviceunplug($vmid, $conf, $opt);
4154 }
4eb68604 4155 } elsif ($opt =~ m/^usb\d+/) {
f745762b
DC
4156 die "skip\n";
4157 # since we cannot reliably hot unplug usb devices
4158 # we are disabling it
4eb68604
DC
4159 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4160 vm_deviceunplug($vmid, $conf, $opt);
8edc9c08 4161 } elsif ($opt eq 'vcpus') {
b3c2bdd1 4162 die "skip\n" if !$hotplug_features->{cpu};
8edc9c08 4163 qemu_cpu_hotplug($vmid, $conf, undef);
9c2f7069 4164 } elsif ($opt eq 'balloon') {
81d95ae1
DM
4165 # enable balloon device is not hotpluggable
4166 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4167 } elsif ($fast_plug_option->{$opt}) {
4168 # do nothing
3eec5767 4169 } elsif ($opt =~ m/^net(\d+)$/) {
b3c2bdd1 4170 die "skip\n" if !$hotplug_features->{network};
3eec5767 4171 vm_deviceunplug($vmid, $conf, $opt);
74479ee9 4172 } elsif (is_valid_drivename($opt)) {
b3c2bdd1 4173 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
19120f99 4174 vm_deviceunplug($vmid, $conf, $opt);
3dc38fbb 4175 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4d3f29ed
AD
4176 } elsif ($opt =~ m/^memory$/) {
4177 die "skip\n" if !$hotplug_features->{memory};
6779f1ac 4178 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
c8effec3
AD
4179 } elsif ($opt eq 'cpuunits') {
4180 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
58be00f1
AD
4181 } elsif ($opt eq 'cpulimit') {
4182 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
3d7389fe 4183 } else {
e56beeda 4184 die "skip\n";
3d7389fe 4185 }
3a11fadb
DM
4186 };
4187 if (my $err = $@) {
e56beeda
DM
4188 &$add_error($opt, $err) if $err ne "skip\n";
4189 } else {
3a11fadb
DM
4190 # save new config if hotplug was successful
4191 delete $conf->{$opt};
4192 vmconfig_undelete_pending_option($conf, $opt);
ffda963f
FG
4193 PVE::QemuConfig->write_config($vmid, $conf);
4194 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3d7389fe 4195 }
3d7389fe
DM
4196 }
4197
4198 foreach my $opt (keys %{$conf->{pending}}) {
3a11fadb 4199 next if $selection && !$selection->{$opt};
3d7389fe 4200 my $value = $conf->{pending}->{$opt};
3a11fadb 4201 eval {
51a6f637
AD
4202 if ($opt eq 'hotplug') {
4203 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4204 } elsif ($opt eq 'tablet') {
b3c2bdd1 4205 die "skip\n" if !$hotplug_features->{usb};
3a11fadb
DM
4206 if ($value == 1) {
4207 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4208 } elsif ($value == 0) {
4209 vm_deviceunplug($vmid, $conf, $opt);
4210 }
4eb68604 4211 } elsif ($opt =~ m/^usb\d+$/) {
f745762b
DC
4212 die "skip\n";
4213 # since we cannot reliably hot unplug usb devices
4214 # we are disabling it
4eb68604
DC
4215 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4216 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4217 die "skip\n" if !$d;
4218 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
8edc9c08 4219 } elsif ($opt eq 'vcpus') {
b3c2bdd1 4220 die "skip\n" if !$hotplug_features->{cpu};
3a11fadb
DM
4221 qemu_cpu_hotplug($vmid, $conf, $value);
4222 } elsif ($opt eq 'balloon') {
81d95ae1 4223 # enable/disable balloning device is not hotpluggable
8fe689e7 4224 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
a1b7d579 4225 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
81d95ae1
DM
4226 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4227
3a11fadb 4228 # allow manual ballooning if shares is set to zero
4cc1efa6 4229 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
9c2f7069
AD
4230 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4231 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4232 }
a1b7d579 4233 } elsif ($opt =~ m/^net(\d+)$/) {
3eec5767 4234 # some changes can be done without hotplug
a1b7d579 4235 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
b3c2bdd1 4236 $vmid, $opt, $value);
74479ee9 4237 } elsif (is_valid_drivename($opt)) {
a05cff86 4238 # some changes can be done without hotplug
b3c2bdd1
DM
4239 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4240 $vmid, $opt, $value, 1);
4d3f29ed
AD
4241 } elsif ($opt =~ m/^memory$/) { #dimms
4242 die "skip\n" if !$hotplug_features->{memory};
6779f1ac 4243 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
c8effec3
AD
4244 } elsif ($opt eq 'cpuunits') {
4245 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
58be00f1 4246 } elsif ($opt eq 'cpulimit') {
c6f773b8 4247 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
58be00f1 4248 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
3a11fadb 4249 } else {
e56beeda 4250 die "skip\n"; # skip non-hot-pluggable options
3d7389fe 4251 }
3a11fadb
DM
4252 };
4253 if (my $err = $@) {
e56beeda
DM
4254 &$add_error($opt, $err) if $err ne "skip\n";
4255 } else {
3a11fadb
DM
4256 # save new config if hotplug was successful
4257 $conf->{$opt} = $value;
4258 delete $conf->{pending}->{$opt};
ffda963f
FG
4259 PVE::QemuConfig->write_config($vmid, $conf);
4260 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3d7389fe 4261 }
3d7389fe 4262 }
c427973b 4263}
055d554d 4264
3dc38fbb
WB
4265sub try_deallocate_drive {
4266 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4267
4268 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4269 my $volid = $drive->{file};
4270 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4271 my $sid = PVE::Storage::parse_volume_id($volid);
4272 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
cee01bcb
WB
4273
4274 # check if the disk is really unused
cee01bcb 4275 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
77019edf 4276 if is_volume_in_use($storecfg, $conf, $key, $volid);
cee01bcb 4277 PVE::Storage::vdisk_free($storecfg, $volid);
3dc38fbb 4278 return 1;
40b977f3
WL
4279 } else {
4280 # If vm is not owner of this disk remove from config
4281 return 1;
3dc38fbb
WB
4282 }
4283 }
4284
4285 return undef;
4286}
4287
4288sub vmconfig_delete_or_detach_drive {
4289 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4290
4291 my $drive = parse_drive($opt, $conf->{$opt});
4292
4293 my $rpcenv = PVE::RPCEnvironment::get();
4294 my $authuser = $rpcenv->get_user();
4295
4296 if ($force) {
4297 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4298 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4299 } else {
4300 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4301 }
4302}
4303
055d554d 4304sub vmconfig_apply_pending {
3a11fadb 4305 my ($vmid, $conf, $storecfg) = @_;
c427973b
DM
4306
4307 # cold plug
055d554d 4308
3dc38fbb
WB
4309 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4310 while (my ($opt, $force) = each %$pending_delete_hash) {
055d554d 4311 die "internal error" if $opt =~ m/^unused/;
ffda963f 4312 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4313 if (!defined($conf->{$opt})) {
4314 vmconfig_undelete_pending_option($conf, $opt);
ffda963f 4315 PVE::QemuConfig->write_config($vmid, $conf);
74479ee9 4316 } elsif (is_valid_drivename($opt)) {
3dc38fbb 4317 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
055d554d
DM
4318 vmconfig_undelete_pending_option($conf, $opt);
4319 delete $conf->{$opt};
ffda963f 4320 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4321 } else {
4322 vmconfig_undelete_pending_option($conf, $opt);
4323 delete $conf->{$opt};
ffda963f 4324 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4325 }
4326 }
4327
ffda963f 4328 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4329
4330 foreach my $opt (keys %{$conf->{pending}}) { # add/change
ffda963f 4331 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4332
4333 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4334 # skip if nothing changed
74479ee9 4335 } elsif (is_valid_drivename($opt)) {
055d554d
DM
4336 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4337 if defined($conf->{$opt});
4338 $conf->{$opt} = $conf->{pending}->{$opt};
4339 } else {
4340 $conf->{$opt} = $conf->{pending}->{$opt};
4341 }
4342
4343 delete $conf->{pending}->{$opt};
ffda963f 4344 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4345 }
4346}
4347
3eec5767
DM
4348my $safe_num_ne = sub {
4349 my ($a, $b) = @_;
4350
4351 return 0 if !defined($a) && !defined($b);
4352 return 1 if !defined($a);
4353 return 1 if !defined($b);
4354
4355 return $a != $b;
4356};
4357
4358my $safe_string_ne = sub {
4359 my ($a, $b) = @_;
4360
4361 return 0 if !defined($a) && !defined($b);
4362 return 1 if !defined($a);
4363 return 1 if !defined($b);
4364
4365 return $a ne $b;
4366};
4367
4368sub vmconfig_update_net {
b3c2bdd1 4369 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
3eec5767
DM
4370
4371 my $newnet = parse_net($value);
4372
4373 if ($conf->{$opt}) {
4374 my $oldnet = parse_net($conf->{$opt});
4375
4376 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4377 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4378 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4379 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4380
4381 # for non online change, we try to hot-unplug
7196b757 4382 die "skip\n" if !$hotplug;
3eec5767
DM
4383 vm_deviceunplug($vmid, $conf, $opt);
4384 } else {
4385
4386 die "internal error" if $opt !~ m/net(\d+)/;
4387 my $iface = "tap${vmid}i$1";
a1b7d579 4388
25088687
DM
4389 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4390 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
16d08ecf 4391 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
25088687 4392 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
3eec5767 4393 PVE::Network::tap_unplug($iface);
4f4fbeb0
WB
4394 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4395 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4396 # Rate can be applied on its own but any change above needs to
4397 # include the rate in tap_plug since OVS resets everything.
4398 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
3eec5767 4399 }
38c590d9 4400
25088687
DM
4401 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4402 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4403 }
4404
38c590d9 4405 return 1;
3eec5767
DM
4406 }
4407 }
a1b7d579 4408
7196b757 4409 if ($hotplug) {
38c590d9
DM
4410 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4411 } else {
4412 die "skip\n";
4413 }
3eec5767
DM
4414}
4415
a05cff86 4416sub vmconfig_update_disk {
b3c2bdd1 4417 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
a05cff86
DM
4418
4419 # fixme: do we need force?
4420
4421 my $drive = parse_drive($opt, $value);
4422
4423 if ($conf->{$opt}) {
4424
4425 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4426
4427 my $media = $drive->{media} || 'disk';
4428 my $oldmedia = $old_drive->{media} || 'disk';
4429 die "unable to change media type\n" if $media ne $oldmedia;
4430
4431 if (!drive_is_cdrom($old_drive)) {
4432
a1b7d579 4433 if ($drive->{file} ne $old_drive->{file}) {
a05cff86 4434
7196b757 4435 die "skip\n" if !$hotplug;
a05cff86
DM
4436
4437 # unplug and register as unused
4438 vm_deviceunplug($vmid, $conf, $opt);
4439 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
a1b7d579 4440
a05cff86
DM
4441 } else {
4442 # update existing disk
4443
4444 # skip non hotpluggable value
6ecfbb44 4445 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
22de899a 4446 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
6e11f143 4447 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
a05cff86
DM
4448 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4449 die "skip\n";
4450 }
4451
4452 # apply throttle
4453 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4454 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4455 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4456 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4457 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4458 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4459 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4460 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4461 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4462 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4463 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
9196a8ec
WB
4464 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4465 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4466 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4467 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4468 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4469 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4470 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
a1b7d579 4471
a05cff86
DM
4472 qemu_block_set_io_throttle($vmid,"drive-$opt",
4473 ($drive->{mbps} || 0)*1024*1024,
4474 ($drive->{mbps_rd} || 0)*1024*1024,
4475 ($drive->{mbps_wr} || 0)*1024*1024,
4476 $drive->{iops} || 0,
4477 $drive->{iops_rd} || 0,
4478 $drive->{iops_wr} || 0,
4479 ($drive->{mbps_max} || 0)*1024*1024,
4480 ($drive->{mbps_rd_max} || 0)*1024*1024,
4481 ($drive->{mbps_wr_max} || 0)*1024*1024,
4482 $drive->{iops_max} || 0,
4483 $drive->{iops_rd_max} || 0,
9196a8ec
WB
4484 $drive->{iops_wr_max} || 0,
4485 $drive->{bps_max_length} || 1,
4486 $drive->{bps_rd_max_length} || 1,
4487 $drive->{bps_wr_max_length} || 1,
4488 $drive->{iops_max_length} || 1,
4489 $drive->{iops_rd_max_length} || 1,
4490 $drive->{iops_wr_max_length} || 1);
a05cff86
DM
4491
4492 }
a1b7d579 4493
a05cff86
DM
4494 return 1;
4495 }
4de1bb25
DM
4496
4497 } else { # cdrom
a1b7d579 4498
4de1bb25
DM
4499 if ($drive->{file} eq 'none') {
4500 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4501 } else {
4502 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4503 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4504 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4505 }
a1b7d579 4506
34758d66 4507 return 1;
a05cff86
DM
4508 }
4509 }
4510 }
4511
a1b7d579 4512 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4de1bb25 4513 # hotplug new disks
f7b4356f 4514 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4de1bb25 4515 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
a05cff86
DM
4516}
4517
1e3baf05 4518sub vm_start {
ba9e1000 4519 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
2189246c 4520 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
1e3baf05 4521
ffda963f
FG
4522 PVE::QemuConfig->lock_config($vmid, sub {
4523 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
1e3baf05 4524
ffda963f 4525 die "you can't start a vm if it's a template\n" if PVE::QemuConfig->is_template($conf);
3dcb98d5 4526
ffda963f 4527 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 4528
7e8dcf2c 4529 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
1e3baf05 4530
055d554d 4531 if (!$statefile && scalar(keys %{$conf->{pending}})) {
3a11fadb 4532 vmconfig_apply_pending($vmid, $conf, $storecfg);
ffda963f 4533 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4534 }
4535
6c47d546
DM
4536 my $defaults = load_defaults();
4537
4538 # set environment variable useful inside network script
4539 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4540
2189246c
AD
4541 my $local_volumes = {};
4542
3b4cf0f0 4543 if ($targetstorage) {
2189246c
AD
4544 foreach_drive($conf, sub {
4545 my ($ds, $drive) = @_;
4546
4547 return if drive_is_cdrom($drive);
4548
4549 my $volid = $drive->{file};
4550
4551 return if !$volid;
4552
4553 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
4554
4555 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4556 return if $scfg->{shared};
4557 $local_volumes->{$ds} = [$volid, $storeid, $volname];
4558 });
4559
4560 my $format = undef;
4561
4562 foreach my $opt (sort keys %$local_volumes) {
4563
4564 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
4565 my $drive = parse_drive($opt, $conf->{$opt});
4566
4567 #if remote storage is specified, use default format
4568 if ($targetstorage && $targetstorage ne "1") {
4569 $storeid = $targetstorage;
4570 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4571 $format = $defFormat;
4572 } else {
4573 #else we use same format than original
4574 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4575 $format = qemu_img_format($scfg, $volid);
4576 }
4577
4578 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
4579 my $newdrive = $drive;
4580 $newdrive->{format} = $format;
4581 $newdrive->{file} = $newvolid;
4582 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
4583 $local_volumes->{$opt} = $drivestr;
4584 #pass drive to conf for command line
4585 $conf->{$opt} = $drivestr;
4586 }
4587 }
4588
67812f9c 4589 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
6c47d546 4590
1e3baf05 4591 my $migrate_port = 0;
5bc1e039 4592 my $migrate_uri;
1e3baf05
DM
4593 if ($statefile) {
4594 if ($statefile eq 'tcp') {
5bc1e039
SP
4595 my $localip = "localhost";
4596 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
af0eba7e 4597 my $nodename = PVE::INotify::nodename();
2de2d6f7 4598
b7a5a225
TL
4599 if (!defined($migration_type)) {
4600 if (defined($datacenterconf->{migration}->{type})) {
4601 $migration_type = $datacenterconf->{migration}->{type};
4602 } else {
4603 $migration_type = 'secure';
4604 }
4605 }
4606
2de2d6f7
TL
4607 if ($migration_type eq 'insecure') {
4608 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4609 if ($migrate_network_addr) {
4610 $localip = $migrate_network_addr;
4611 } else {
5bc1e039 4612 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
2de2d6f7
TL
4613 }
4614
4615 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
5bc1e039 4616 }
2de2d6f7 4617
af0eba7e
WB
4618 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4619 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
407e0b8b 4620 $migrate_uri = "tcp:${localip}:${migrate_port}";
6c47d546
DM
4621 push @$cmd, '-incoming', $migrate_uri;
4622 push @$cmd, '-S';
1c9d54bf
TL
4623
4624 } elsif ($statefile eq 'unix') {
4625 # should be default for secure migrations as a ssh TCP forward
4626 # tunnel is not deterministic reliable ready and fails regurarly
4627 # to set up in time, so use UNIX socket forwards
54323eed
TL
4628 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4629 unlink $socket_addr;
4630
4631 $migrate_uri = "unix:$socket_addr";
1c9d54bf
TL
4632
4633 push @$cmd, '-incoming', $migrate_uri;
4634 push @$cmd, '-S';
4635
1e3baf05 4636 } else {
6c47d546 4637 push @$cmd, '-loadstate', $statefile;
1e3baf05 4638 }
91bd6c90
DM
4639 } elsif ($paused) {
4640 push @$cmd, '-S';
1e3baf05
DM
4641 }
4642
1e3baf05 4643 # host pci devices
040b06b7
DA
4644 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4645 my $d = parse_hostpci($conf->{"hostpci$i"});
4646 next if !$d;
b1f72af6
AD
4647 my $pcidevices = $d->{pciid};
4648 foreach my $pcidevice (@$pcidevices) {
4649 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
000fc0a2 4650
b1f72af6
AD
4651 my $info = pci_device_info("0000:$pciid");
4652 die "IOMMU not present\n" if !check_iommu_support();
4653 die "no pci device info for device '$pciid'\n" if !$info;
6ea8cd3b 4654 die "can't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
8f3e88af 4655 die "can't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
b1f72af6 4656 }
040b06b7 4657 }
1e3baf05
DM
4658
4659 PVE::Storage::activate_volumes($storecfg, $vollist);
4660
2b401189
AD
4661 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4662 my $cmd = [];
4663 push @$cmd, '/bin/systemctl', 'stop', "$vmid.scope";
4664 eval { run_command($cmd); };
4665 }
4666
8e59d952
WB
4667 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4668 : $defaults->{cpuunits};
4669
7023f3ea
AD
4670 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4671
4672 my %properties = (
4673 Slice => 'qemu.slice',
4674 KillMode => 'none',
4675 CPUShares => $cpuunits
4676 );
4677
4678 if (my $cpulimit = $conf->{cpulimit}) {
4679 $properties{CPUQuota} = int($cpulimit * 100);
4680 }
4681 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4682
4683 if ($conf->{hugepages}) {
4684
4685 my $code = sub {
4686 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4687 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4688
4689 PVE::QemuServer::Memory::hugepages_mount();
4690 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4691
4692 eval {
4693 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4694 run_command($cmd, %run_params);
4695 };
4696
4697 if (my $err = $@) {
4698 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4699 die $err;
4700 }
4701
4702 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4703 };
4704 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4705
4706 } else {
4707 eval {
4708 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4709 run_command($cmd, %run_params);
4710 };
4711 }
77cde36b
DC
4712
4713 if (my $err = $@) {
4714 # deactivate volumes if start fails
4715 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4716 die "start failed: $err";
4717 }
1e3baf05 4718
5bc1e039 4719 print "migration listens on $migrate_uri\n" if $migrate_uri;
afdb31d5 4720
b37ecfe6 4721 if ($statefile && $statefile ne 'tcp' && $statefile ne 'unix') {
95381ce0 4722 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
8c609afd 4723 warn $@ if $@;
62de2cbd
DM
4724 }
4725
2189246c
AD
4726 #start nbd server for storage migration
4727 if ($targetstorage) {
2189246c
AD
4728 my $nodename = PVE::INotify::nodename();
4729 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4730 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
4731 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4732 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4733
4734 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet', data => { host => "${localip}", port => "${migrate_port}" } } );
4735
4736 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4737
4738 foreach my $opt (sort keys %$local_volumes) {
4739 my $volid = $local_volumes->{$opt};
4740 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
4741 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
4742 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
4743 }
4744 }
4745
1d794448 4746 if ($migratedfrom) {
a89fded1 4747 eval {
8e90138a 4748 set_migration_caps($vmid);
a89fded1 4749 };
1d794448 4750 warn $@ if $@;
a89fded1 4751
1d794448
DM
4752 if ($spice_port) {
4753 print "spice listens on port $spice_port\n";
4754 if ($spice_ticket) {
8e90138a
DM
4755 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice', password => $spice_ticket);
4756 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice', time => "+30");
95a4b4a9
AD
4757 }
4758 }
4759
1d794448 4760 } else {
15b1fc93 4761 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
be190583 4762 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4ec05c4c 4763 if $conf->{balloon};
4ec05c4c 4764 }
25088687
DM
4765
4766 foreach my $opt (keys %$conf) {
4767 next if $opt !~ m/^net\d+$/;
4768 my $nicconf = parse_net($conf->{$opt});
4769 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4770 }
e18b0b99 4771 }
a1b7d579 4772
eb065317
AD
4773 vm_mon_cmd_nocheck($vmid, 'qom-set',
4774 path => "machine/peripheral/balloon0",
4775 property => "guest-stats-polling-interval",
4776 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4777
1e3baf05
DM
4778 });
4779}
4780
0eedc444
AD
4781sub vm_mon_cmd {
4782 my ($vmid, $execute, %params) = @_;
4783
26f11676
DM
4784 my $cmd = { execute => $execute, arguments => \%params };
4785 vm_qmp_command($vmid, $cmd);
0eedc444
AD
4786}
4787
4788sub vm_mon_cmd_nocheck {
4789 my ($vmid, $execute, %params) = @_;
4790
26f11676
DM
4791 my $cmd = { execute => $execute, arguments => \%params };
4792 vm_qmp_command($vmid, $cmd, 1);
0eedc444
AD
4793}
4794
c971c4f2 4795sub vm_qmp_command {
c5a07de5 4796 my ($vmid, $cmd, $nocheck) = @_;
97d62eb7 4797
c971c4f2 4798 my $res;
26f11676 4799
14db5366
DM
4800 my $timeout;
4801 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4802 $timeout = $cmd->{arguments}->{timeout};
4803 delete $cmd->{arguments}->{timeout};
4804 }
be190583 4805
c971c4f2
AD
4806 eval {
4807 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
7a6c2150
DM
4808 my $sname = qmp_socket($vmid);
4809 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
c5a07de5 4810 my $qmpclient = PVE::QMPClient->new();
dab36e1e 4811
14db5366 4812 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
c5a07de5 4813 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
dab36e1e
DM
4814 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4815 if scalar(%{$cmd->{arguments}});
4816 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4817 } else {
4818 die "unable to open monitor socket\n";
4819 }
c971c4f2 4820 };
26f11676 4821 if (my $err = $@) {
c971c4f2
AD
4822 syslog("err", "VM $vmid qmp command failed - $err");
4823 die $err;
4824 }
4825
4826 return $res;
4827}
4828
9df5cbcc
DM
4829sub vm_human_monitor_command {
4830 my ($vmid, $cmdline) = @_;
4831
4832 my $res;
4833
f5eb281a 4834 my $cmd = {
9df5cbcc
DM
4835 execute => 'human-monitor-command',
4836 arguments => { 'command-line' => $cmdline},
4837 };
4838
4839 return vm_qmp_command($vmid, $cmd);
4840}
4841
1e3baf05
DM
4842sub vm_commandline {
4843 my ($storecfg, $vmid) = @_;
4844
ffda963f 4845 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05
DM
4846
4847 my $defaults = load_defaults();
4848
6b64503e 4849 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 4850
5930c1ff 4851 return PVE::Tools::cmd2string($cmd);
1e3baf05
DM
4852}
4853
4854sub vm_reset {
4855 my ($vmid, $skiplock) = @_;
4856
ffda963f 4857 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4858
ffda963f 4859 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 4860
ffda963f 4861 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 4862
816e2c4a 4863 vm_mon_cmd($vmid, "system_reset");
ff1a2432
DM
4864 });
4865}
4866
4867sub get_vm_volumes {
4868 my ($conf) = @_;
1e3baf05 4869
ff1a2432 4870 my $vollist = [];
d5769dc2 4871 foreach_volid($conf, sub {
392f8b5d 4872 my ($volid, $attr) = @_;
ff1a2432 4873
d5769dc2 4874 return if $volid =~ m|^/|;
ff1a2432 4875
d5769dc2
DM
4876 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4877 return if !$sid;
ff1a2432
DM
4878
4879 push @$vollist, $volid;
1e3baf05 4880 });
ff1a2432
DM
4881
4882 return $vollist;
4883}
4884
4885sub vm_stop_cleanup {
70b04821 4886 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
ff1a2432 4887
745fed70 4888 eval {
ff1a2432 4889
254575e9
DM
4890 if (!$keepActive) {
4891 my $vollist = get_vm_volumes($conf);
4892 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4893 }
a1b7d579 4894
ab6a046f 4895 foreach my $ext (qw(mon qmp pid vnc qga)) {
961bfcb2
DM
4896 unlink "/var/run/qemu-server/${vmid}.$ext";
4897 }
a1b7d579 4898
70b04821 4899 vmconfig_apply_pending($vmid, $conf, $storecfg) if $apply_pending_changes;
745fed70
DM
4900 };
4901 warn $@ if $@; # avoid errors - just warn
1e3baf05
DM
4902}
4903
e6c3b671 4904# Note: use $nockeck to skip tests if VM configuration file exists.
254575e9
DM
4905# We need that when migration VMs to other nodes (files already moved)
4906# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
1e3baf05 4907sub vm_stop {
af30308f 4908 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
9269013a 4909
9269013a 4910 $force = 1 if !defined($force) && !$shutdown;
1e3baf05 4911
af30308f
DM
4912 if ($migratedfrom){
4913 my $pid = check_running($vmid, $nocheck, $migratedfrom);
4914 kill 15, $pid if $pid;
ffda963f 4915 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
70b04821 4916 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 0);
af30308f
DM
4917 return;
4918 }
4919
ffda963f 4920 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4921
e6c3b671 4922 my $pid = check_running($vmid, $nocheck);
ff1a2432 4923 return if !$pid;
1e3baf05 4924
ff1a2432 4925 my $conf;
e6c3b671 4926 if (!$nocheck) {
ffda963f
FG
4927 $conf = PVE::QemuConfig->load_config($vmid);
4928 PVE::QemuConfig->check_lock($conf) if !$skiplock;
7f4a5b5a 4929 if (!defined($timeout) && $shutdown && $conf->{startup}) {
38f7f26c 4930 my $opts = PVE::JSONSchema::pve_parse_startup_order($conf->{startup});
7f4a5b5a
DM
4931 $timeout = $opts->{down} if $opts->{down};
4932 }
e6c3b671 4933 }
19672434 4934
7f4a5b5a 4935 $timeout = 60 if !defined($timeout);
67fb9de6 4936
9269013a
DM
4937 eval {
4938 if ($shutdown) {
fbda7965 4939 if (defined($conf) && $conf->{agent}) {
2ea54503 4940 vm_qmp_command($vmid, { execute => "guest-shutdown" }, $nocheck);
1c0c1c17 4941 } else {
2ea54503 4942 vm_qmp_command($vmid, { execute => "system_powerdown" }, $nocheck);
1c0c1c17 4943 }
9269013a 4944 } else {
2ea54503 4945 vm_qmp_command($vmid, { execute => "quit" }, $nocheck);
afdb31d5 4946 }
9269013a 4947 };
1e3baf05
DM
4948 my $err = $@;
4949
4950 if (!$err) {
1e3baf05 4951 my $count = 0;
e6c3b671 4952 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
4953 $count++;
4954 sleep 1;
4955 }
4956
4957 if ($count >= $timeout) {
9269013a
DM
4958 if ($force) {
4959 warn "VM still running - terminating now with SIGTERM\n";
4960 kill 15, $pid;
4961 } else {
4962 die "VM quit/powerdown failed - got timeout\n";
4963 }
4964 } else {
70b04821 4965 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
9269013a 4966 return;
1e3baf05
DM
4967 }
4968 } else {
9269013a
DM
4969 if ($force) {
4970 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4971 kill 15, $pid;
4972 } else {
afdb31d5 4973 die "VM quit/powerdown failed\n";
9269013a 4974 }
1e3baf05
DM
4975 }
4976
4977 # wait again
ff1a2432 4978 $timeout = 10;
1e3baf05
DM
4979
4980 my $count = 0;
e6c3b671 4981 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
4982 $count++;
4983 sleep 1;
4984 }
4985
4986 if ($count >= $timeout) {
ff1a2432 4987 warn "VM still running - terminating now with SIGKILL\n";
1e3baf05 4988 kill 9, $pid;
ff1a2432 4989 sleep 1;
1e3baf05
DM
4990 }
4991
70b04821 4992 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
ff1a2432 4993 });
1e3baf05
DM
4994}
4995
4996sub vm_suspend {
4997 my ($vmid, $skiplock) = @_;
4998
ffda963f 4999 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5000
ffda963f 5001 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5002
e79706d4
FG
5003 PVE::QemuConfig->check_lock($conf)
5004 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
bcb7c9cf 5005
f77f91f3 5006 vm_mon_cmd($vmid, "stop");
1e3baf05
DM
5007 });
5008}
5009
5010sub vm_resume {
289e0b85 5011 my ($vmid, $skiplock, $nocheck) = @_;
1e3baf05 5012
ffda963f 5013 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5014
289e0b85 5015 if (!$nocheck) {
1e3baf05 5016
ffda963f 5017 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5018
e79706d4
FG
5019 PVE::QemuConfig->check_lock($conf)
5020 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
289e0b85
AD
5021
5022 vm_mon_cmd($vmid, "cont");
5023
5024 } else {
5025 vm_mon_cmd_nocheck($vmid, "cont");
5026 }
1e3baf05
DM
5027 });
5028}
5029
5fdbe4f0
DM
5030sub vm_sendkey {
5031 my ($vmid, $skiplock, $key) = @_;
1e3baf05 5032
ffda963f 5033 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5034
ffda963f 5035 my $conf = PVE::QemuConfig->load_config($vmid);
f5eb281a 5036
7b7c6d1b
DM
5037 # there is no qmp command, so we use the human monitor command
5038 vm_human_monitor_command($vmid, "sendkey $key");
1e3baf05
DM
5039 });
5040}
5041
5042sub vm_destroy {
5043 my ($storecfg, $vmid, $skiplock) = @_;
5044
ffda963f 5045 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5046
ffda963f 5047 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5048
ff1a2432 5049 if (!check_running($vmid)) {
15cc8784 5050 destroy_vm($storecfg, $vmid, undef, $skiplock);
ff1a2432
DM
5051 } else {
5052 die "VM $vmid is running - destroy failed\n";
1e3baf05
DM
5053 }
5054 });
5055}
5056
1e3baf05
DM
5057# pci helpers
5058
5059sub file_write {
5060 my ($filename, $buf) = @_;
5061
6b64503e 5062 my $fh = IO::File->new($filename, "w");
1e3baf05
DM
5063 return undef if !$fh;
5064
5065 my $res = print $fh $buf;
5066
5067 $fh->close();
5068
5069 return $res;
5070}
5071
5072sub pci_device_info {
5073 my ($name) = @_;
5074
5075 my $res;
5076
5077 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
5078 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
5079
5080 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
5081 return undef if !defined($irq) || $irq !~ m/^\d+$/;
5082
5083 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
5084 return undef if !defined($vendor) || $vendor !~ s/^0x//;
5085
5086 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
5087 return undef if !defined($product) || $product !~ s/^0x//;
5088
5089 $res = {
5090 name => $name,
5091 vendor => $vendor,
5092 product => $product,
5093 domain => $domain,
5094 bus => $bus,
5095 slot => $slot,
5096 func => $func,
5097 irq => $irq,
5098 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
5099 };
5100
5101 return $res;
5102}
5103
5104sub pci_dev_reset {
5105 my ($dev) = @_;
5106
5107 my $name = $dev->{name};
5108
5109 my $fn = "$pcisysfs/devices/$name/reset";
5110
6b64503e 5111 return file_write($fn, "1");
1e3baf05
DM
5112}
5113
000fc0a2
SP
5114sub pci_dev_bind_to_vfio {
5115 my ($dev) = @_;
5116
5117 my $name = $dev->{name};
5118
5119 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5120
5121 if (!-d $vfio_basedir) {
5122 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5123 }
5124 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
5125
5126 my $testdir = "$vfio_basedir/$name";
5127 return 1 if -d $testdir;
5128
5129 my $data = "$dev->{vendor} $dev->{product}";
5130 return undef if !file_write("$vfio_basedir/new_id", $data);
5131
5132 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5133 if (!file_write($fn, $name)) {
5134 return undef if -f $fn;
5135 }
5136
5137 $fn = "$vfio_basedir/bind";
5138 if (! -d $testdir) {
5139 return undef if !file_write($fn, $name);
5140 }
5141
5142 return -d $testdir;
5143}
5144
5145sub pci_dev_group_bind_to_vfio {
5146 my ($pciid) = @_;
5147
5148 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5149
5150 if (!-d $vfio_basedir) {
5151 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5152 }
5153 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
5154
5155 # get IOMMU group devices
5156 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5157 my @devs = grep /^0000:/, readdir($D);
5158 closedir($D);
5159
5160 foreach my $pciid (@devs) {
5161 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
f8fa2ed7
SP
5162
5163 # pci bridges, switches or root ports are not supported
5164 # they have a pci_bus subdirectory so skip them
5165 next if (-e "$pcisysfs/devices/$pciid/pci_bus");
5166
000fc0a2
SP
5167 my $info = pci_device_info($1);
5168 pci_dev_bind_to_vfio($info) || die "Cannot bind $pciid to vfio\n";
5169 }
5170
5171 return 1;
5172}
5173
3e16d5fc
DM
5174# vzdump restore implementaion
5175
ed221350 5176sub tar_archive_read_firstfile {
3e16d5fc 5177 my $archive = shift;
afdb31d5 5178
3e16d5fc
DM
5179 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
5180
5181 # try to detect archive type first
387ba257 5182 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
3e16d5fc 5183 die "unable to open file '$archive'\n";
387ba257 5184 my $firstfile = <$fh>;
3e16d5fc 5185 kill 15, $pid;
387ba257 5186 close $fh;
3e16d5fc
DM
5187
5188 die "ERROR: archive contaions no data\n" if !$firstfile;
5189 chomp $firstfile;
5190
5191 return $firstfile;
5192}
5193
ed221350
DM
5194sub tar_restore_cleanup {
5195 my ($storecfg, $statfile) = @_;
3e16d5fc
DM
5196
5197 print STDERR "starting cleanup\n";
5198
5199 if (my $fd = IO::File->new($statfile, "r")) {
5200 while (defined(my $line = <$fd>)) {
5201 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5202 my $volid = $2;
5203 eval {
5204 if ($volid =~ m|^/|) {
5205 unlink $volid || die 'unlink failed\n';
5206 } else {
ed221350 5207 PVE::Storage::vdisk_free($storecfg, $volid);
3e16d5fc 5208 }
afdb31d5 5209 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3e16d5fc
DM
5210 };
5211 print STDERR "unable to cleanup '$volid' - $@" if $@;
5212 } else {
5213 print STDERR "unable to parse line in statfile - $line";
afdb31d5 5214 }
3e16d5fc
DM
5215 }
5216 $fd->close();
5217 }
5218}
5219
5220sub restore_archive {
a0d1b1a2 5221 my ($archive, $vmid, $user, $opts) = @_;
3e16d5fc 5222
91bd6c90
DM
5223 my $format = $opts->{format};
5224 my $comp;
5225
5226 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5227 $format = 'tar' if !$format;
5228 $comp = 'gzip';
5229 } elsif ($archive =~ m/\.tar$/) {
5230 $format = 'tar' if !$format;
5231 } elsif ($archive =~ m/.tar.lzo$/) {
5232 $format = 'tar' if !$format;
5233 $comp = 'lzop';
5234 } elsif ($archive =~ m/\.vma$/) {
5235 $format = 'vma' if !$format;
5236 } elsif ($archive =~ m/\.vma\.gz$/) {
5237 $format = 'vma' if !$format;
5238 $comp = 'gzip';
5239 } elsif ($archive =~ m/\.vma\.lzo$/) {
5240 $format = 'vma' if !$format;
5241 $comp = 'lzop';
5242 } else {
5243 $format = 'vma' if !$format; # default
5244 }
5245
5246 # try to detect archive format
5247 if ($format eq 'tar') {
5248 return restore_tar_archive($archive, $vmid, $user, $opts);
5249 } else {
5250 return restore_vma_archive($archive, $vmid, $user, $opts, $comp);
5251 }
5252}
5253
5254sub restore_update_config_line {
5255 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5256
5257 return if $line =~ m/^\#qmdump\#/;
5258 return if $line =~ m/^\#vzdump\#/;
5259 return if $line =~ m/^lock:/;
5260 return if $line =~ m/^unused\d+:/;
5261 return if $line =~ m/^parent:/;
ca3e4fa4 5262 return if $line =~ m/^template:/; # restored VM is never a template
91bd6c90 5263
b5b99790 5264 my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
91bd6c90
DM
5265 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5266 # try to convert old 1.X settings
5267 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5268 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
5269 my ($model, $macaddr) = split(/\=/, $devconfig);
b5b99790 5270 $macaddr = PVE::Tools::random_ether_addr($dc->{mac_prefix}) if !$macaddr || $unique;
91bd6c90
DM
5271 my $net = {
5272 model => $model,
5273 bridge => "vmbr$ind",
5274 macaddr => $macaddr,
5275 };
5276 my $netstr = print_net($net);
5277
5278 print $outfd "net$cookie->{netcount}: $netstr\n";
5279 $cookie->{netcount}++;
5280 }
5281 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5282 my ($id, $netstr) = ($1, $2);
5283 my $net = parse_net($netstr);
b5b99790 5284 $net->{macaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix}) if $net->{macaddr};
91bd6c90
DM
5285 $netstr = print_net($net);
5286 print $outfd "$id: $netstr\n";
6470743f 5287 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
91bd6c90 5288 my $virtdev = $1;
907ea891 5289 my $value = $3;
d9faf790
WB
5290 my $di = parse_drive($virtdev, $value);
5291 if (defined($di->{backup}) && !$di->{backup}) {
91bd6c90 5292 print $outfd "#$line";
c0f7406e 5293 } elsif ($map->{$virtdev}) {
8fd57431 5294 delete $di->{format}; # format can change on restore
91bd6c90 5295 $di->{file} = $map->{$virtdev};
ed221350 5296 $value = print_drive($vmid, $di);
91bd6c90
DM
5297 print $outfd "$virtdev: $value\n";
5298 } else {
5299 print $outfd $line;
5300 }
5301 } else {
5302 print $outfd $line;
5303 }
5304}
5305
5306sub scan_volids {
5307 my ($cfg, $vmid) = @_;
5308
5309 my $info = PVE::Storage::vdisk_list($cfg, undef, $vmid);
5310
5311 my $volid_hash = {};
5312 foreach my $storeid (keys %$info) {
5313 foreach my $item (@{$info->{$storeid}}) {
5314 next if !($item->{volid} && $item->{size});
5996a936 5315 $item->{path} = PVE::Storage::path($cfg, $item->{volid});
91bd6c90
DM
5316 $volid_hash->{$item->{volid}} = $item;
5317 }
5318 }
5319
5320 return $volid_hash;
5321}
5322
77019edf
WB
5323sub is_volume_in_use {
5324 my ($storecfg, $conf, $skip_drive, $volid) = @_;
a8e2f942 5325
77019edf 5326 my $path = PVE::Storage::path($storecfg, $volid);
a8e2f942
DM
5327
5328 my $scan_config = sub {
5329 my ($cref, $snapname) = @_;
5330
5331 foreach my $key (keys %$cref) {
5332 my $value = $cref->{$key};
74479ee9 5333 if (is_valid_drivename($key)) {
a8e2f942
DM
5334 next if $skip_drive && $key eq $skip_drive;
5335 my $drive = parse_drive($key, $value);
5336 next if !$drive || !$drive->{file} || drive_is_cdrom($drive);
77019edf 5337 return 1 if $volid eq $drive->{file};
a8e2f942 5338 if ($drive->{file} =~ m!^/!) {
77019edf 5339 return 1 if $drive->{file} eq $path;
a8e2f942
DM
5340 } else {
5341 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
5342 next if !$storeid;
5343 my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1);
5344 next if !$scfg;
77019edf 5345 return 1 if $path eq PVE::Storage::path($storecfg, $drive->{file}, $snapname);
a8e2f942
DM
5346 }
5347 }
5348 }
77019edf
WB
5349
5350 return 0;
a8e2f942
DM
5351 };
5352
77019edf 5353 return 1 if &$scan_config($conf);
a8e2f942
DM
5354
5355 undef $skip_drive;
5356
77019edf
WB
5357 foreach my $snapname (keys %{$conf->{snapshots}}) {
5358 return 1 if &$scan_config($conf->{snapshots}->{$snapname}, $snapname);
a8e2f942
DM
5359 }
5360
77019edf 5361 return 0;
a8e2f942
DM
5362}
5363
91bd6c90
DM
5364sub update_disksize {
5365 my ($vmid, $conf, $volid_hash) = @_;
be190583 5366
91bd6c90
DM
5367 my $changes;
5368
c449137a
DC
5369 # used and unused disks
5370 my $referenced = {};
91bd6c90 5371
5996a936
DM
5372 # Note: it is allowed to define multiple storages with same path (alias), so
5373 # we need to check both 'volid' and real 'path' (two different volid can point
5374 # to the same path).
5375
c449137a 5376 my $referencedpath = {};
be190583 5377
91bd6c90
DM
5378 # update size info
5379 foreach my $opt (keys %$conf) {
74479ee9 5380 if (is_valid_drivename($opt)) {
ed221350 5381 my $drive = parse_drive($opt, $conf->{$opt});
91bd6c90
DM
5382 my $volid = $drive->{file};
5383 next if !$volid;
5384
c449137a 5385 $referenced->{$volid} = 1;
be190583 5386 if ($volid_hash->{$volid} &&
5996a936 5387 (my $path = $volid_hash->{$volid}->{path})) {
c449137a 5388 $referencedpath->{$path} = 1;
5996a936 5389 }
91bd6c90 5390
ed221350 5391 next if drive_is_cdrom($drive);
91bd6c90
DM
5392 next if !$volid_hash->{$volid};
5393
5394 $drive->{size} = $volid_hash->{$volid}->{size};
7a907ce6
DM
5395 my $new = print_drive($vmid, $drive);
5396 if ($new ne $conf->{$opt}) {
5397 $changes = 1;
5398 $conf->{$opt} = $new;
5399 }
91bd6c90
DM
5400 }
5401 }
5402
5996a936
DM
5403 # remove 'unusedX' entry if volume is used
5404 foreach my $opt (keys %$conf) {
5405 next if $opt !~ m/^unused\d+$/;
5406 my $volid = $conf->{$opt};
5407 my $path = $volid_hash->{$volid}->{path} if $volid_hash->{$volid};
c449137a 5408 if ($referenced->{$volid} || ($path && $referencedpath->{$path})) {
5996a936
DM
5409 $changes = 1;
5410 delete $conf->{$opt};
5411 }
c449137a
DC
5412
5413 $referenced->{$volid} = 1;
5414 $referencedpath->{$path} = 1 if $path;
5996a936
DM
5415 }
5416
91bd6c90
DM
5417 foreach my $volid (sort keys %$volid_hash) {
5418 next if $volid =~ m/vm-$vmid-state-/;
c449137a 5419 next if $referenced->{$volid};
5996a936
DM
5420 my $path = $volid_hash->{$volid}->{path};
5421 next if !$path; # just to be sure
c449137a 5422 next if $referencedpath->{$path};
91bd6c90 5423 $changes = 1;
8793d495 5424 PVE::QemuConfig->add_unused_volume($conf, $volid);
c449137a 5425 $referencedpath->{$path} = 1; # avoid to add more than once (aliases)
91bd6c90
DM
5426 }
5427
5428 return $changes;
5429}
5430
5431sub rescan {
5432 my ($vmid, $nolock) = @_;
5433
20519efc 5434 my $cfg = PVE::Storage::config();
91bd6c90
DM
5435
5436 my $volid_hash = scan_volids($cfg, $vmid);
5437
5438 my $updatefn = sub {
5439 my ($vmid) = @_;
5440
ffda963f 5441 my $conf = PVE::QemuConfig->load_config($vmid);
be190583 5442
ffda963f 5443 PVE::QemuConfig->check_lock($conf);
91bd6c90 5444
03da3f0d
DM
5445 my $vm_volids = {};
5446 foreach my $volid (keys %$volid_hash) {
5447 my $info = $volid_hash->{$volid};
5448 $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
5449 }
5450
5451 my $changes = update_disksize($vmid, $conf, $vm_volids);
91bd6c90 5452
ffda963f 5453 PVE::QemuConfig->write_config($vmid, $conf) if $changes;
91bd6c90
DM
5454 };
5455
5456 if (defined($vmid)) {
5457 if ($nolock) {
5458 &$updatefn($vmid);
5459 } else {
ffda963f 5460 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
91bd6c90
DM
5461 }
5462 } else {
5463 my $vmlist = config_list();
5464 foreach my $vmid (keys %$vmlist) {
5465 if ($nolock) {
5466 &$updatefn($vmid);
5467 } else {
ffda963f 5468 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
be190583 5469 }
91bd6c90
DM
5470 }
5471 }
5472}
5473
5474sub restore_vma_archive {
5475 my ($archive, $vmid, $user, $opts, $comp) = @_;
5476
5477 my $input = $archive eq '-' ? "<&STDIN" : undef;
5478 my $readfrom = $archive;
5479
5480 my $uncomp = '';
5481 if ($comp) {
5482 $readfrom = '-';
5483 my $qarchive = PVE::Tools::shellquote($archive);
5484 if ($comp eq 'gzip') {
5485 $uncomp = "zcat $qarchive|";
5486 } elsif ($comp eq 'lzop') {
5487 $uncomp = "lzop -d -c $qarchive|";
5488 } else {
5489 die "unknown compression method '$comp'\n";
5490 }
be190583 5491
91bd6c90
DM
5492 }
5493
5494 my $tmpdir = "/var/tmp/vzdumptmp$$";
5495 rmtree $tmpdir;
5496
5497 # disable interrupts (always do cleanups)
5b97ef24
TL
5498 local $SIG{INT} =
5499 local $SIG{TERM} =
5500 local $SIG{QUIT} =
5501 local $SIG{HUP} = sub { warn "got interrupt - ignored\n"; };
91bd6c90
DM
5502
5503 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5504 POSIX::mkfifo($mapfifo, 0600);
5505 my $fifofh;
5506
5507 my $openfifo = sub {
5508 open($fifofh, '>', $mapfifo) || die $!;
5509 };
5510
5511 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5512
5513 my $oldtimeout;
5514 my $timeout = 5;
5515
5516 my $devinfo = {};
5517
5518 my $rpcenv = PVE::RPCEnvironment::get();
5519
ffda963f 5520 my $conffile = PVE::QemuConfig->config_file($vmid);
91bd6c90
DM
5521 my $tmpfn = "$conffile.$$.tmp";
5522
ed221350 5523 # Note: $oldconf is undef if VM does not exists
ffda963f
FG
5524 my $cfs_path = PVE::QemuConfig->cfs_config_path($vmid);
5525 my $oldconf = PVE::Cluster::cfs_read_file($cfs_path);
ed221350 5526
91bd6c90
DM
5527 my $print_devmap = sub {
5528 my $virtdev_hash = {};
5529
5530 my $cfgfn = "$tmpdir/qemu-server.conf";
5531
5532 # we can read the config - that is already extracted
5533 my $fh = IO::File->new($cfgfn, "r") ||
5534 "unable to read qemu-server.conf - $!\n";
5535
6738ab9c 5536 my $fwcfgfn = "$tmpdir/qemu-server.fw";
3457d090
WL
5537 if (-f $fwcfgfn) {
5538 my $pve_firewall_dir = '/etc/pve/firewall';
5539 mkdir $pve_firewall_dir; # make sure the dir exists
5540 PVE::Tools::file_copy($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5541 }
6738ab9c 5542
91bd6c90
DM
5543 while (defined(my $line = <$fh>)) {
5544 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5545 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5546 die "archive does not contain data for drive '$virtdev'\n"
5547 if !$devinfo->{$devname};
5548 if (defined($opts->{storage})) {
5549 $storeid = $opts->{storage} || 'local';
5550 } elsif (!$storeid) {
5551 $storeid = 'local';
5552 }
5553 $format = 'raw' if !$format;
5554 $devinfo->{$devname}->{devname} = $devname;
5555 $devinfo->{$devname}->{virtdev} = $virtdev;
5556 $devinfo->{$devname}->{format} = $format;
5557 $devinfo->{$devname}->{storeid} = $storeid;
5558
be190583 5559 # check permission on storage
91bd6c90
DM
5560 my $pool = $opts->{pool}; # todo: do we need that?
5561 if ($user ne 'root@pam') {
5562 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5563 }
5564
5565 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5566 }
5567 }
5568
5569 foreach my $devname (keys %$devinfo) {
be190583
DM
5570 die "found no device mapping information for device '$devname'\n"
5571 if !$devinfo->{$devname}->{virtdev};
91bd6c90
DM
5572 }
5573
20519efc 5574 my $cfg = PVE::Storage::config();
ed221350
DM
5575
5576 # create empty/temp config
be190583 5577 if ($oldconf) {
ed221350
DM
5578 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
5579 foreach_drive($oldconf, sub {
5580 my ($ds, $drive) = @_;
5581
5582 return if drive_is_cdrom($drive);
5583
5584 my $volid = $drive->{file};
5585
5586 return if !$volid || $volid =~ m|^/|;
5587
5588 my ($path, $owner) = PVE::Storage::path($cfg, $volid);
5589 return if !$path || !$owner || ($owner != $vmid);
5590
5591 # Note: only delete disk we want to restore
5592 # other volumes will become unused
5593 if ($virtdev_hash->{$ds}) {
6b72854b
FG
5594 eval { PVE::Storage::vdisk_free($cfg, $volid); };
5595 if (my $err = $@) {
5596 warn $err;
5597 }
ed221350
DM
5598 }
5599 });
381b8fae
DC
5600
5601 # delete vmstate files
5602 # since after the restore we have no snapshots anymore
5603 foreach my $snapname (keys %{$oldconf->{snapshots}}) {
5604 my $snap = $oldconf->{snapshots}->{$snapname};
5605 if ($snap->{vmstate}) {
5606 eval { PVE::Storage::vdisk_free($cfg, $snap->{vmstate}); };
5607 if (my $err = $@) {
5608 warn $err;
5609 }
5610 }
5611 }
ed221350
DM
5612 }
5613
5614 my $map = {};
91bd6c90
DM
5615 foreach my $virtdev (sort keys %$virtdev_hash) {
5616 my $d = $virtdev_hash->{$virtdev};
5617 my $alloc_size = int(($d->{size} + 1024 - 1)/1024);
5618 my $scfg = PVE::Storage::storage_config($cfg, $d->{storeid});
8fd57431
DM
5619
5620 # test if requested format is supported
5621 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($cfg, $d->{storeid});
5622 my $supported = grep { $_ eq $d->{format} } @$validFormats;
5623 $d->{format} = $defFormat if !$supported;
5624
91bd6c90
DM
5625 my $volid = PVE::Storage::vdisk_alloc($cfg, $d->{storeid}, $vmid,
5626 $d->{format}, undef, $alloc_size);
5627 print STDERR "new volume ID is '$volid'\n";
5628 $d->{volid} = $volid;
5629 my $path = PVE::Storage::path($cfg, $volid);
5630
5f96f4df
WL
5631 PVE::Storage::activate_volumes($cfg,[$volid]);
5632
91bd6c90 5633 my $write_zeros = 1;
88240a83 5634 if (PVE::Storage::volume_has_feature($cfg, 'sparseinit', $volid)) {
91bd6c90
DM
5635 $write_zeros = 0;
5636 }
5637
3c525055 5638 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
91bd6c90
DM
5639
5640 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5641 $map->{$virtdev} = $volid;
5642 }
5643
5644 $fh->seek(0, 0) || die "seek failed - $!\n";
5645
5646 my $outfd = new IO::File ($tmpfn, "w") ||
5647 die "unable to write config for VM $vmid\n";
5648
5649 my $cookie = { netcount => 0 };
5650 while (defined(my $line = <$fh>)) {
be190583 5651 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
91bd6c90
DM
5652 }
5653
5654 $fh->close();
5655 $outfd->close();
5656 };
5657
5658 eval {
5659 # enable interrupts
6cb0144a
EK
5660 local $SIG{INT} =
5661 local $SIG{TERM} =
5662 local $SIG{QUIT} =
5663 local $SIG{HUP} =
5664 local $SIG{PIPE} = sub { die "interrupted by signal\n"; };
91bd6c90
DM
5665 local $SIG{ALRM} = sub { die "got timeout\n"; };
5666
5667 $oldtimeout = alarm($timeout);
5668
5669 my $parser = sub {
5670 my $line = shift;
5671
5672 print "$line\n";
5673
5674 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5675 my ($dev_id, $size, $devname) = ($1, $2, $3);
5676 $devinfo->{$devname} = { size => $size, dev_id => $dev_id };
5677 } elsif ($line =~ m/^CTIME: /) {
46f58b5f 5678 # we correctly received the vma config, so we can disable
3cf90d7a
DM
5679 # the timeout now for disk allocation (set to 10 minutes, so
5680 # that we always timeout if something goes wrong)
5681 alarm(600);
91bd6c90
DM
5682 &$print_devmap();
5683 print $fifofh "done\n";
5684 my $tmp = $oldtimeout || 0;
5685 $oldtimeout = undef;
5686 alarm($tmp);
5687 close($fifofh);
5688 }
5689 };
be190583 5690
91bd6c90
DM
5691 print "restore vma archive: $cmd\n";
5692 run_command($cmd, input => $input, outfunc => $parser, afterfork => $openfifo);
5693 };
5694 my $err = $@;
5695
5696 alarm($oldtimeout) if $oldtimeout;
5697
5f96f4df
WL
5698 my $vollist = [];
5699 foreach my $devname (keys %$devinfo) {
5700 my $volid = $devinfo->{$devname}->{volid};
5701 push @$vollist, $volid if $volid;
5702 }
5703
20519efc 5704 my $cfg = PVE::Storage::config();
5f96f4df
WL
5705 PVE::Storage::deactivate_volumes($cfg, $vollist);
5706
91bd6c90
DM
5707 unlink $mapfifo;
5708
5709 if ($err) {
5710 rmtree $tmpdir;
5711 unlink $tmpfn;
5712
91bd6c90
DM
5713 foreach my $devname (keys %$devinfo) {
5714 my $volid = $devinfo->{$devname}->{volid};
5715 next if !$volid;
5716 eval {
5717 if ($volid =~ m|^/|) {
5718 unlink $volid || die 'unlink failed\n';
5719 } else {
5720 PVE::Storage::vdisk_free($cfg, $volid);
5721 }
5722 print STDERR "temporary volume '$volid' sucessfuly removed\n";
5723 };
5724 print STDERR "unable to cleanup '$volid' - $@" if $@;
5725 }
5726 die $err;
5727 }
5728
5729 rmtree $tmpdir;
ed221350
DM
5730
5731 rename($tmpfn, $conffile) ||
91bd6c90
DM
5732 die "unable to commit configuration file '$conffile'\n";
5733
ed221350
DM
5734 PVE::Cluster::cfs_update(); # make sure we read new file
5735
91bd6c90
DM
5736 eval { rescan($vmid, 1); };
5737 warn $@ if $@;
5738}
5739
5740sub restore_tar_archive {
5741 my ($archive, $vmid, $user, $opts) = @_;
5742
9c502e26 5743 if ($archive ne '-') {
ed221350 5744 my $firstfile = tar_archive_read_firstfile($archive);
9c502e26
DM
5745 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5746 if $firstfile ne 'qemu-server.conf';
5747 }
3e16d5fc 5748
20519efc 5749 my $storecfg = PVE::Storage::config();
ebb55558 5750
ed221350 5751 # destroy existing data - keep empty config
ffda963f 5752 my $vmcfgfn = PVE::QemuConfig->config_file($vmid);
ebb55558 5753 destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
ed221350 5754
3e16d5fc
DM
5755 my $tocmd = "/usr/lib/qemu-server/qmextract";
5756
2415a446 5757 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
a0d1b1a2 5758 $tocmd .= " --pool " . PVE::Tools::shellquote($opts->{pool}) if $opts->{pool};
3e16d5fc
DM
5759 $tocmd .= ' --prealloc' if $opts->{prealloc};
5760 $tocmd .= ' --info' if $opts->{info};
5761
a0d1b1a2 5762 # tar option "xf" does not autodetect compression when read from STDIN,
9c502e26 5763 # so we pipe to zcat
2415a446
DM
5764 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
5765 PVE::Tools::shellquote("--to-command=$tocmd");
3e16d5fc
DM
5766
5767 my $tmpdir = "/var/tmp/vzdumptmp$$";
5768 mkpath $tmpdir;
5769
5770 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
5771 local $ENV{VZDUMP_VMID} = $vmid;
a0d1b1a2 5772 local $ENV{VZDUMP_USER} = $user;
3e16d5fc 5773
ffda963f 5774 my $conffile = PVE::QemuConfig->config_file($vmid);
3e16d5fc
DM
5775 my $tmpfn = "$conffile.$$.tmp";
5776
5777 # disable interrupts (always do cleanups)
6cb0144a
EK
5778 local $SIG{INT} =
5779 local $SIG{TERM} =
5780 local $SIG{QUIT} =
5781 local $SIG{HUP} = sub { print STDERR "got interrupt - ignored\n"; };
3e16d5fc 5782
afdb31d5 5783 eval {
3e16d5fc 5784 # enable interrupts
6cb0144a
EK
5785 local $SIG{INT} =
5786 local $SIG{TERM} =
5787 local $SIG{QUIT} =
5788 local $SIG{HUP} =
5789 local $SIG{PIPE} = sub { die "interrupted by signal\n"; };
3e16d5fc 5790
9c502e26
DM
5791 if ($archive eq '-') {
5792 print "extracting archive from STDIN\n";
5793 run_command($cmd, input => "<&STDIN");
5794 } else {
5795 print "extracting archive '$archive'\n";
5796 run_command($cmd);
5797 }
3e16d5fc
DM
5798
5799 return if $opts->{info};
5800
5801 # read new mapping
5802 my $map = {};
5803 my $statfile = "$tmpdir/qmrestore.stat";
5804 if (my $fd = IO::File->new($statfile, "r")) {
5805 while (defined (my $line = <$fd>)) {
5806 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5807 $map->{$1} = $2 if $1;
5808 } else {
5809 print STDERR "unable to parse line in statfile - $line\n";
5810 }
5811 }
5812 $fd->close();
5813 }
5814
5815 my $confsrc = "$tmpdir/qemu-server.conf";
5816
5817 my $srcfd = new IO::File($confsrc, "r") ||
5818 die "unable to open file '$confsrc'\n";
5819
5820 my $outfd = new IO::File ($tmpfn, "w") ||
5821 die "unable to write config for VM $vmid\n";
5822
91bd6c90 5823 my $cookie = { netcount => 0 };
3e16d5fc 5824 while (defined (my $line = <$srcfd>)) {
be190583 5825 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
3e16d5fc
DM
5826 }
5827
5828 $srcfd->close();
5829 $outfd->close();
5830 };
5831 my $err = $@;
5832
afdb31d5 5833 if ($err) {
3e16d5fc
DM
5834
5835 unlink $tmpfn;
5836
ed221350 5837 tar_restore_cleanup($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info};
afdb31d5 5838
3e16d5fc 5839 die $err;
afdb31d5 5840 }
3e16d5fc
DM
5841
5842 rmtree $tmpdir;
5843
5844 rename $tmpfn, $conffile ||
5845 die "unable to commit configuration file '$conffile'\n";
91bd6c90 5846
ed221350
DM
5847 PVE::Cluster::cfs_update(); # make sure we read new file
5848
91bd6c90
DM
5849 eval { rescan($vmid, 1); };
5850 warn $@ if $@;
3e16d5fc
DM
5851};
5852
65a5ce88 5853sub foreach_storage_used_by_vm {
18bfb361
DM
5854 my ($conf, $func) = @_;
5855
5856 my $sidhash = {};
5857
8ddbcf8b
FG
5858 foreach_drive($conf, sub {
5859 my ($ds, $drive) = @_;
5860 return if drive_is_cdrom($drive);
18bfb361
DM
5861
5862 my $volid = $drive->{file};
5863
5864 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
be190583 5865 $sidhash->{$sid} = $sid if $sid;
8ddbcf8b 5866 });
18bfb361
DM
5867
5868 foreach my $sid (sort keys %$sidhash) {
5869 &$func($sid);
5870 }
5871}
5872
e5eaa028
WL
5873sub do_snapshots_with_qemu {
5874 my ($storecfg, $volid) = @_;
5875
5876 my $storage_name = PVE::Storage::parse_volume_id($volid);
5877
116da784
WL
5878 if ($qemu_snap_storage->{$storecfg->{ids}->{$storage_name}->{type}}
5879 && !$storecfg->{ids}->{$storage_name}->{krbd}){
e5eaa028
WL
5880 return 1;
5881 }
5882
5883 if ($volid =~ m/\.(qcow2|qed)$/){
5884 return 1;
5885 }
5886
5887 return undef;
5888}
5889
4dcc780c
WL
5890sub qga_check_running {
5891 my ($vmid) = @_;
5892
5893 eval { vm_mon_cmd($vmid, "guest-ping", timeout => 3); };
5894 if ($@) {
6941ee4e 5895 warn "Qemu Guest Agent is not running - $@";
4dcc780c
WL
5896 return 0;
5897 }
5898 return 1;
5899}
5900
04a69bb4
AD
5901sub template_create {
5902 my ($vmid, $conf, $disk) = @_;
5903
04a69bb4 5904 my $storecfg = PVE::Storage::config();
04a69bb4 5905
9cd07842
DM
5906 foreach_drive($conf, sub {
5907 my ($ds, $drive) = @_;
5908
5909 return if drive_is_cdrom($drive);
5910 return if $disk && $ds ne $disk;
5911
5912 my $volid = $drive->{file};
bbd56097 5913 return if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
9cd07842 5914
04a69bb4
AD
5915 my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
5916 $drive->{file} = $voliddst;
152fe752 5917 $conf->{$ds} = print_drive($vmid, $drive);
ffda963f 5918 PVE::QemuConfig->write_config($vmid, $conf);
04a69bb4 5919 });
04a69bb4
AD
5920}
5921
5133de42 5922sub qemu_img_convert {
988e2714 5923 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5133de42
AD
5924
5925 my $storecfg = PVE::Storage::config();
5926 my ($src_storeid, $src_volname) = PVE::Storage::parse_volume_id($src_volid, 1);
5927 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
5928
5929 if ($src_storeid && $dst_storeid) {
6bb91c17
DM
5930
5931 PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);
5932
5133de42
AD
5933 my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
5934 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
5935
5936 my $src_format = qemu_img_format($src_scfg, $src_volname);
5937 my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
5938
5939 my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
5940 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
5941
5942 my $cmd = [];
eed24303 5943 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5133de42 5944 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
988e2714
WB
5945 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5946 if ($is_zero_initialized) {
5947 push @$cmd, "zeroinit:$dst_path";
5948 } else {
5949 push @$cmd, $dst_path;
5950 }
5133de42
AD
5951
5952 my $parser = sub {
5953 my $line = shift;
5954 if($line =~ m/\((\S+)\/100\%\)/){
5955 my $percent = $1;
5956 my $transferred = int($size * $percent / 100);
5957 my $remaining = $size - $transferred;
5958
5959 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5960 }
5961
5962 };
5963
5964 eval { run_command($cmd, timeout => undef, outfunc => $parser); };
5965 my $err = $@;
5966 die "copy failed: $err" if $err;
5967 }
5968}
5969
5970sub qemu_img_format {
5971 my ($scfg, $volname) = @_;
5972
d81f0f09 5973 if ($scfg->{path} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5133de42 5974 return $1;
be190583 5975 } else {
5133de42 5976 return "raw";
5133de42
AD
5977 }
5978}
5979
cfad42af 5980sub qemu_drive_mirror {
5619e74a 5981 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
cfad42af 5982
5a345967
AD
5983 $jobs = {} if !$jobs;
5984
5985 my $qemu_target;
5986 my $format;
35e4ab04 5987 $jobs->{"drive-$drive"} = {};
152fe752 5988
3b4cf0f0 5989 if ($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+):exportname=(\S+)/) {
5a345967
AD
5990 my $server = $1;
5991 my $port = $2;
35e4ab04
AD
5992 my $exportname = $3;
5993
5a345967 5994 $format = "nbd";
35e4ab04
AD
5995 my $unixsocket = "/run/qemu-server/$vmid.mirror-drive-$drive";
5996 $qemu_target = "nbd+unix:///$exportname?socket=$unixsocket";
923aaa9e 5997 my $cmd = ['socat', '-T30', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=5"];
35e4ab04
AD
5998
5999 my $pid = fork();
6000 if (!defined($pid)) {
bd2d5fe6 6001 die "forking socat tunnel failed\n";
35e4ab04
AD
6002 } elsif ($pid == 0) {
6003 exec(@$cmd);
ca5c27f0
WB
6004 warn "exec failed: $!\n";
6005 POSIX::_exit(-1);
6006 }
6007 $jobs->{"drive-$drive"}->{pid} = $pid;
35e4ab04 6008
ca5c27f0
WB
6009 my $timeout = 0;
6010 while (!-S $unixsocket) {
6011 die "nbd connection helper timed out\n"
6012 if $timeout++ > 5;
6013 sleep 1;
35e4ab04 6014 }
5a345967 6015 } else {
5a345967
AD
6016 my $storecfg = PVE::Storage::config();
6017 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid);
6018
6019 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
cfad42af 6020
5a345967 6021 $format = qemu_img_format($dst_scfg, $dst_volname);
21ccdb50 6022
5a345967 6023 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
21ccdb50 6024
5a345967
AD
6025 $qemu_target = $is_zero_initialized ? "zeroinit:$dst_path" : $dst_path;
6026 }
988e2714
WB
6027
6028 my $opts = { timeout => 10, device => "drive-$drive", mode => "existing", sync => "full", target => $qemu_target };
88383920
DM
6029 $opts->{format} = $format if $format;
6030
5a345967 6031 print "drive mirror is starting for drive-$drive\n";
21ccdb50 6032
5a345967 6033 eval { vm_mon_cmd($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
35e4ab04 6034
5a345967
AD
6035 if (my $err = $@) {
6036 eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
6037 die "mirroring error: $err";
6038 }
6039
5619e74a 6040 qemu_drive_mirror_monitor ($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
5a345967
AD
6041}
6042
6043sub qemu_drive_mirror_monitor {
5619e74a 6044 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
2e953867 6045
08ac653f 6046 eval {
5a345967
AD
6047 my $err_complete = 0;
6048
08ac653f 6049 while (1) {
5a345967
AD
6050 die "storage migration timed out\n" if $err_complete > 300;
6051
08ac653f 6052 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
08ac653f 6053
5a345967
AD
6054 my $running_mirror_jobs = {};
6055 foreach my $stat (@$stats) {
6056 next if $stat->{type} ne 'mirror';
6057 $running_mirror_jobs->{$stat->{device}} = $stat;
6058 }
08ac653f 6059
5a345967 6060 my $readycounter = 0;
67fb9de6 6061
5a345967
AD
6062 foreach my $job (keys %$jobs) {
6063
6064 if(defined($jobs->{$job}->{complete}) && !defined($running_mirror_jobs->{$job})) {
6065 print "$job : finished\n";
6066 delete $jobs->{$job};
6067 next;
6068 }
6069
bd2d5fe6 6070 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
f34ebd52 6071
5a345967
AD
6072 my $busy = $running_mirror_jobs->{$job}->{busy};
6073 my $ready = $running_mirror_jobs->{$job}->{ready};
6074 if (my $total = $running_mirror_jobs->{$job}->{len}) {
6075 my $transferred = $running_mirror_jobs->{$job}->{offset} || 0;
6076 my $remaining = $total - $transferred;
6077 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
08ac653f 6078
5a345967
AD
6079 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6080 }
f34ebd52 6081
d1782eba 6082 $readycounter++ if $running_mirror_jobs->{$job}->{ready};
5a345967 6083 }
b467f79a 6084
5a345967
AD
6085 last if scalar(keys %$jobs) == 0;
6086
6087 if ($readycounter == scalar(keys %$jobs)) {
6088 print "all mirroring jobs are ready \n";
6089 last if $skipcomplete; #do the complete later
6090
6091 if ($vmiddst && $vmiddst != $vmid) {
1a988fd2
DC
6092 my $agent_running = $qga && qga_check_running($vmid);
6093 if ($agent_running) {
5619e74a
AD
6094 print "freeze filesystem\n";
6095 eval { PVE::QemuServer::vm_mon_cmd($vmid, "guest-fsfreeze-freeze"); };
6096 } else {
6097 print "suspend vm\n";
6098 eval { PVE::QemuServer::vm_suspend($vmid, 1); };
6099 }
6100
5a345967
AD
6101 # if we clone a disk for a new target vm, we don't switch the disk
6102 PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs);
5619e74a 6103
1a988fd2 6104 if ($agent_running) {
5619e74a
AD
6105 print "unfreeze filesystem\n";
6106 eval { PVE::QemuServer::vm_mon_cmd($vmid, "guest-fsfreeze-thaw"); };
6107 } else {
6108 print "resume vm\n";
6109 eval { PVE::QemuServer::vm_resume($vmid, 1, 1); };
6110 }
6111
2e953867 6112 last;
5a345967
AD
6113 } else {
6114
6115 foreach my $job (keys %$jobs) {
6116 # try to switch the disk if source and destination are on the same guest
bd2d5fe6 6117 print "$job: Completing block job...\n";
5a345967
AD
6118
6119 eval { vm_mon_cmd($vmid, "block-job-complete", device => $job) };
6120 if ($@ =~ m/cannot be completed/) {
bd2d5fe6 6121 print "$job: Block job cannot be completed, try again.\n";
5a345967
AD
6122 $err_complete++;
6123 }else {
bd2d5fe6 6124 print "$job: Completed successfully.\n";
5a345967 6125 $jobs->{$job}->{complete} = 1;
35e4ab04 6126 eval { qemu_blockjobs_finish_tunnel($vmid, $job, $jobs->{$job}->{pid}) } ;
5a345967
AD
6127 }
6128 }
2e953867 6129 }
08ac653f 6130 }
08ac653f 6131 sleep 1;
cfad42af 6132 }
08ac653f 6133 };
88383920 6134 my $err = $@;
08ac653f 6135
88383920 6136 if ($err) {
5a345967 6137 eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
88383920
DM
6138 die "mirroring error: $err";
6139 }
6140
5a345967
AD
6141}
6142
6143sub qemu_blockjobs_cancel {
6144 my ($vmid, $jobs) = @_;
6145
6146 foreach my $job (keys %$jobs) {
bd2d5fe6 6147 print "$job: Cancelling block job\n";
5a345967
AD
6148 eval { vm_mon_cmd($vmid, "block-job-cancel", device => $job); };
6149 $jobs->{$job}->{cancel} = 1;
6150 }
6151
6152 while (1) {
6153 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
6154
6155 my $running_jobs = {};
6156 foreach my $stat (@$stats) {
6157 $running_jobs->{$stat->{device}} = $stat;
6158 }
6159
6160 foreach my $job (keys %$jobs) {
6161
bd2d5fe6
WB
6162 if (defined($jobs->{$job}->{cancel}) && !defined($running_jobs->{$job})) {
6163 print "$job: Done.\n";
35e4ab04 6164 eval { qemu_blockjobs_finish_tunnel($vmid, $job, $jobs->{$job}->{pid}) } ;
5a345967
AD
6165 delete $jobs->{$job};
6166 }
6167 }
6168
6169 last if scalar(keys %$jobs) == 0;
6170
6171 sleep 1;
cfad42af
AD
6172 }
6173}
6174
35e4ab04
AD
6175sub qemu_blockjobs_finish_tunnel {
6176 my ($vmid, $job, $cpid) = @_;
6177
6178 return if !$cpid;
6179
6180 for (my $i = 1; $i < 20; $i++) {
6181 my $waitpid = waitpid($cpid, WNOHANG);
6182 last if (defined($waitpid) && ($waitpid == $cpid));
6183
6184 if ($i == 10) {
6185 kill(15, $cpid);
6186 } elsif ($i >= 15) {
6187 kill(9, $cpid);
6188 }
6189 sleep (1);
6190 }
6191 unlink "/run/qemu-server/$vmid.mirror-$job";
6192}
6193
152fe752 6194sub clone_disk {
be190583 6195 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5619e74a 6196 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
152fe752
DM
6197
6198 my $newvolid;
6199
6200 if (!$full) {
6201 print "create linked clone of drive $drivename ($drive->{file})\n";
258e646c 6202 $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid, $snapname);
152fe752
DM
6203 push @$newvollist, $newvolid;
6204 } else {
5a345967 6205
152fe752
DM
6206 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
6207 $storeid = $storage if $storage;
6208
44549149 6209 my $dst_format = resolve_dst_disk_format($storecfg, $storeid, $volname, $format);
152fe752
DM
6210 my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3);
6211
6212 print "create full clone of drive $drivename ($drive->{file})\n";
44549149 6213 $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $dst_format, undef, ($size/1024));
152fe752
DM
6214 push @$newvollist, $newvolid;
6215
3999f370 6216 PVE::Storage::activate_volumes($storecfg, [$newvolid]);
1dbd6d30 6217
988e2714 6218 my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
152fe752 6219 if (!$running || $snapname) {
988e2714 6220 qemu_img_convert($drive->{file}, $newvolid, $size, $snapname, $sparseinit);
152fe752 6221 } else {
2e541679
AD
6222
6223 my $kvmver = get_running_qemu_version ($vmid);
6224 if (!qemu_machine_feature_enabled (undef, $kvmver, 2, 7)) {
961af8a3
WB
6225 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6226 if $drive->{iothread};
2e541679 6227 }
2af848a2 6228
5619e74a 6229 qemu_drive_mirror($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
be190583 6230 }
152fe752
DM
6231 }
6232
6233 my ($size) = PVE::Storage::volume_size_info($storecfg, $newvolid, 3);
6234
6235 my $disk = $drive;
6236 $disk->{format} = undef;
6237 $disk->{file} = $newvolid;
6238 $disk->{size} = $size;
6239
6240 return $disk;
6241}
6242
ff556cf2
DM
6243# this only works if VM is running
6244sub get_current_qemu_machine {
6245 my ($vmid) = @_;
6246
6247 my $cmd = { execute => 'query-machines', arguments => {} };
8e90138a 6248 my $res = vm_qmp_command($vmid, $cmd);
ff556cf2
DM
6249
6250 my ($current, $default);
6251 foreach my $e (@$res) {
6252 $default = $e->{name} if $e->{'is-default'};
6253 $current = $e->{name} if $e->{'is-current'};
6254 }
6255
6256 # fallback to the default machine if current is not supported by qemu
6257 return $current || $default || 'pc';
6258}
6259
98cfd8b6
AD
6260sub get_running_qemu_version {
6261 my ($vmid) = @_;
6262 my $cmd = { execute => 'query-version', arguments => {} };
6263 my $res = vm_qmp_command($vmid, $cmd);
6264 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6265}
6266
23f73120
AD
6267sub qemu_machine_feature_enabled {
6268 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6269
6270 my $current_major;
6271 my $current_minor;
6272
6273 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6274
6275 $current_major = $3;
6276 $current_minor = $4;
6277
6278 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6279
6280 $current_major = $1;
6281 $current_minor = $2;
6282 }
6283
6284 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6285
6286
6287}
6288
42dbd2ee
AD
6289sub qemu_machine_pxe {
6290 my ($vmid, $conf, $machine) = @_;
6291
6292 $machine = PVE::QemuServer::get_current_qemu_machine($vmid) if !$machine;
6293
6294 foreach my $opt (keys %$conf) {
6295 next if $opt !~ m/^net(\d+)$/;
6296 my $net = PVE::QemuServer::parse_net($conf->{$opt});
6297 next if !$net;
6298 my $romfile = PVE::QemuServer::vm_mon_cmd_nocheck($vmid, 'qom-get', path => $opt, property => 'romfile');
6299 return $machine.".pxe" if $romfile =~ m/pxe/;
6300 last;
6301 }
6302
d1363934 6303 return $machine;
42dbd2ee
AD
6304}
6305
249c4a6c
AD
6306sub qemu_use_old_bios_files {
6307 my ($machine_type) = @_;
6308
6309 return if !$machine_type;
6310
6311 my $use_old_bios_files = undef;
6312
6313 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6314 $machine_type = $1;
6315 $use_old_bios_files = 1;
6316 } else {
74cc511f 6317 my $kvmver = kvm_user_version();
249c4a6c
AD
6318 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6319 # load new efi bios files on migration. So this hack is required to allow
6320 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6321 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
74cc511f 6322 $use_old_bios_files = !qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 4);
249c4a6c
AD
6323 }
6324
6325 return ($use_old_bios_files, $machine_type);
6326}
6327
3e1f1122
TL
6328sub create_efidisk {
6329 my ($storecfg, $storeid, $vmid, $fmt) = @_;
6330
6331 die "EFI vars default image not found\n" if ! -f $OVMF_VARS;
6332
6333 my $vars_size = PVE::Tools::convert_size(-s $OVMF_VARS, 'b' => 'kb');
6334 my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
6335 PVE::Storage::activate_volumes($storecfg, [$volid]);
6336
6337 my $path = PVE::Storage::path($storecfg, $volid);
6338 eval {
6339 run_command(['/usr/bin/qemu-img', 'convert', '-n', '-f', 'raw', '-O', $fmt, $OVMF_VARS, $path]);
6340 };
6341 die "Copying EFI vars image failed: $@" if $@;
6342
6343 return ($volid, $vars_size);
6344}
6345
4543ecf0
AD
6346sub lspci {
6347
6348 my $devices = {};
6349
6350 dir_glob_foreach("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6351 my (undef, $id, $function) = @_;
6352 my $res = { id => $id, function => $function};
6353 push @{$devices->{$id}}, $res;
6354 });
6355
5ee38471
WB
6356 # Entries should be sorted by functions.
6357 foreach my $id (keys %$devices) {
6358 my $dev = $devices->{$id};
6359 $devices->{$id} = [ sort { $a->{function} <=> $b->{function} } @$dev ];
6360 }
6361
4543ecf0
AD
6362 return $devices;
6363}
6364
22de899a
AD
6365sub vm_iothreads_list {
6366 my ($vmid) = @_;
6367
6368 my $res = vm_mon_cmd($vmid, 'query-iothreads');
6369
6370 my $iothreads = {};
6371 foreach my $iothread (@$res) {
6372 $iothreads->{ $iothread->{id} } = $iothread->{"thread-id"};
6373 }
6374
6375 return $iothreads;
6376}
6377
ee034f5c
AD
6378sub scsihw_infos {
6379 my ($conf, $drive) = @_;
6380
6381 my $maxdev = 0;
6382
7fe1b688 6383 if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)) {
ee034f5c 6384 $maxdev = 7;
a1511b3c 6385 } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
ee034f5c
AD
6386 $maxdev = 1;
6387 } else {
6388 $maxdev = 256;
6389 }
6390
6391 my $controller = int($drive->{index} / $maxdev);
a1511b3c 6392 my $controller_prefix = ($conf->{scsihw} && $conf->{scsihw} eq 'virtio-scsi-single') ? "virtioscsi" : "scsihw";
ee034f5c
AD
6393
6394 return ($maxdev, $controller, $controller_prefix);
6395}
a1511b3c 6396
075e8249
PA
6397sub add_hyperv_enlightenments {
6398 my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough) = @_;
4317f69f 6399
4317f69f
AD
6400 return if $winversion < 6;
6401 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6402
5aba3953
AD
6403 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6404
4317f69f
AD
6405 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
6406 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6407 push @$cpuFlags , 'hv_vapic';
6408 push @$cpuFlags , 'hv_time';
6409 } else {
6410 push @$cpuFlags , 'hv_spinlocks=0xffff';
6411 }
6412
6413 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 6)) {
6414 push @$cpuFlags , 'hv_reset';
6415 push @$cpuFlags , 'hv_vpindex';
6416 push @$cpuFlags , 'hv_runtime';
6417 }
6418
6419 if ($winversion >= 7) {
6420 push @$cpuFlags , 'hv_relaxed';
4317f69f
AD
6421 }
6422}
6423
6424sub windows_version {
6425 my ($ostype) = @_;
6426
6427 return 0 if !$ostype;
6428
6429 my $winversion = 0;
6430
6431 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6432 $winversion = 5;
6433 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6434 $winversion = 6;
6435 } elsif ($ostype =~ m/^win(\d+)$/) {
6436 $winversion = $1;
6437 }
6438
6439 return $winversion;
6440}
6441
44549149
EK
6442sub resolve_dst_disk_format {
6443 my ($storecfg, $storeid, $src_volname, $format) = @_;
6444 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
6445
6446 if (!$format) {
6447 # if no target format is specified, use the source disk format as hint
6448 if ($src_volname) {
6449 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
6450 $format = qemu_img_format($scfg, $src_volname);
6451 } else {
6452 return $defFormat;
6453 }
6454 }
6455
6456 # test if requested format is supported - else use default
6457 my $supported = grep { $_ eq $format } @$validFormats;
6458 $format = $defFormat if !$supported;
6459 return $format;
6460}
6461
ae2fcb3b
EK
6462sub resolve_first_disk {
6463 my $conf = shift;
6464 my @disks = PVE::QemuServer::valid_drive_names();
6465 my $firstdisk;
6466 foreach my $ds (reverse @disks) {
6467 next if !$conf->{$ds};
6468 my $disk = PVE::QemuServer::parse_drive($ds, $conf->{$ds});
6469 next if PVE::QemuServer::drive_is_cdrom($disk);
6470 $firstdisk = $ds;
6471 }
6472 return $firstdisk;
6473}
6474
6475sub generate_smbios1_uuid {
6476 my ($uuid, $uuid_str);
6477 UUID::generate($uuid);
6478 UUID::unparse($uuid, $uuid_str);
6479 return "uuid=$uuid_str";
6480}
6481
65e866e5
DM
6482# bash completion helper
6483
6484sub complete_backup_archives {
6485 my ($cmdname, $pname, $cvalue) = @_;
6486
6487 my $cfg = PVE::Storage::config();
6488
6489 my $storeid;
6490
6491 if ($cvalue =~ m/^([^:]+):/) {
6492 $storeid = $1;
6493 }
6494
6495 my $data = PVE::Storage::template_list($cfg, $storeid, 'backup');
6496
6497 my $res = [];
6498 foreach my $id (keys %$data) {
6499 foreach my $item (@{$data->{$id}}) {
6500 next if $item->{format} !~ m/^vma\.(gz|lzo)$/;
6501 push @$res, $item->{volid} if defined($item->{volid});
6502 }
6503 }
6504
6505 return $res;
6506}
6507
6508my $complete_vmid_full = sub {
6509 my ($running) = @_;
6510
6511 my $idlist = vmstatus();
6512
6513 my $res = [];
6514
6515 foreach my $id (keys %$idlist) {
6516 my $d = $idlist->{$id};
6517 if (defined($running)) {
6518 next if $d->{template};
6519 next if $running && $d->{status} ne 'running';
6520 next if !$running && $d->{status} eq 'running';
6521 }
6522 push @$res, $id;
6523
6524 }
6525 return $res;
6526};
6527
6528sub complete_vmid {
6529 return &$complete_vmid_full();
6530}
6531
6532sub complete_vmid_stopped {
6533 return &$complete_vmid_full(0);
6534}
6535
6536sub complete_vmid_running {
6537 return &$complete_vmid_full(1);
6538}
6539
335af808
DM
6540sub complete_storage {
6541
6542 my $cfg = PVE::Storage::config();
6543 my $ids = $cfg->{ids};
6544
6545 my $res = [];
6546 foreach my $sid (keys %$ids) {
6547 next if !PVE::Storage::storage_check_enabled($cfg, $sid, undef, 1);
c4c844ef 6548 next if !$ids->{$sid}->{content}->{images};
335af808
DM
6549 push @$res, $sid;
6550 }
6551
6552 return $res;
6553}
6554
63a09370
AD
6555sub nbd_stop {
6556 my ($vmid) = @_;
6557
6558 vm_mon_cmd($vmid, 'nbd-server-stop');
6559}
6560
1e3baf05 65611;