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