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