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