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