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