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