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