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