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