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