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