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