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