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