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