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