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