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