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