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