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