]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
add read_x509_subject_spice
[qemu-server.git] / PVE / QemuServer.pm
CommitLineData
1e3baf05
DM
1package PVE::QemuServer;
2
3use strict;
4use POSIX;
5use IO::Handle;
6use IO::Select;
7use IO::File;
8use IO::Dir;
9use IO::Socket::UNIX;
10use File::Basename;
11use File::Path;
12use File::stat;
13use Getopt::Long;
fc1ddcdc 14use Digest::SHA;
1e3baf05
DM
15use Fcntl ':flock';
16use Cwd 'abs_path';
17use IPC::Open3;
c971c4f2 18use JSON;
1e3baf05
DM
19use Fcntl;
20use PVE::SafeSyslog;
21use Storable qw(dclone);
22use PVE::Exception qw(raise raise_param_exc);
23use PVE::Storage;
6116f729 24use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline);
b7ba6b79 25use PVE::JSONSchema qw(get_standard_option);
1e3baf05
DM
26use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
27use PVE::INotify;
28use PVE::ProcFSTools;
26f11676 29use PVE::QMPClient;
91bd6c90 30use PVE::RPCEnvironment;
6b64503e 31use Time::HiRes qw(gettimeofday);
1e3baf05 32
7f0b5beb 33my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
1e3baf05 34
19672434 35# Note about locking: we use flock on the config file protect
1e3baf05
DM
36# against concurent actions.
37# Aditionaly, we have a 'lock' setting in the config file. This
22c377f0 38# can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
1e3baf05
DM
39# allowed when such lock is set. But you can ignore this kind of
40# lock with the --skiplock flag.
41
97d62eb7 42cfs_register_file('/qemu-server/',
1858638f
DM
43 \&parse_vm_config,
44 \&write_vm_config);
1e3baf05 45
3ea94c60
DM
46PVE::JSONSchema::register_standard_option('skiplock', {
47 description => "Ignore locks - only root is allowed to use this option.",
afdb31d5 48 type => 'boolean',
3ea94c60
DM
49 optional => 1,
50});
51
52PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
53 description => "Some command save/restore state from this location.",
54 type => 'string',
55 maxLength => 128,
56 optional => 1,
57});
58
8abd398b
DM
59PVE::JSONSchema::register_standard_option('pve-snapshot-name', {
60 description => "The name of the snapshot.",
61 type => 'string', format => 'pve-configid',
62 maxLength => 40,
63});
64
1e3baf05
DM
65#no warnings 'redefine';
66
67unless(defined(&_VZSYSCALLS_H_)) {
68 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_);
69 require 'sys/syscall.ph';
70 if(defined(&__x86_64__)) {
71 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus);
72 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod);
73 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod);
74 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt);
75 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr);
76 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate);
77 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid);
78 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit);
79 }
80 elsif(defined( &__i386__) ) {
81 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod);
82 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod);
83 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt);
84 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr);
85 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate);
86 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus);
87 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid);
88 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit);
89 } else {
90 die("no fairsched syscall for this arch");
91 }
92 require 'asm/ioctl.ph';
93 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION);
94}
95
96sub fairsched_mknod {
97 my ($parent, $weight, $desired) = @_;
98
6b64503e 99 return syscall(&__NR_fairsched_mknod, int($parent), int($weight), int($desired));
1e3baf05
DM
100}
101
102sub fairsched_rmnod {
103 my ($id) = @_;
104
6b64503e 105 return syscall(&__NR_fairsched_rmnod, int($id));
1e3baf05
DM
106}
107
108sub fairsched_mvpr {
109 my ($pid, $newid) = @_;
110
6b64503e 111 return syscall(&__NR_fairsched_mvpr, int($pid), int($newid));
1e3baf05
DM
112}
113
114sub fairsched_vcpus {
115 my ($id, $vcpus) = @_;
116
6b64503e 117 return syscall(&__NR_fairsched_vcpus, int($id), int($vcpus));
1e3baf05
DM
118}
119
120sub fairsched_rate {
121 my ($id, $op, $rate) = @_;
122
6b64503e 123 return syscall(&__NR_fairsched_rate, int($id), int($op), int($rate));
1e3baf05
DM
124}
125
126use constant FAIRSCHED_SET_RATE => 0;
127use constant FAIRSCHED_DROP_RATE => 1;
128use constant FAIRSCHED_GET_RATE => 2;
129
130sub fairsched_cpulimit {
131 my ($id, $limit) = @_;
132
6b64503e 133 my $cpulim1024 = int($limit * 1024 / 100);
1e3baf05
DM
134 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE : FAIRSCHED_DROP_RATE;
135
6b64503e 136 return fairsched_rate($id, $op, $cpulim1024);
1e3baf05
DM
137}
138
139my $nodename = PVE::INotify::nodename();
140
141mkdir "/etc/pve/nodes/$nodename";
142my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
143mkdir $confdir;
144
145my $var_run_tmpdir = "/var/run/qemu-server";
146mkdir $var_run_tmpdir;
147
148my $lock_dir = "/var/lock/qemu-server";
149mkdir $lock_dir;
150
151my $pcisysfs = "/sys/bus/pci";
152
1e3baf05
DM
153my $confdesc = {
154 onboot => {
155 optional => 1,
156 type => 'boolean',
157 description => "Specifies whether a VM will be started during system bootup.",
158 default => 0,
159 },
160 autostart => {
161 optional => 1,
162 type => 'boolean',
163 description => "Automatic restart after crash (currently ignored).",
164 default => 0,
165 },
2ff09f52
DA
166 hotplug => {
167 optional => 1,
e8b9c17c 168 type => 'boolean',
6c52b679 169 description => "Allow hotplug for disk and network device",
2dbe827e 170 default => 0,
2ff09f52 171 },
1e3baf05
DM
172 reboot => {
173 optional => 1,
174 type => 'boolean',
175 description => "Allow reboot. If set to '0' the VM exit on reboot.",
176 default => 1,
177 },
178 lock => {
179 optional => 1,
180 type => 'string',
181 description => "Lock/unlock the VM.",
22c377f0 182 enum => [qw(migrate backup snapshot rollback)],
1e3baf05
DM
183 },
184 cpulimit => {
185 optional => 1,
186 type => 'integer',
187 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.",
188 minimum => 0,
189 default => 0,
190 },
191 cpuunits => {
192 optional => 1,
193 type => 'integer',
194 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.",
195 minimum => 0,
196 maximum => 500000,
197 default => 1000,
198 },
199 memory => {
200 optional => 1,
201 type => 'integer',
7878afeb 202 description => "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
1e3baf05
DM
203 minimum => 16,
204 default => 512,
205 },
13a48620
DA
206 balloon => {
207 optional => 1,
208 type => 'integer',
8b1accf7
DM
209 description => "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
210 minimum => 0,
211 },
212 shares => {
213 optional => 1,
214 type => 'integer',
215 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",
216 minimum => 0,
217 maximum => 50000,
218 default => 1000,
13a48620 219 },
1e3baf05
DM
220 keyboard => {
221 optional => 1,
222 type => 'string',
223 description => "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
e95fe75f 224 enum => PVE::Tools::kvmkeymaplist(),
1e3baf05
DM
225 default => 'en-us',
226 },
227 name => {
228 optional => 1,
7fabe17d 229 type => 'string', format => 'dns-name',
1e3baf05
DM
230 description => "Set a name for the VM. Only used on the configuration web interface.",
231 },
cdd20088
AD
232 scsihw => {
233 optional => 1,
234 type => 'string',
235 description => "scsi controller model",
29972af3 236 enum => [qw(lsi virtio-scsi-pci megasas)],
cdd20088
AD
237 default => 'lsi',
238 },
1e3baf05
DM
239 description => {
240 optional => 1,
241 type => 'string',
0581fe4f 242 description => "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
1e3baf05
DM
243 },
244 ostype => {
245 optional => 1,
246 type => 'string',
a70ebde3 247 enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26)],
1e3baf05
DM
248 description => <<EODESC,
249Used to enable special optimization/features for specific
250operating systems:
251
252other => unspecified OS
253wxp => Microsoft Windows XP
254w2k => Microsoft Windows 2000
255w2k3 => Microsoft Windows 2003
256w2k8 => Microsoft Windows 2008
257wvista => Microsoft Windows Vista
258win7 => Microsoft Windows 7
a70ebde3 259win8 => Microsoft Windows 8/2012
1e3baf05
DM
260l24 => Linux 2.4 Kernel
261l26 => Linux 2.6/3.X Kernel
262
a70ebde3
DM
263other|l24|l26 ... no special behaviour
264wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
1e3baf05
DM
265EODESC
266 },
267 boot => {
268 optional => 1,
269 type => 'string',
270 description => "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
271 pattern => '[acdn]{1,4}',
32baffb4 272 default => 'cdn',
1e3baf05
DM
273 },
274 bootdisk => {
275 optional => 1,
276 type => 'string', format => 'pve-qm-bootdisk',
277 description => "Enable booting from specified disk.",
03e480fc 278 pattern => '(ide|sata|scsi|virtio)\d+',
1e3baf05
DM
279 },
280 smp => {
281 optional => 1,
282 type => 'integer',
283 description => "The number of CPUs. Please use option -sockets instead.",
284 minimum => 1,
285 default => 1,
286 },
287 sockets => {
288 optional => 1,
289 type => 'integer',
290 description => "The number of CPU sockets.",
291 minimum => 1,
292 default => 1,
293 },
294 cores => {
295 optional => 1,
296 type => 'integer',
297 description => "The number of cores per socket.",
298 minimum => 1,
299 default => 1,
300 },
301 acpi => {
302 optional => 1,
303 type => 'boolean',
304 description => "Enable/disable ACPI.",
305 default => 1,
306 },
bc84dcca 307 agent => {
ab6a046f
AD
308 optional => 1,
309 type => 'boolean',
310 description => "Enable/disable Qemu GuestAgent.",
be79c214 311 default => 0,
ab6a046f 312 },
1e3baf05
DM
313 kvm => {
314 optional => 1,
315 type => 'boolean',
316 description => "Enable/disable KVM hardware virtualization.",
317 default => 1,
318 },
319 tdf => {
320 optional => 1,
321 type => 'boolean',
8c559505
DM
322 description => "Enable/disable time drift fix.",
323 default => 0,
1e3baf05 324 },
19672434 325 localtime => {
1e3baf05
DM
326 optional => 1,
327 type => 'boolean',
328 description => "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
329 },
330 freeze => {
331 optional => 1,
332 type => 'boolean',
333 description => "Freeze CPU at startup (use 'c' monitor command to start execution).",
334 },
335 vga => {
336 optional => 1,
337 type => 'string',
1011b570
DM
338 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.",
339 enum => [qw(std cirrus vmware qxl)],
1e3baf05 340 },
0ea9541d
DM
341 watchdog => {
342 optional => 1,
343 type => 'string', format => 'pve-qm-watchdog',
344 typetext => '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
345 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)",
346 },
1e3baf05
DM
347 startdate => {
348 optional => 1,
19672434 349 type => 'string',
1e3baf05
DM
350 typetext => "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
351 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'.",
352 pattern => '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
353 default => 'now',
354 },
59411c4e
DM
355 startup => {
356 optional => 1,
357 type => 'string', format => 'pve-qm-startup',
358 typetext => '[[order=]\d+] [,up=\d+] [,down=\d+] ',
359 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.",
360 },
68eda3ab
AD
361 template => {
362 optional => 1,
363 type => 'boolean',
364 description => "Enable/disable Template.",
365 default => 0,
366 },
1e3baf05
DM
367 args => {
368 optional => 1,
369 type => 'string',
370 description => <<EODESCR,
371Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
372
373args: -no-reboot -no-hpet
374EODESCR
375 },
376 tablet => {
377 optional => 1,
378 type => 'boolean',
379 default => 1,
5acbfe9e 380 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
381 },
382 migrate_speed => {
383 optional => 1,
384 type => 'integer',
385 description => "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
386 minimum => 0,
387 default => 0,
388 },
389 migrate_downtime => {
390 optional => 1,
04432191 391 type => 'number',
1e3baf05
DM
392 description => "Set maximum tolerated downtime (in seconds) for migrations.",
393 minimum => 0,
04432191 394 default => 0.1,
1e3baf05
DM
395 },
396 cdrom => {
397 optional => 1,
398 type => 'string', format => 'pve-qm-drive',
399 typetext => 'volume',
400 description => "This is an alias for option -ide2",
401 },
402 cpu => {
403 optional => 1,
404 description => "Emulated CPU type.",
405 type => 'string',
98a0dc5e 406 enum => [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
eac6899d 407 default => 'kvm64',
1e3baf05 408 },
b7ba6b79
DM
409 parent => get_standard_option('pve-snapshot-name', {
410 optional => 1,
411 description => "Parent snapshot name. This is used internally, and should not be modified.",
412 }),
982c7f12
DM
413 snaptime => {
414 optional => 1,
415 description => "Timestamp for snapshots.",
416 type => 'integer',
417 minimum => 0,
418 },
18bfb361
DM
419 vmstate => {
420 optional => 1,
421 type => 'string', format => 'pve-volume-id',
422 description => "Reference to a volume which stores the VM state. This is used internally for snapshots.",
423 },
3bafc510
DM
424 machine => {
425 description => "Specific the Qemu machine type.",
426 type => 'string',
427 pattern => '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
428 maxLength => 40,
429 optional => 1,
430 },
1e3baf05
DM
431};
432
433# what about other qemu settings ?
434#cpu => 'string',
435#machine => 'string',
436#fda => 'file',
437#fdb => 'file',
438#mtdblock => 'file',
439#sd => 'file',
440#pflash => 'file',
441#snapshot => 'bool',
442#bootp => 'file',
443##tftp => 'dir',
444##smb => 'dir',
445#kernel => 'file',
446#append => 'string',
447#initrd => 'file',
448##soundhw => 'string',
449
450while (my ($k, $v) = each %$confdesc) {
451 PVE::JSONSchema::register_standard_option("pve-qm-$k", $v);
452}
453
454my $MAX_IDE_DISKS = 4;
f62db2a4 455my $MAX_SCSI_DISKS = 14;
a2650619 456my $MAX_VIRTIO_DISKS = 16;
cdb0931f 457my $MAX_SATA_DISKS = 6;
1e3baf05 458my $MAX_USB_DEVICES = 5;
5bdcf937 459my $MAX_NETS = 32;
1e3baf05 460my $MAX_UNUSED_DISKS = 8;
040b06b7 461my $MAX_HOSTPCI_DEVICES = 2;
bae179aa 462my $MAX_SERIAL_PORTS = 4;
1989a89c 463my $MAX_PARALLEL_PORTS = 3;
1e3baf05
DM
464
465my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
466 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
6b64503e 467my $nic_model_list_txt = join(' ', sort @$nic_model_list);
1e3baf05 468
1e3baf05
DM
469my $netdesc = {
470 optional => 1,
471 type => 'string', format => 'pve-qm-net',
5070f384 472 typetext => "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
1e3baf05 473 description => <<EODESCR,
19672434 474Specify network devices.
1e3baf05
DM
475
476MODEL is one of: $nic_model_list_txt
477
19672434 478XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
1e3baf05
DM
479automatically generated if not specified.
480
481The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
482
483Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
484
485If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
486
48710.0.2.2 Gateway
48810.0.2.3 DNS Server
48910.0.2.4 SMB Server
490
491The DHCP server assign addresses to the guest starting from 10.0.2.15.
492
493EODESCR
494};
495PVE::JSONSchema::register_standard_option("pve-qm-net", $netdesc);
496
497for (my $i = 0; $i < $MAX_NETS; $i++) {
498 $confdesc->{"net$i"} = $netdesc;
499}
500
501my $drivename_hash;
19672434 502
1e3baf05
DM
503my $idedesc = {
504 optional => 1,
505 type => 'string', format => 'pve-qm-drive',
e482cec3 506 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]',
3c770faa 507 description => "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
1e3baf05
DM
508};
509PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc);
510
511my $scsidesc = {
512 optional => 1,
513 type => 'string', format => 'pve-qm-drive',
e482cec3 514 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]',
3c770faa 515 description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
1e3baf05
DM
516};
517PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
518
cdb0931f
DA
519my $satadesc = {
520 optional => 1,
521 type => 'string', format => 'pve-qm-drive',
e482cec3 522 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]',
3c770faa 523 description => "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
cdb0931f
DA
524};
525PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc);
526
1e3baf05
DM
527my $virtiodesc = {
528 optional => 1,
529 type => 'string', format => 'pve-qm-drive',
e482cec3 530 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]',
3c770faa 531 description => "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
1e3baf05
DM
532};
533PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc);
534
535my $usbdesc = {
536 optional => 1,
537 type => 'string', format => 'pve-qm-usb-device',
80401dd8 538 typetext => 'host=HOSTUSBDEVICE|spice',
1e3baf05 539 description => <<EODESCR,
2fe1a152 540Configure an USB device (n is 0 to 4). This can be used to
1e3baf05
DM
541pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
542
19672434 543'bus-port(.port)*' (decimal numbers) or
1e3baf05
DM
544'vendor_id:product_id' (hexadeciaml numbers)
545
19672434 546You can use the 'lsusb -t' command to list existing usb devices.
1e3baf05
DM
547
548Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
549
80401dd8
DM
550The value 'spice' can be used to add a usb redirection devices for spice.
551
1e3baf05
DM
552EODESCR
553};
554PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
555
040b06b7
DA
556my $hostpcidesc = {
557 optional => 1,
558 type => 'string', format => 'pve-qm-hostpci',
559 typetext => "HOSTPCIDEVICE",
560 description => <<EODESCR,
561Map host pci devices. HOSTPCIDEVICE syntax is:
562
563'bus:dev.func' (hexadecimal numbers)
564
565You can us the 'lspci' command to list existing pci devices.
566
567Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
568
569Experimental: user reported problems with this option.
570EODESCR
571};
572PVE::JSONSchema::register_standard_option("pve-qm-hostpci", $hostpcidesc);
573
bae179aa
DA
574my $serialdesc = {
575 optional => 1,
ca0cef26 576 type => 'string',
2fe1a152 577 pattern => '/dev/ttyS\d+',
bae179aa 578 description => <<EODESCR,
19672434 579Map host serial devices (n is 0 to 3).
bae179aa
DA
580
581Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
582
583Experimental: user reported problems with this option.
584EODESCR
585};
bae179aa 586
1989a89c
DA
587my $paralleldesc= {
588 optional => 1,
ca0cef26 589 type => 'string',
2fe1a152 590 pattern => '/dev/parport\d+',
1989a89c 591 description => <<EODESCR,
19672434 592Map host parallel devices (n is 0 to 2).
1989a89c
DA
593
594Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
595
596Experimental: user reported problems with this option.
597EODESCR
598};
1989a89c
DA
599
600for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
601 $confdesc->{"parallel$i"} = $paralleldesc;
602}
603
bae179aa
DA
604for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
605 $confdesc->{"serial$i"} = $serialdesc;
606}
607
040b06b7
DA
608for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
609 $confdesc->{"hostpci$i"} = $hostpcidesc;
610}
1e3baf05
DM
611
612for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
613 $drivename_hash->{"ide$i"} = 1;
614 $confdesc->{"ide$i"} = $idedesc;
615}
616
cdb0931f
DA
617for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
618 $drivename_hash->{"sata$i"} = 1;
619 $confdesc->{"sata$i"} = $satadesc;
620}
621
1e3baf05
DM
622for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
623 $drivename_hash->{"scsi$i"} = 1;
624 $confdesc->{"scsi$i"} = $scsidesc ;
625}
626
627for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
628 $drivename_hash->{"virtio$i"} = 1;
629 $confdesc->{"virtio$i"} = $virtiodesc;
630}
631
632for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
633 $confdesc->{"usb$i"} = $usbdesc;
634}
635
636my $unuseddesc = {
637 optional => 1,
638 type => 'string', format => 'pve-volume-id',
639 description => "Reference to unused volumes.",
640};
641
642for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
643 $confdesc->{"unused$i"} = $unuseddesc;
644}
645
646my $kvm_api_version = 0;
647
648sub kvm_version {
649
650 return $kvm_api_version if $kvm_api_version;
651
6b64503e 652 my $fh = IO::File->new("</dev/kvm") ||
1e3baf05
DM
653 return 0;
654
6b64503e 655 if (my $v = $fh->ioctl(KVM_GET_API_VERSION(), 0)) {
1e3baf05
DM
656 $kvm_api_version = $v;
657 }
658
659 $fh->close();
660
661 return $kvm_api_version;
662}
663
664my $kvm_user_version;
665
666sub kvm_user_version {
667
668 return $kvm_user_version if $kvm_user_version;
669
670 $kvm_user_version = 'unknown';
671
672 my $tmp = `kvm -help 2>/dev/null`;
19672434 673
fa7ae705 674 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
1e3baf05
DM
675 $kvm_user_version = $2;
676 }
677
678 return $kvm_user_version;
679
680}
681
682my $kernel_has_vhost_net = -c '/dev/vhost-net';
683
684sub disknames {
685 # order is important - used to autoselect boot disk
19672434 686 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1e3baf05 687 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
cdb0931f
DA
688 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
689 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1e3baf05
DM
690}
691
692sub valid_drivename {
693 my $dev = shift;
694
6b64503e 695 return defined($drivename_hash->{$dev});
1e3baf05
DM
696}
697
698sub option_exists {
699 my $key = shift;
700 return defined($confdesc->{$key});
19672434 701}
1e3baf05
DM
702
703sub nic_models {
704 return $nic_model_list;
705}
706
707sub os_list_description {
708
709 return {
710 other => 'Other',
711 wxp => 'Windows XP',
712 w2k => 'Windows 2000',
713 w2k3 =>, 'Windows 2003',
714 w2k8 => 'Windows 2008',
715 wvista => 'Windows Vista',
716 win7 => 'Windows 7',
a70ebde3 717 win8 => 'Windows 8/2012',
1e3baf05
DM
718 l24 => 'Linux 2.4',
719 l26 => 'Linux 2.6',
19672434 720 };
1e3baf05
DM
721}
722
1e3baf05
DM
723my $cdrom_path;
724
725sub get_cdrom_path {
726
727 return $cdrom_path if $cdrom_path;
728
729 return $cdrom_path = "/dev/cdrom" if -l "/dev/cdrom";
730 return $cdrom_path = "/dev/cdrom1" if -l "/dev/cdrom1";
731 return $cdrom_path = "/dev/cdrom2" if -l "/dev/cdrom2";
732}
733
734sub get_iso_path {
735 my ($storecfg, $vmid, $cdrom) = @_;
736
737 if ($cdrom eq 'cdrom') {
738 return get_cdrom_path();
739 } elsif ($cdrom eq 'none') {
740 return '';
741 } elsif ($cdrom =~ m|^/|) {
742 return $cdrom;
743 } else {
6b64503e 744 return PVE::Storage::path($storecfg, $cdrom);
1e3baf05
DM
745 }
746}
747
748# try to convert old style file names to volume IDs
749sub filename_to_volume_id {
750 my ($vmid, $file, $media) = @_;
751
752 if (!($file eq 'none' || $file eq 'cdrom' ||
753 $file =~ m|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
19672434 754
1e3baf05 755 return undef if $file =~ m|/|;
19672434 756
1e3baf05
DM
757 if ($media && $media eq 'cdrom') {
758 $file = "local:iso/$file";
759 } else {
760 $file = "local:$vmid/$file";
761 }
762 }
763
764 return $file;
765}
766
767sub verify_media_type {
768 my ($opt, $vtype, $media) = @_;
769
770 return if !$media;
771
772 my $etype;
773 if ($media eq 'disk') {
a125592c 774 $etype = 'images';
1e3baf05
DM
775 } elsif ($media eq 'cdrom') {
776 $etype = 'iso';
777 } else {
778 die "internal error";
779 }
780
781 return if ($vtype eq $etype);
19672434 782
1e3baf05
DM
783 raise_param_exc({ $opt => "unexpected media type ($vtype != $etype)" });
784}
785
786sub cleanup_drive_path {
787 my ($opt, $storecfg, $drive) = @_;
788
789 # try to convert filesystem paths to volume IDs
790
791 if (($drive->{file} !~ m/^(cdrom|none)$/) &&
792 ($drive->{file} !~ m|^/dev/.+|) &&
793 ($drive->{file} !~ m/^([^:]+):(.+)$/) &&
19672434 794 ($drive->{file} !~ m/^\d+$/)) {
1e3baf05
DM
795 my ($vtype, $volid) = PVE::Storage::path_to_volume_id($storecfg, $drive->{file});
796 raise_param_exc({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
797 $drive->{media} = 'cdrom' if !$drive->{media} && $vtype eq 'iso';
798 verify_media_type($opt, $vtype, $drive->{media});
799 $drive->{file} = $volid;
800 }
801
802 $drive->{media} = 'cdrom' if !$drive->{media} && $drive->{file} =~ m/^(cdrom|none)$/;
803}
804
805sub create_conf_nolock {
806 my ($vmid, $settings) = @_;
807
6b64503e 808 my $filename = config_file($vmid);
1e3baf05
DM
809
810 die "configuration file '$filename' already exists\n" if -f $filename;
19672434 811
1e3baf05
DM
812 my $defaults = load_defaults();
813
814 $settings->{name} = "vm$vmid" if !$settings->{name};
815 $settings->{memory} = $defaults->{memory} if !$settings->{memory};
816
817 my $data = '';
818 foreach my $opt (keys %$settings) {
819 next if !$confdesc->{$opt};
820
821 my $value = $settings->{$opt};
822 next if !$value;
823
824 $data .= "$opt: $value\n";
825 }
826
827 PVE::Tools::file_set_contents($filename, $data);
828}
829
f36ed4f4
DM
830my $parse_size = sub {
831 my ($value) = @_;
832
9bf371a6 833 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
f36ed4f4
DM
834 my ($size, $unit) = ($1, $3);
835 if ($unit) {
836 if ($unit eq 'K') {
837 $size = $size * 1024;
838 } elsif ($unit eq 'M') {
839 $size = $size * 1024 * 1024;
840 } elsif ($unit eq 'G') {
841 $size = $size * 1024 * 1024 * 1024;
842 }
843 }
844 return int($size);
845};
846
847my $format_size = sub {
848 my ($size) = @_;
849
850 $size = int($size);
851
852 my $kb = int($size/1024);
853 return $size if $kb*1024 != $size;
854
855 my $mb = int($kb/1024);
856 return "${kb}K" if $mb*1024 != $kb;
857
858 my $gb = int($mb/1024);
859 return "${mb}M" if $gb*1024 != $mb;
860
861 return "${gb}G";
862};
863
1e3baf05
DM
864# ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
865# [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
036e0e2b 866# [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1e3baf05
DM
867# [,aio=native|threads]
868
869sub parse_drive {
870 my ($key, $data) = @_;
871
872 my $res = {};
19672434 873
1e3baf05
DM
874 # $key may be undefined - used to verify JSON parameters
875 if (!defined($key)) {
876 $res->{interface} = 'unknown'; # should not harm when used to verify parameters
877 $res->{index} = 0;
878 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
879 $res->{interface} = $1;
880 $res->{index} = $2;
881 } else {
882 return undef;
883 }
884
885 foreach my $p (split (/,/, $data)) {
886 next if $p =~ m/^\s*$/;
887
9bf371a6 888 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|bps_rd|mbps_rd|bps_wr|mbps_wr|iops|iops_rd|iops_wr|size)=(.+)$/) {
1e3baf05
DM
889 my ($k, $v) = ($1, $2);
890
891 $k = 'file' if $k eq 'volume';
892
893 return undef if defined $res->{$k};
19672434 894
9bf371a6
DM
895 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
896 return undef if !$v || $v !~ m/^\d+/;
897 $k = "m$k";
898 $v = sprintf("%.3f", $v / (1024*1024));
899 }
1e3baf05
DM
900 $res->{$k} = $v;
901 } else {
902 if (!$res->{file} && $p !~ m/=/) {
903 $res->{file} = $p;
904 } else {
905 return undef;
906 }
907 }
908 }
909
910 return undef if !$res->{file};
911
bdf3f362
AD
912 if($res->{file} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
913 $res->{format} = $1;
914 }
915
19672434 916 return undef if $res->{cache} &&
e482cec3 917 $res->{cache} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
1e3baf05
DM
918 return undef if $res->{snapshot} && $res->{snapshot} !~ m/^(on|off)$/;
919 return undef if $res->{cyls} && $res->{cyls} !~ m/^\d+$/;
920 return undef if $res->{heads} && $res->{heads} !~ m/^\d+$/;
921 return undef if $res->{secs} && $res->{secs} !~ m/^\d+$/;
922 return undef if $res->{media} && $res->{media} !~ m/^(disk|cdrom)$/;
923 return undef if $res->{trans} && $res->{trans} !~ m/^(none|lba|auto)$/;
924 return undef if $res->{format} && $res->{format} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
925 return undef if $res->{rerror} && $res->{rerror} !~ m/^(ignore|report|stop)$/;
926 return undef if $res->{werror} && $res->{werror} !~ m/^(enospc|ignore|report|stop)$/;
927 return undef if $res->{backup} && $res->{backup} !~ m/^(yes|no)$/;
928 return undef if $res->{aio} && $res->{aio} !~ m/^(native|threads)$/;
929
be190583 930
9bf371a6
DM
931 return undef if $res->{mbps_rd} && $res->{mbps};
932 return undef if $res->{mbps_wr} && $res->{mbps};
933
934 return undef if $res->{mbps} && $res->{mbps} !~ m/^\d+(\.\d+)?$/;
935 return undef if $res->{mbps_rd} && $res->{mbps_rd} !~ m/^\d+(\.\d+)?$/;
936 return undef if $res->{mbps_wr} && $res->{mbps_wr} !~ m/^\d+(\.\d+)?$/;
937
affd2f88
AD
938 return undef if $res->{iops_rd} && $res->{iops};
939 return undef if $res->{iops_wr} && $res->{iops};
affd2f88
AD
940 return undef if $res->{iops} && $res->{iops} !~ m/^\d+$/;
941 return undef if $res->{iops_rd} && $res->{iops_rd} !~ m/^\d+$/;
942 return undef if $res->{iops_wr} && $res->{iops_wr} !~ m/^\d+$/;
943
944
24afaca0 945 if ($res->{size}) {
be190583 946 return undef if !defined($res->{size} = &$parse_size($res->{size}));
24afaca0
DM
947 }
948
1e3baf05
DM
949 if ($res->{media} && ($res->{media} eq 'cdrom')) {
950 return undef if $res->{snapshot} || $res->{trans} || $res->{format};
19672434 951 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
1e3baf05
DM
952 return undef if $res->{interface} eq 'virtio';
953 }
954
955 # rerror does not work with scsi drives
956 if ($res->{rerror}) {
957 return undef if $res->{interface} eq 'scsi';
958 }
959
960 return $res;
961}
962
9bf371a6 963my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
1e3baf05
DM
964
965sub print_drive {
966 my ($vmid, $drive) = @_;
967
968 my $opts = '';
9bf371a6 969 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
1e3baf05
DM
970 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
971 }
972
24afaca0
DM
973 if ($drive->{size}) {
974 $opts .= ",size=" . &$format_size($drive->{size});
975 }
976
1e3baf05
DM
977 return "$drive->{file}$opts";
978}
979
28ef82d3
DM
980sub scsi_inquiry {
981 my($fh, $noerr) = @_;
982
983 my $SG_IO = 0x2285;
984 my $SG_GET_VERSION_NUM = 0x2282;
985
986 my $versionbuf = "\x00" x 8;
987 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
988 if (!$ret) {
989 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
990 return undef;
991 }
97d62eb7 992 my $version = unpack("I", $versionbuf);
28ef82d3
DM
993 if ($version < 30000) {
994 die "scsi generic interface too old\n" if !$noerr;
995 return undef;
996 }
97d62eb7 997
28ef82d3
DM
998 my $buf = "\x00" x 36;
999 my $sensebuf = "\x00" x 8;
f334aa3e 1000 my $cmd = pack("C x3 C x1", 0x12, 36);
97d62eb7 1001
28ef82d3
DM
1002 # see /usr/include/scsi/sg.h
1003 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";
1004
97d62eb7
DM
1005 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1006 length($sensebuf), 0, length($buf), $buf,
28ef82d3
DM
1007 $cmd, $sensebuf, 6000);
1008
1009 $ret = ioctl($fh, $SG_IO, $packet);
1010 if (!$ret) {
1011 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1012 return undef;
1013 }
97d62eb7 1014
28ef82d3
DM
1015 my @res = unpack($sg_io_hdr_t, $packet);
1016 if ($res[17] || $res[18]) {
1017 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1018 return undef;
1019 }
1020
1021 my $res = {};
09984754 1022 (my $byte0, my $byte1, $res->{vendor},
28ef82d3
DM
1023 $res->{product}, $res->{revision}) = unpack("C C x6 A8 A16 A4", $buf);
1024
09984754
DM
1025 $res->{removable} = $byte1 & 128 ? 1 : 0;
1026 $res->{type} = $byte0 & 31;
1027
28ef82d3
DM
1028 return $res;
1029}
1030
1031sub path_is_scsi {
1032 my ($path) = @_;
1033
1034 my $fh = IO::File->new("+<$path") || return undef;
1035 my $res = scsi_inquiry($fh, 1);
1036 close($fh);
1037
1038 return $res;
1039}
1040
ca916ecc 1041sub print_drivedevice_full {
5bdcf937 1042 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
ca916ecc
DA
1043
1044 my $device = '';
1045 my $maxdev = 0;
19672434 1046
ca916ecc 1047 if ($drive->{interface} eq 'virtio') {
5bdcf937 1048 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}", $bridges);
2ed36a41
DM
1049 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1050 } elsif ($drive->{interface} eq 'scsi') {
cdd20088 1051 $maxdev = ($conf->{scsihw} && $conf->{scsihw} ne 'lsi') ? 256 : 7;
2ed36a41
DM
1052 my $controller = int($drive->{index} / $maxdev);
1053 my $unit = $drive->{index} % $maxdev;
1054 my $devicetype = 'hd';
231f2e13
DA
1055 my $path = '';
1056 if (drive_is_cdrom($drive)) {
1057 $devicetype = 'cd';
29b19529 1058 } else {
231f2e13
DA
1059 if ($drive->{file} =~ m|^/|) {
1060 $path = $drive->{file};
1061 } else {
1062 $path = PVE::Storage::path($storecfg, $drive->{file});
1063 }
d454d040
AD
1064
1065 if($path =~ m/^iscsi\:\/\//){
29b19529
DM
1066 $devicetype = 'generic';
1067 } else {
09984754
DM
1068 if (my $info = path_is_scsi($path)) {
1069 if ($info->{type} == 0) {
1070 $devicetype = 'block';
1071 } elsif ($info->{type} == 1) { # tape
1072 $devicetype = 'generic';
1073 }
1074 }
d454d040 1075 }
231f2e13 1076 }
ca916ecc 1077
cdd20088
AD
1078 if (!$conf->{scsihw} || $conf->{scsihw} eq 'lsi'){
1079 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}" if !$conf->{scsihw} || $conf->{scsihw} eq 'lsi';
1080 } else {
1081 $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}";
1082 }
1083
2ed36a41
DM
1084 } elsif ($drive->{interface} eq 'ide'){
1085 $maxdev = 2;
1086 my $controller = int($drive->{index} / $maxdev);
1087 my $unit = $drive->{index} % $maxdev;
1088 my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
1089
7ebe888a 1090 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
cdb0931f
DA
1091 } elsif ($drive->{interface} eq 'sata'){
1092 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1093 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1094 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
2ed36a41
DM
1095 } elsif ($drive->{interface} eq 'usb') {
1096 die "implement me";
1097 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1098 } else {
1099 die "unsupported interface type";
ca916ecc
DA
1100 }
1101
3b408e82
DM
1102 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
1103
ca916ecc
DA
1104 return $device;
1105}
1106
1e3baf05
DM
1107sub print_drive_full {
1108 my ($storecfg, $vmid, $drive) = @_;
1109
1110 my $opts = '';
1111 foreach my $o (@qemu_drive_options) {
3b408e82 1112 next if $o eq 'bootindex';
1e3baf05 1113 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
19672434 1114 }
1e3baf05 1115
9bf371a6
DM
1116 foreach my $o (qw(bps bps_rd bps_wr)) {
1117 my $v = $drive->{"m$o"};
1118 $opts .= ",$o=" . int($v*1024*1024) if $v;
1119 }
1120
1e3baf05 1121 # use linux-aio by default (qemu default is threads)
19672434 1122 $opts .= ",aio=native" if !$drive->{aio};
1e3baf05
DM
1123
1124 my $path;
1125 my $volid = $drive->{file};
6b64503e
DM
1126 if (drive_is_cdrom($drive)) {
1127 $path = get_iso_path($storecfg, $vmid, $volid);
1e3baf05
DM
1128 } else {
1129 if ($volid =~ m|^/|) {
1130 $path = $volid;
1131 } else {
6b64503e 1132 $path = PVE::Storage::path($storecfg, $volid);
1e3baf05
DM
1133 }
1134 }
1135
ef86170e 1136 $opts .= ",cache=none" if !$drive->{cache} && !drive_is_cdrom($drive);
11490cf2 1137
1e3baf05
DM
1138 my $pathinfo = $path ? "file=$path," : '';
1139
3ebfcc86 1140 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1e3baf05
DM
1141}
1142
cc4d6182 1143sub print_netdevice_full {
5bdcf937 1144 my ($vmid, $conf, $net, $netid, $bridges) = @_;
cc4d6182
DA
1145
1146 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
1147
1148 my $device = $net->{model};
1149 if ($net->{model} eq 'virtio') {
1150 $device = 'virtio-net-pci';
1151 };
1152
1153 # qemu > 0.15 always try to boot from network - we disable that by
1154 # not loading the pxe rom file
1155 my $extra = ($bootorder !~ m/n/) ? "romfile=," : '';
5bdcf937 1156 my $pciaddr = print_pci_addr("$netid", $bridges);
cc4d6182
DA
1157 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1158 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex} ;
1159 return $tmpstr;
1160}
1161
1162sub print_netdev_full {
1163 my ($vmid, $conf, $net, $netid) = @_;
1164
1165 my $i = '';
1166 if ($netid =~ m/^net(\d+)$/) {
1167 $i = int($1);
1168 }
1169
1170 die "got strange net id '$i'\n" if $i >= ${MAX_NETS};
1171
1172 my $ifname = "tap${vmid}i$i";
1173
1174 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1175 die "interface name '$ifname' is too long (max 15 character)\n"
1176 if length($ifname) >= 16;
1177
1178 my $vhostparam = '';
1179 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model} eq 'virtio';
1180
1181 my $vmname = $conf->{name} || "vm$vmid";
1182
1183 if ($net->{bridge}) {
1184 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1185 } else {
1186 return "type=user,id=$netid,hostname=$vmname";
1187 }
1188}
1e3baf05
DM
1189
1190sub drive_is_cdrom {
1191 my ($drive) = @_;
1192
1193 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
1194
1195}
1196
040b06b7
DA
1197sub parse_hostpci {
1198 my ($value) = @_;
1199
1200 return undef if !$value;
1201
1202 my $res = {};
1203
1204 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1205 $res->{pciid} = $value;
1206 } else {
1207 return undef;
1208 }
1209
1210 return $res;
1211}
1212
1e3baf05
DM
1213# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1214sub parse_net {
1215 my ($data) = @_;
1216
1217 my $res = {};
1218
6b64503e 1219 foreach my $kvp (split(/,/, $data)) {
1e3baf05
DM
1220
1221 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
6b64503e 1222 my $model = lc($1);
92f0fedc 1223 my $mac = defined($3) ? uc($3) : PVE::Tools::random_ether_addr();
1e3baf05
DM
1224 $res->{model} = $model;
1225 $res->{macaddr} = $mac;
1226 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1227 $res->{bridge} = $1;
1228 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1229 $res->{rate} = $1;
5070f384
DA
1230 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1231 $res->{tag} = $1;
1e3baf05
DM
1232 } else {
1233 return undef;
1234 }
19672434 1235
1e3baf05
DM
1236 }
1237
1238 return undef if !$res->{model};
1239
1240 return $res;
1241}
1242
1243sub print_net {
1244 my $net = shift;
1245
1246 my $res = "$net->{model}";
1247 $res .= "=$net->{macaddr}" if $net->{macaddr};
1248 $res .= ",bridge=$net->{bridge}" if $net->{bridge};
1249 $res .= ",rate=$net->{rate}" if $net->{rate};
18744ba3 1250 $res .= ",tag=$net->{tag}" if $net->{tag};
1e3baf05
DM
1251
1252 return $res;
1253}
1254
1255sub add_random_macs {
1256 my ($settings) = @_;
1257
1258 foreach my $opt (keys %$settings) {
1259 next if $opt !~ m/^net(\d+)$/;
1260 my $net = parse_net($settings->{$opt});
1261 next if !$net;
1262 $settings->{$opt} = print_net($net);
1263 }
1264}
1265
1266sub add_unused_volume {
1858638f 1267 my ($config, $volid) = @_;
1e3baf05
DM
1268
1269 my $key;
1270 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1271 my $test = "unused$ind";
1272 if (my $vid = $config->{$test}) {
1273 return if $vid eq $volid; # do not add duplicates
1274 } else {
1275 $key = $test;
19672434 1276 }
1e3baf05
DM
1277 }
1278
1279 die "To many unused volume - please delete them first.\n" if !$key;
97d62eb7 1280
1858638f 1281 $config->{$key} = $volid;
1e3baf05 1282
1858638f 1283 return $key;
1e3baf05
DM
1284}
1285
1e3baf05
DM
1286PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
1287sub verify_bootdisk {
1288 my ($value, $noerr) = @_;
1289
19672434 1290 return $value if valid_drivename($value);
1e3baf05
DM
1291
1292 return undef if $noerr;
1293
1294 die "invalid boot disk '$value'\n";
1295}
1296
1297PVE::JSONSchema::register_format('pve-qm-net', \&verify_net);
1298sub verify_net {
1299 my ($value, $noerr) = @_;
1300
1301 return $value if parse_net($value);
1302
1303 return undef if $noerr;
19672434 1304
1e3baf05
DM
1305 die "unable to parse network options\n";
1306}
1307
1308PVE::JSONSchema::register_format('pve-qm-drive', \&verify_drive);
1309sub verify_drive {
1310 my ($value, $noerr) = @_;
1311
6b64503e 1312 return $value if parse_drive(undef, $value);
1e3baf05
DM
1313
1314 return undef if $noerr;
19672434 1315
1e3baf05
DM
1316 die "unable to parse drive options\n";
1317}
1318
1319PVE::JSONSchema::register_format('pve-qm-hostpci', \&verify_hostpci);
1320sub verify_hostpci {
1321 my ($value, $noerr) = @_;
1322
040b06b7
DA
1323 return $value if parse_hostpci($value);
1324
1325 return undef if $noerr;
1326
1327 die "unable to parse pci id\n";
1e3baf05
DM
1328}
1329
0ea9541d
DM
1330PVE::JSONSchema::register_format('pve-qm-watchdog', \&verify_watchdog);
1331sub verify_watchdog {
1332 my ($value, $noerr) = @_;
1333
1334 return $value if parse_watchdog($value);
1335
1336 return undef if $noerr;
19672434 1337
0ea9541d
DM
1338 die "unable to parse watchdog options\n";
1339}
1340
1341sub parse_watchdog {
1342 my ($value) = @_;
1343
1344 return undef if !$value;
1345
1346 my $res = {};
1347
6b64503e 1348 foreach my $p (split(/,/, $value)) {
0ea9541d
DM
1349 next if $p =~ m/^\s*$/;
1350
1351 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1352 $res->{model} = $2;
1353 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1354 $res->{action} = $2;
1355 } else {
1356 return undef;
1357 }
1358 }
1359
1360 return $res;
1361}
1362
59411c4e
DM
1363PVE::JSONSchema::register_format('pve-qm-startup', \&verify_startup);
1364sub verify_startup {
1365 my ($value, $noerr) = @_;
1366
1367 return $value if parse_startup($value);
1368
1369 return undef if $noerr;
1370
1371 die "unable to parse startup options\n";
1372}
1373
1374sub parse_startup {
1375 my ($value) = @_;
1376
1377 return undef if !$value;
1378
1379 my $res = {};
1380
1381 foreach my $p (split(/,/, $value)) {
1382 next if $p =~ m/^\s*$/;
1383
1384 if ($p =~ m/^(order=)?(\d+)$/) {
1385 $res->{order} = $2;
1386 } elsif ($p =~ m/^up=(\d+)$/) {
1387 $res->{up} = $1;
1388 } elsif ($p =~ m/^down=(\d+)$/) {
1389 $res->{down} = $1;
1390 } else {
1391 return undef;
1392 }
1393 }
1394
1395 return $res;
1396}
1397
1e3baf05
DM
1398sub parse_usb_device {
1399 my ($value) = @_;
1400
1401 return undef if !$value;
1402
6b64503e 1403 my @dl = split(/,/, $value);
1e3baf05
DM
1404 my $found;
1405
1406 my $res = {};
1407 foreach my $v (@dl) {
036e0e2b 1408 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1e3baf05 1409 $found = 1;
036e0e2b
DM
1410 $res->{vendorid} = $2;
1411 $res->{productid} = $4;
1e3baf05
DM
1412 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1413 $found = 1;
1414 $res->{hostbus} = $1;
1415 $res->{hostport} = $2;
80401dd8
DM
1416 } elsif ($v =~ m/^spice$/) {
1417 $found = 1;
1418 $res->{spice} = 1;
1e3baf05
DM
1419 } else {
1420 return undef;
1421 }
1422 }
1423 return undef if !$found;
1424
1425 return $res;
1426}
19672434 1427
1e3baf05
DM
1428PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
1429sub verify_usb_device {
1430 my ($value, $noerr) = @_;
1431
1432 return $value if parse_usb_device($value);
1433
1434 return undef if $noerr;
19672434 1435
1e3baf05
DM
1436 die "unable to parse usb device\n";
1437}
1438
1e3baf05
DM
1439# add JSON properties for create and set function
1440sub json_config_properties {
1441 my $prop = shift;
1442
1443 foreach my $opt (keys %$confdesc) {
18bfb361 1444 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1e3baf05
DM
1445 $prop->{$opt} = $confdesc->{$opt};
1446 }
1447
1448 return $prop;
1449}
1450
1451sub check_type {
1452 my ($key, $value) = @_;
1453
1454 die "unknown setting '$key'\n" if !$confdesc->{$key};
1455
1456 my $type = $confdesc->{$key}->{type};
1457
6b64503e 1458 if (!defined($value)) {
1e3baf05
DM
1459 die "got undefined value\n";
1460 }
1461
1462 if ($value =~ m/[\n\r]/) {
1463 die "property contains a line feed\n";
1464 }
1465
1466 if ($type eq 'boolean') {
19672434
DM
1467 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1468 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1469 die "type check ('boolean') failed - got '$value'\n";
1e3baf05
DM
1470 } elsif ($type eq 'integer') {
1471 return int($1) if $value =~ m/^(\d+)$/;
1472 die "type check ('integer') failed - got '$value'\n";
04432191
AD
1473 } elsif ($type eq 'number') {
1474 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1475 die "type check ('number') failed - got '$value'\n";
1e3baf05
DM
1476 } elsif ($type eq 'string') {
1477 if (my $fmt = $confdesc->{$key}->{format}) {
1478 if ($fmt eq 'pve-qm-drive') {
1479 # special case - we need to pass $key to parse_drive()
6b64503e 1480 my $drive = parse_drive($key, $value);
1e3baf05
DM
1481 return $value if $drive;
1482 die "unable to parse drive options\n";
1483 }
1484 PVE::JSONSchema::check_format($fmt, $value);
19672434
DM
1485 return $value;
1486 }
1e3baf05 1487 $value =~ s/^\"(.*)\"$/$1/;
19672434 1488 return $value;
1e3baf05
DM
1489 } else {
1490 die "internal error"
1491 }
1492}
1493
191435c6
DM
1494sub lock_config_full {
1495 my ($vmid, $timeout, $code, @param) = @_;
1e3baf05 1496
6b64503e 1497 my $filename = config_file_lock($vmid);
1e3baf05 1498
191435c6 1499 my $res = lock_file($filename, $timeout, $code, @param);
1e3baf05
DM
1500
1501 die $@ if $@;
5fdbe4f0
DM
1502
1503 return $res;
1e3baf05
DM
1504}
1505
4e4f83fe
DM
1506sub lock_config_mode {
1507 my ($vmid, $timeout, $shared, $code, @param) = @_;
6116f729
DM
1508
1509 my $filename = config_file_lock($vmid);
1510
4e4f83fe 1511 my $res = lock_file_full($filename, $timeout, $shared, $code, @param);
6116f729
DM
1512
1513 die $@ if $@;
1514
1515 return $res;
1516}
1517
191435c6
DM
1518sub lock_config {
1519 my ($vmid, $code, @param) = @_;
1520
1521 return lock_config_full($vmid, 10, $code, @param);
1522}
1523
1e3baf05 1524sub cfs_config_path {
a78ccf26 1525 my ($vmid, $node) = @_;
1e3baf05 1526
a78ccf26
DM
1527 $node = $nodename if !$node;
1528 return "nodes/$node/qemu-server/$vmid.conf";
1e3baf05
DM
1529}
1530
040b06b7
DA
1531sub check_iommu_support{
1532 #fixme : need to check IOMMU support
1533 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1534
1535 my $iommu=1;
1536 return $iommu;
1537
1538}
1539
1e3baf05 1540sub config_file {
a78ccf26 1541 my ($vmid, $node) = @_;
1e3baf05 1542
a78ccf26 1543 my $cfspath = cfs_config_path($vmid, $node);
1e3baf05
DM
1544 return "/etc/pve/$cfspath";
1545}
1546
1547sub config_file_lock {
1548 my ($vmid) = @_;
1549
1550 return "$lock_dir/lock-$vmid.conf";
1551}
1552
1553sub touch_config {
1554 my ($vmid) = @_;
1555
6b64503e 1556 my $conf = config_file($vmid);
1e3baf05
DM
1557 utime undef, undef, $conf;
1558}
1559
1e3baf05 1560sub destroy_vm {
a6af7b3e 1561 my ($storecfg, $vmid, $keep_empty_config) = @_;
1e3baf05 1562
6b64503e 1563 my $conffile = config_file($vmid);
1e3baf05 1564
6b64503e 1565 my $conf = load_config($vmid);
1e3baf05 1566
6b64503e 1567 check_lock($conf);
1e3baf05 1568
19672434 1569 # only remove disks owned by this VM
1e3baf05
DM
1570 foreach_drive($conf, sub {
1571 my ($ds, $drive) = @_;
1572
6b64503e 1573 return if drive_is_cdrom($drive);
1e3baf05
DM
1574
1575 my $volid = $drive->{file};
ed221350 1576
ff1a2432 1577 return if !$volid || $volid =~ m|^/|;
1e3baf05 1578
6b64503e 1579 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
ff1a2432 1580 return if !$path || !$owner || ($owner != $vmid);
1e3baf05 1581
6b64503e 1582 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05 1583 });
19672434 1584
a6af7b3e 1585 if ($keep_empty_config) {
9c502e26 1586 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
a6af7b3e
DM
1587 } else {
1588 unlink $conffile;
1589 }
1e3baf05
DM
1590
1591 # also remove unused disk
1592 eval {
6b64503e 1593 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1e3baf05
DM
1594
1595 eval {
6b64503e 1596 PVE::Storage::foreach_volid($dl, sub {
1e3baf05 1597 my ($volid, $sid, $volname, $d) = @_;
6b64503e 1598 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05
DM
1599 });
1600 };
1601 warn $@ if $@;
1602
1603 };
1604 warn $@ if $@;
1605}
1606
1e3baf05 1607sub load_config {
7e8dcf2c 1608 my ($vmid, $node) = @_;
1e3baf05 1609
7e8dcf2c 1610 my $cfspath = cfs_config_path($vmid, $node);
1e3baf05
DM
1611
1612 my $conf = PVE::Cluster::cfs_read_file($cfspath);
1613
1614 die "no such VM ('$vmid')\n" if !defined($conf);
1615
1616 return $conf;
19672434 1617}
1e3baf05
DM
1618
1619sub parse_vm_config {
1620 my ($filename, $raw) = @_;
1621
1622 return undef if !defined($raw);
1623
554ac7e7 1624 my $res = {
fc1ddcdc 1625 digest => Digest::SHA::sha1_hex($raw),
0d18dcfc 1626 snapshots => {},
554ac7e7 1627 };
1e3baf05 1628
19672434 1629 $filename =~ m|/qemu-server/(\d+)\.conf$|
1e3baf05
DM
1630 || die "got strange filename '$filename'";
1631
1632 my $vmid = $1;
1633
0d18dcfc 1634 my $conf = $res;
0581fe4f
DM
1635 my $descr = '';
1636
0d18dcfc
DM
1637 my @lines = split(/\n/, $raw);
1638 foreach my $line (@lines) {
1e3baf05 1639 next if $line =~ m/^\s*$/;
be190583 1640
0d18dcfc
DM
1641 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1642 my $snapname = $1;
1643 $conf->{description} = $descr if $descr;
782f4f75 1644 $descr = '';
be190583 1645 $conf = $res->{snapshots}->{$snapname} = {};
0d18dcfc
DM
1646 next;
1647 }
1e3baf05 1648
0581fe4f
DM
1649 if ($line =~ m/^\#(.*)\s*$/) {
1650 $descr .= PVE::Tools::decode_text($1) . "\n";
1651 next;
1652 }
1653
1e3baf05 1654 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
0581fe4f 1655 $descr .= PVE::Tools::decode_text($2);
0d18dcfc
DM
1656 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1657 $conf->{snapstate} = $1;
1e3baf05
DM
1658 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1659 my $key = $1;
1660 my $value = $2;
0d18dcfc 1661 $conf->{$key} = $value;
1e3baf05
DM
1662 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1663 my $key = $1;
1664 my $value = $2;
1665 eval { $value = check_type($key, $value); };
1666 if ($@) {
1667 warn "vm $vmid - unable to parse value of '$key' - $@";
1668 } else {
1669 my $fmt = $confdesc->{$key}->{format};
1670 if ($fmt && $fmt eq 'pve-qm-drive') {
1671 my $v = parse_drive($key, $value);
1672 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
1673 $v->{file} = $volid;
6b64503e 1674 $value = print_drive($vmid, $v);
1e3baf05
DM
1675 } else {
1676 warn "vm $vmid - unable to parse value of '$key'\n";
1677 next;
1678 }
1679 }
1680
1681 if ($key eq 'cdrom') {
0d18dcfc 1682 $conf->{ide2} = $value;
1e3baf05 1683 } else {
0d18dcfc 1684 $conf->{$key} = $value;
1e3baf05
DM
1685 }
1686 }
1687 }
1688 }
1689
0d18dcfc 1690 $conf->{description} = $descr if $descr;
0581fe4f 1691
0d18dcfc 1692 delete $res->{snapstate}; # just to be sure
1e3baf05
DM
1693
1694 return $res;
1695}
1696
1858638f
DM
1697sub write_vm_config {
1698 my ($filename, $conf) = @_;
1e3baf05 1699
0d18dcfc
DM
1700 delete $conf->{snapstate}; # just to be sure
1701
1858638f
DM
1702 if ($conf->{cdrom}) {
1703 die "option ide2 conflicts with cdrom\n" if $conf->{ide2};
1704 $conf->{ide2} = $conf->{cdrom};
1705 delete $conf->{cdrom};
1706 }
1e3baf05
DM
1707
1708 # we do not use 'smp' any longer
1858638f
DM
1709 if ($conf->{sockets}) {
1710 delete $conf->{smp};
1711 } elsif ($conf->{smp}) {
1712 $conf->{sockets} = $conf->{smp};
1713 delete $conf->{cores};
1714 delete $conf->{smp};
1e3baf05
DM
1715 }
1716
ee2f90b1 1717 my $used_volids = {};
0d18dcfc 1718
ee2f90b1 1719 my $cleanup_config = sub {
a8e2f942 1720 my ($cref, $snapname) = @_;
1858638f 1721
ee2f90b1
DM
1722 foreach my $key (keys %$cref) {
1723 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1724 $key eq 'snapstate';
1725 my $value = $cref->{$key};
1726 eval { $value = check_type($key, $value); };
1727 die "unable to parse value of '$key' - $@" if $@;
1858638f 1728
ee2f90b1
DM
1729 $cref->{$key} = $value;
1730
a8e2f942 1731 if (!$snapname && valid_drivename($key)) {
ed221350 1732 my $drive = parse_drive($key, $value);
ee2f90b1
DM
1733 $used_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
1734 }
1e3baf05 1735 }
ee2f90b1
DM
1736 };
1737
1738 &$cleanup_config($conf);
1739 foreach my $snapname (keys %{$conf->{snapshots}}) {
a8e2f942 1740 &$cleanup_config($conf->{snapshots}->{$snapname}, $snapname);
1e3baf05
DM
1741 }
1742
1858638f
DM
1743 # remove 'unusedX' settings if we re-add a volume
1744 foreach my $key (keys %$conf) {
1745 my $value = $conf->{$key};
ee2f90b1 1746 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1858638f 1747 delete $conf->{$key};
1e3baf05 1748 }
1858638f 1749 }
be190583 1750
0d18dcfc
DM
1751 my $generate_raw_config = sub {
1752 my ($conf) = @_;
0581fe4f 1753
0d18dcfc
DM
1754 my $raw = '';
1755
1756 # add description as comment to top of file
1757 my $descr = $conf->{description} || '';
1758 foreach my $cl (split(/\n/, $descr)) {
1759 $raw .= '#' . PVE::Tools::encode_text($cl) . "\n";
1760 }
1761
1762 foreach my $key (sort keys %$conf) {
1763 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1764 $raw .= "$key: $conf->{$key}\n";
1765 }
1766 return $raw;
1767 };
0581fe4f 1768
0d18dcfc
DM
1769 my $raw = &$generate_raw_config($conf);
1770 foreach my $snapname (sort keys %{$conf->{snapshots}}) {
1771 $raw .= "\n[$snapname]\n";
1772 $raw .= &$generate_raw_config($conf->{snapshots}->{$snapname});
1858638f 1773 }
1e3baf05 1774
1858638f
DM
1775 return $raw;
1776}
1e3baf05 1777
1858638f
DM
1778sub update_config_nolock {
1779 my ($vmid, $conf, $skiplock) = @_;
1e3baf05 1780
1858638f 1781 check_lock($conf) if !$skiplock;
97d62eb7 1782
1858638f 1783 my $cfspath = cfs_config_path($vmid);
1e3baf05 1784
1858638f
DM
1785 PVE::Cluster::cfs_write_file($cfspath, $conf);
1786}
1e3baf05 1787
1858638f
DM
1788sub update_config {
1789 my ($vmid, $conf, $skiplock) = @_;
1e3baf05 1790
1858638f 1791 lock_config($vmid, &update_config_nolock, $conf, $skiplock);
1e3baf05
DM
1792}
1793
19672434 1794sub load_defaults {
1e3baf05
DM
1795
1796 my $res = {};
1797
1798 # we use static defaults from our JSON schema configuration
1799 foreach my $key (keys %$confdesc) {
1800 if (defined(my $default = $confdesc->{$key}->{default})) {
1801 $res->{$key} = $default;
1802 }
1803 }
19672434 1804
1e3baf05
DM
1805 my $conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
1806 $res->{keyboard} = $conf->{keyboard} if $conf->{keyboard};
1807
1808 return $res;
1809}
1810
1811sub config_list {
1812 my $vmlist = PVE::Cluster::get_vmlist();
1813 my $res = {};
1814 return $res if !$vmlist || !$vmlist->{ids};
1815 my $ids = $vmlist->{ids};
1816
1e3baf05
DM
1817 foreach my $vmid (keys %$ids) {
1818 my $d = $ids->{$vmid};
1819 next if !$d->{node} || $d->{node} ne $nodename;
5ee957cc 1820 next if !$d->{type} || $d->{type} ne 'qemu';
1e3baf05
DM
1821 $res->{$vmid}->{exists} = 1;
1822 }
1823 return $res;
1824}
1825
64e13401
DM
1826# test if VM uses local resources (to prevent migration)
1827sub check_local_resources {
1828 my ($conf, $noerr) = @_;
1829
1830 my $loc_res = 0;
19672434 1831
e0ab7331
DM
1832 $loc_res = 1 if $conf->{hostusb}; # old syntax
1833 $loc_res = 1 if $conf->{hostpci}; # old syntax
64e13401 1834
0d29ab3b 1835 foreach my $k (keys %$conf) {
2fe1a152 1836 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
64e13401
DM
1837 }
1838
1839 die "VM uses local resources\n" if $loc_res && !$noerr;
1840
1841 return $loc_res;
1842}
1843
719893a9 1844# check if used storages are available on all nodes (use by migrate)
47152e2e
DM
1845sub check_storage_availability {
1846 my ($storecfg, $conf, $node) = @_;
1847
1848 foreach_drive($conf, sub {
1849 my ($ds, $drive) = @_;
1850
1851 my $volid = $drive->{file};
1852 return if !$volid;
1853
1854 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
1855 return if !$sid;
1856
1857 # check if storage is available on both nodes
1858 my $scfg = PVE::Storage::storage_check_node($storecfg, $sid);
1859 PVE::Storage::storage_check_node($storecfg, $sid, $node);
1860 });
1861}
1862
719893a9
DM
1863# list nodes where all VM images are available (used by has_feature API)
1864sub shared_nodes {
1865 my ($conf, $storecfg) = @_;
1866
1867 my $nodelist = PVE::Cluster::get_nodelist();
1868 my $nodehash = { map { $_ => 1 } @$nodelist };
1869 my $nodename = PVE::INotify::nodename();
be190583 1870
719893a9
DM
1871 foreach_drive($conf, sub {
1872 my ($ds, $drive) = @_;
1873
1874 my $volid = $drive->{file};
1875 return if !$volid;
1876
1877 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
1878 if ($storeid) {
1879 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
1880 if ($scfg->{disable}) {
1881 $nodehash = {};
1882 } elsif (my $avail = $scfg->{nodes}) {
1883 foreach my $node (keys %$nodehash) {
1884 delete $nodehash->{$node} if !$avail->{$node};
1885 }
1886 } elsif (!$scfg->{shared}) {
1887 foreach my $node (keys %$nodehash) {
1888 delete $nodehash->{$node} if $node ne $nodename
1889 }
1890 }
1891 }
1892 });
1893
1894 return $nodehash
1895}
1896
1e3baf05
DM
1897sub check_lock {
1898 my ($conf) = @_;
1899
1900 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1901}
1902
1903sub check_cmdline {
1904 my ($pidfile, $pid) = @_;
1905
6b64503e
DM
1906 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
1907 if (defined($fh)) {
1e3baf05
DM
1908 my $line = <$fh>;
1909 $fh->close;
1910 return undef if !$line;
6b64503e 1911 my @param = split(/\0/, $line);
1e3baf05
DM
1912
1913 my $cmd = $param[0];
06094efd 1914 return if !$cmd || ($cmd !~ m|kvm$| && $cmd !~ m|qemu-system-x86_64$|);
1e3baf05
DM
1915
1916 for (my $i = 0; $i < scalar (@param); $i++) {
1917 my $p = $param[$i];
1918 next if !$p;
1919 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1920 my $p = $param[$i+1];
1921 return 1 if $p && ($p eq $pidfile);
1922 return undef;
1923 }
1924 }
1925 }
1926 return undef;
1927}
1928
1929sub check_running {
7e8dcf2c 1930 my ($vmid, $nocheck, $node) = @_;
1e3baf05 1931
7e8dcf2c 1932 my $filename = config_file($vmid, $node);
1e3baf05
DM
1933
1934 die "unable to find configuration file for VM $vmid - no such machine\n"
e6c3b671 1935 if !$nocheck && ! -f $filename;
1e3baf05 1936
e6c3b671 1937 my $pidfile = pidfile_name($vmid);
1e3baf05 1938
e6c3b671
DM
1939 if (my $fd = IO::File->new("<$pidfile")) {
1940 my $st = stat($fd);
1e3baf05 1941 my $line = <$fd>;
6b64503e 1942 close($fd);
1e3baf05
DM
1943
1944 my $mtime = $st->mtime;
1945 if ($mtime > time()) {
1946 warn "file '$filename' modified in future\n";
1947 }
1948
1949 if ($line =~ m/^(\d+)$/) {
1950 my $pid = $1;
e6c3b671
DM
1951 if (check_cmdline($pidfile, $pid)) {
1952 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
1953 return $pid;
1954 }
1955 }
1e3baf05
DM
1956 }
1957 }
1958
1959 return undef;
1960}
1961
1962sub vzlist {
19672434 1963
1e3baf05
DM
1964 my $vzlist = config_list();
1965
6b64503e 1966 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1e3baf05 1967
19672434 1968 while (defined(my $de = $fd->read)) {
1e3baf05
DM
1969 next if $de !~ m/^(\d+)\.pid$/;
1970 my $vmid = $1;
6b64503e
DM
1971 next if !defined($vzlist->{$vmid});
1972 if (my $pid = check_running($vmid)) {
1e3baf05
DM
1973 $vzlist->{$vmid}->{pid} = $pid;
1974 }
1975 }
1976
1977 return $vzlist;
1978}
1979
1e3baf05
DM
1980sub disksize {
1981 my ($storecfg, $conf) = @_;
1982
1983 my $bootdisk = $conf->{bootdisk};
1984 return undef if !$bootdisk;
1985 return undef if !valid_drivename($bootdisk);
1986
1987 return undef if !$conf->{$bootdisk};
1988
1989 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
1990 return undef if !defined($drive);
1991
1992 return undef if drive_is_cdrom($drive);
1993
1994 my $volid = $drive->{file};
1995 return undef if !$volid;
1996
24afaca0 1997 return $drive->{size};
1e3baf05
DM
1998}
1999
2000my $last_proc_pid_stat;
2001
03a33f30
DM
2002# get VM status information
2003# This must be fast and should not block ($full == false)
2004# We only query KVM using QMP if $full == true (this can be slow)
1e3baf05 2005sub vmstatus {
03a33f30 2006 my ($opt_vmid, $full) = @_;
1e3baf05
DM
2007
2008 my $res = {};
2009
19672434 2010 my $storecfg = PVE::Storage::config();
1e3baf05
DM
2011
2012 my $list = vzlist();
694fcad4 2013 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1e3baf05 2014
ae4915a2
DM
2015 my $cpucount = $cpuinfo->{cpus} || 1;
2016
1e3baf05
DM
2017 foreach my $vmid (keys %$list) {
2018 next if $opt_vmid && ($vmid ne $opt_vmid);
2019
2020 my $cfspath = cfs_config_path($vmid);
2021 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
2022
2023 my $d = {};
2024 $d->{pid} = $list->{$vmid}->{pid};
2025
2026 # fixme: better status?
2027 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
2028
af990afe
DM
2029 my $size = disksize($storecfg, $conf);
2030 if (defined($size)) {
2031 $d->{disk} = 0; # no info available
1e3baf05
DM
2032 $d->{maxdisk} = $size;
2033 } else {
2034 $d->{disk} = 0;
2035 $d->{maxdisk} = 0;
2036 }
2037
2038 $d->{cpus} = ($conf->{sockets} || 1) * ($conf->{cores} || 1);
ae4915a2
DM
2039 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
2040
1e3baf05 2041 $d->{name} = $conf->{name} || "VM $vmid";
19672434 2042 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
1e3baf05 2043
8b1accf7 2044 if ($conf->{balloon}) {
4bdb0514 2045 $d->{balloon_min} = $conf->{balloon}*(1024*1024);
074e01c8 2046 $d->{shares} = defined($conf->{shares}) ? $conf->{shares} : 1000;
8b1accf7
DM
2047 }
2048
1e3baf05
DM
2049 $d->{uptime} = 0;
2050 $d->{cpu} = 0;
1e3baf05
DM
2051 $d->{mem} = 0;
2052
2053 $d->{netout} = 0;
2054 $d->{netin} = 0;
2055
2056 $d->{diskread} = 0;
2057 $d->{diskwrite} = 0;
2058
4d8c851b
AD
2059 $d->{template} = is_template($conf);
2060
1e3baf05
DM
2061 $res->{$vmid} = $d;
2062 }
2063
2064 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
2065 foreach my $dev (keys %$netdev) {
2066 next if $dev !~ m/^tap([1-9]\d*)i/;
2067 my $vmid = $1;
2068 my $d = $res->{$vmid};
2069 next if !$d;
19672434 2070
1e3baf05
DM
2071 $d->{netout} += $netdev->{$dev}->{receive};
2072 $d->{netin} += $netdev->{$dev}->{transmit};
2073 }
2074
1e3baf05
DM
2075 my $ctime = gettimeofday;
2076
2077 foreach my $vmid (keys %$list) {
2078
2079 my $d = $res->{$vmid};
2080 my $pid = $d->{pid};
2081 next if !$pid;
2082
694fcad4
DM
2083 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
2084 next if !$pstat; # not running
19672434 2085
694fcad4 2086 my $used = $pstat->{utime} + $pstat->{stime};
1e3baf05 2087
694fcad4 2088 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1e3baf05 2089
694fcad4 2090 if ($pstat->{vsize}) {
6b64503e 2091 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1e3baf05
DM
2092 }
2093
2094 my $old = $last_proc_pid_stat->{$pid};
2095 if (!$old) {
19672434
DM
2096 $last_proc_pid_stat->{$pid} = {
2097 time => $ctime,
1e3baf05
DM
2098 used => $used,
2099 cpu => 0,
1e3baf05
DM
2100 };
2101 next;
2102 }
2103
7f0b5beb 2104 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1e3baf05
DM
2105
2106 if ($dtime > 1000) {
2107 my $dutime = $used - $old->{used};
2108
ae4915a2 2109 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1e3baf05 2110 $last_proc_pid_stat->{$pid} = {
19672434 2111 time => $ctime,
1e3baf05
DM
2112 used => $used,
2113 cpu => $d->{cpu},
1e3baf05
DM
2114 };
2115 } else {
2116 $d->{cpu} = $old->{cpu};
1e3baf05
DM
2117 }
2118 }
2119
f5eb281a 2120 return $res if !$full;
03a33f30
DM
2121
2122 my $qmpclient = PVE::QMPClient->new();
2123
64e7fcf2
DM
2124 my $ballooncb = sub {
2125 my ($vmid, $resp) = @_;
2126
2127 my $info = $resp->{'return'};
2128 return if !$info->{max_mem};
be190583 2129
64e7fcf2
DM
2130 my $d = $res->{$vmid};
2131
2132 # use memory assigned to VM
2133 $d->{maxmem} = $info->{max_mem};
2134 $d->{balloon} = $info->{actual};
be190583 2135
64e7fcf2
DM
2136 if (defined($info->{total_mem}) && defined($info->{free_mem})) {
2137 $d->{mem} = $info->{total_mem} - $info->{free_mem};
2138 $d->{freemem} = $info->{free_mem};
2139 }
2140
2141 };
2142
03a33f30
DM
2143 my $blockstatscb = sub {
2144 my ($vmid, $resp) = @_;
2145 my $data = $resp->{'return'} || [];
2146 my $totalrdbytes = 0;
2147 my $totalwrbytes = 0;
2148 for my $blockstat (@$data) {
2149 $totalrdbytes = $totalrdbytes + $blockstat->{stats}->{rd_bytes};
2150 $totalwrbytes = $totalwrbytes + $blockstat->{stats}->{wr_bytes};
2151 }
2152 $res->{$vmid}->{diskread} = $totalrdbytes;
2153 $res->{$vmid}->{diskwrite} = $totalwrbytes;
2154 };
2155
2156 my $statuscb = sub {
2157 my ($vmid, $resp) = @_;
64e7fcf2 2158
03a33f30 2159 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
64e7fcf2
DM
2160 # this fails if ballon driver is not loaded, so this must be
2161 # the last commnand (following command are aborted if this fails).
2162 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
03a33f30
DM
2163
2164 my $status = 'unknown';
2165 if (!defined($status = $resp->{'return'}->{status})) {
2166 warn "unable to get VM status\n";
2167 return;
2168 }
2169
2170 $res->{$vmid}->{qmpstatus} = $resp->{'return'}->{status};
2171 };
2172
2173 foreach my $vmid (keys %$list) {
2174 next if $opt_vmid && ($vmid ne $opt_vmid);
2175 next if !$res->{$vmid}->{pid}; # not running
2176 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2177 }
2178
2179 $qmpclient->queue_execute();
2180
2181 foreach my $vmid (keys %$list) {
2182 next if $opt_vmid && ($vmid ne $opt_vmid);
2183 $res->{$vmid}->{qmpstatus} = $res->{$vmid}->{status} if !$res->{$vmid}->{qmpstatus};
2184 }
2185
1e3baf05
DM
2186 return $res;
2187}
2188
2189sub foreach_drive {
2190 my ($conf, $func) = @_;
2191
2192 foreach my $ds (keys %$conf) {
2193 next if !valid_drivename($ds);
2194
6b64503e 2195 my $drive = parse_drive($ds, $conf->{$ds});
1e3baf05
DM
2196 next if !$drive;
2197
2198 &$func($ds, $drive);
2199 }
2200}
2201
d5769dc2
DM
2202sub foreach_volid {
2203 my ($conf, $func) = @_;
be190583 2204
d5769dc2
DM
2205 my $volhash = {};
2206
2207 my $test_volid = sub {
2208 my ($volid, $is_cdrom) = @_;
2209
2210 return if !$volid;
be190583 2211
d5769dc2
DM
2212 $volhash->{$volid} = $is_cdrom || 0;
2213 };
2214
ed221350 2215 foreach_drive($conf, sub {
d5769dc2
DM
2216 my ($ds, $drive) = @_;
2217 &$test_volid($drive->{file}, drive_is_cdrom($drive));
2218 });
2219
2220 foreach my $snapname (keys %{$conf->{snapshots}}) {
2221 my $snap = $conf->{snapshots}->{$snapname};
2222 &$test_volid($snap->{vmstate}, 0);
ed221350 2223 foreach_drive($snap, sub {
d5769dc2
DM
2224 my ($ds, $drive) = @_;
2225 &$test_volid($drive->{file}, drive_is_cdrom($drive));
2226 });
2227 }
2228
2229 foreach my $volid (keys %$volhash) {
be190583 2230 &$func($volid, $volhash->{$volid});
d5769dc2
DM
2231 }
2232}
2233
1e3baf05 2234sub config_to_command {
952958bc 2235 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
1e3baf05
DM
2236
2237 my $cmd = [];
8c559505
DM
2238 my $globalFlags = [];
2239 my $machineFlags = [];
2240 my $rtcFlags = [];
519ed28c 2241 my $cpuFlags = [];
5bdcf937 2242 my $devices = [];
b78ebef7 2243 my $pciaddr = '';
5bdcf937 2244 my $bridges = {};
1e3baf05
DM
2245 my $kvmver = kvm_user_version();
2246 my $vernum = 0; # unknown
a3c52213
DM
2247 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2248 $vernum = $1*1000000+$2*1000;
2249 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1e3baf05
DM
2250 $vernum = $1*1000000+$2*1000+$3;
2251 }
2252
a3c52213 2253 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1e3baf05
DM
2254
2255 my $have_ovz = -f '/proc/vz/vestat';
2256
2257 push @$cmd, '/usr/bin/kvm';
2258
2259 push @$cmd, '-id', $vmid;
2260
2261 my $use_virtio = 0;
2262
c971c4f2
AD
2263 my $qmpsocket = qmp_socket($vmid);
2264 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2265 push @$cmd, '-mon', "chardev=qmp,mode=control";
2266
7b7c6d1b 2267 my $socket = vnc_socket($vmid);
1e3baf05
DM
2268 push @$cmd, '-vnc', "unix:$socket,x509,password";
2269
6b64503e 2270 push @$cmd, '-pidfile' , pidfile_name($vmid);
19672434 2271
1e3baf05
DM
2272 push @$cmd, '-daemonize';
2273
24f0d39a
AD
2274 $pciaddr = print_pci_addr("piix3", $bridges);
2275 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2276
fcc573ab
DM
2277 my $use_usb2 = 0;
2278 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2279 next if !$conf->{"usb$i"};
2280 $use_usb2 = 1;
2281 }
2282 # include usb device config
2283 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
19672434 2284
5acbfe9e
DM
2285 my $vga = $conf->{vga};
2286 if (!$vga) {
2287 if ($conf->{ostype} && ($conf->{ostype} eq 'win8' ||
2288 $conf->{ostype} eq 'win7' ||
2289 $conf->{ostype} eq 'w2k8')) {
2290 $vga = 'std';
2291 } else {
2292 $vga = 'cirrus';
2293 }
2294 }
2295
1e3baf05 2296 # enable absolute mouse coordinates (needed by vnc)
5acbfe9e
DM
2297 my $tablet;
2298 if (defined($conf->{tablet})) {
2299 $tablet = $conf->{tablet};
2300 } else {
2301 $tablet = $defaults->{tablet};
2302 $tablet = 0 if $vga eq 'qxl'; # disable for spice because it is not needed
2303 }
2304
0ecf8463 2305 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
1e3baf05
DM
2306
2307 # host pci devices
040b06b7
DA
2308 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2309 my $d = parse_hostpci($conf->{"hostpci$i"});
2310 next if !$d;
5bdcf937
AD
2311 $pciaddr = print_pci_addr("hostpci$i", $bridges);
2312 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
1e3baf05
DM
2313 }
2314
2315 # usb devices
2316 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2317 my $d = parse_usb_device($conf->{"usb$i"});
2318 next if !$d;
2319 if ($d->{vendorid} && $d->{productid}) {
5bdcf937 2320 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
1e3baf05 2321 } elsif (defined($d->{hostbus}) && defined($d->{hostport})) {
5bdcf937 2322 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
80401dd8
DM
2323 } elsif ($d->{spice}) {
2324 # usb redir support for spice
2325 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2326 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
1e3baf05
DM
2327 }
2328 }
2329
1e3baf05 2330 # serial devices
bae179aa 2331 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
34978be3 2332 if (my $path = $conf->{"serial$i"}) {
19672434 2333 die "no such serial device\n" if ! -c $path;
5bdcf937
AD
2334 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2335 push @$devices, '-device', "isa-serial,chardev=serial$i";
34978be3 2336 }
1e3baf05
DM
2337 }
2338
2339 # parallel devices
1989a89c 2340 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
34978be3 2341 if (my $path = $conf->{"parallel$i"}) {
19672434 2342 die "no such parallel device\n" if ! -c $path;
5bdcf937
AD
2343 push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
2344 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
34978be3 2345 }
1e3baf05
DM
2346 }
2347
2348 my $vmname = $conf->{name} || "vm$vmid";
2349
2350 push @$cmd, '-name', $vmname;
19672434 2351
1e3baf05
DM
2352 my $sockets = 1;
2353 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
2354 $sockets = $conf->{sockets} if $conf->{sockets};
2355
2356 my $cores = $conf->{cores} || 1;
1e3baf05
DM
2357 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2358
1e3baf05
DM
2359 push @$cmd, '-nodefaults';
2360
32baffb4 2361 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
3b408e82 2362
0888fdce
DM
2363 my $bootindex_hash = {};
2364 my $i = 1;
2365 foreach my $o (split(//, $bootorder)) {
2366 $bootindex_hash->{$o} = $i*100;
2367 $i++;
afdb31d5 2368 }
3b408e82
DM
2369
2370 push @$cmd, '-boot', "menu=on";
1e3baf05 2371
6b64503e 2372 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
1e3baf05 2373
6b64503e 2374 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
1e3baf05 2375
1e3baf05
DM
2376 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2377
2378 # time drift fix
6b64503e 2379 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
1e3baf05 2380
6b64503e 2381 my $nokvm = defined($conf->{kvm}) && $conf->{kvm} == 0 ? 1 : 0;
8c559505 2382 my $useLocaltime = $conf->{localtime};
1e3baf05
DM
2383
2384 if (my $ost = $conf->{ostype}) {
a70ebde3 2385 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26
1e3baf05
DM
2386
2387 if ($ost =~ m/^w/) { # windows
8c559505 2388 $useLocaltime = 1 if !defined($conf->{localtime});
1e3baf05 2389
8c559505 2390 # use time drift fix when acpi is enabled
6b64503e 2391 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
8c559505 2392 $tdf = 1 if !defined($conf->{tdf});
1e3baf05
DM
2393 }
2394 }
2395
be190583 2396 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
a70ebde3 2397 $ost eq 'wvista') {
8c559505 2398 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
b7e0c8bf 2399 push @$cmd, '-no-hpet';
462e8d19
AD
2400 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2401 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2402 }
2403
2404 if ($ost eq 'win7' || $ost eq 'win8') {
2405 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
b7e0c8bf 2406 }
1e3baf05
DM
2407 }
2408
8c559505
DM
2409 push @$rtcFlags, 'driftfix=slew' if $tdf;
2410
7f0b5beb 2411 if ($nokvm) {
8c559505 2412 push @$machineFlags, 'accel=tcg';
7f0b5beb
DM
2413 } else {
2414 die "No accelerator found!\n" if !$cpuinfo->{hvm};
2415 }
1e3baf05 2416
952958bc
DM
2417 my $machine_type = $forcemachine || $conf->{machine};
2418 if ($machine_type) {
2419 push @$machineFlags, "type=${machine_type}";
3bafc510
DM
2420 }
2421
8c559505
DM
2422 if ($conf->{startdate}) {
2423 push @$rtcFlags, "base=$conf->{startdate}";
2424 } elsif ($useLocaltime) {
2425 push @$rtcFlags, 'base=localtime';
2426 }
1e3baf05 2427
519ed28c
AD
2428 my $cpu = $nokvm ? "qemu64" : "kvm64";
2429 $cpu = $conf->{cpu} if $conf->{cpu};
2430
2431 push @$cpuFlags , '+x2apic' if !$nokvm;
2432
2e1a5389
AD
2433 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2434
be190583 2435 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
519ed28c
AD
2436
2437 push @$cmd, '-cpu', $cpu;
2438
1e3baf05
DM
2439 push @$cmd, '-S' if $conf->{freeze};
2440
2441 # set keyboard layout
2442 my $kb = $conf->{keyboard} || $defaults->{keyboard};
2443 push @$cmd, '-k', $kb if $kb;
2444
2445 # enable sound
2446 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2447 #push @$cmd, '-soundhw', 'es1370';
2448 #push @$cmd, '-soundhw', $soundhw if $soundhw;
ab6a046f 2449
bc84dcca 2450 if($conf->{agent}) {
ab6a046f
AD
2451 my $qgasocket = qga_socket($vmid);
2452 my $pciaddr = print_pci_addr("qga0", $bridges);
2453 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2454 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2455 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2456 }
2457
1011b570
DM
2458 if ($vga eq 'qxl') {
2459 my $pciaddr = print_pci_addr("spice", $bridges);
943340a6
DM
2460
2461 my $port = PVE::Tools::next_unused_port(61000, 61099);
2462
d685bd1d 2463 push @$cmd, '-spice', "tls-port=$port,addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA";
1011b570 2464
1011b570
DM
2465 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2466 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2467 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2468 }
2469
8d9ae0d2
DM
2470 # enable balloon by default, unless explicitly disabled
2471 if (!defined($conf->{balloon}) || $conf->{balloon}) {
2472 $pciaddr = print_pci_addr("balloon0", $bridges);
2473 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2474 }
1e3baf05 2475
0ea9541d
DM
2476 if ($conf->{watchdog}) {
2477 my $wdopts = parse_watchdog($conf->{watchdog});
5bdcf937 2478 $pciaddr = print_pci_addr("watchdog", $bridges);
0a40e8ea 2479 my $watchdog = $wdopts->{model} || 'i6300esb';
5bdcf937
AD
2480 push @$devices, '-device', "$watchdog$pciaddr";
2481 push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
0ea9541d
DM
2482 }
2483
1e3baf05 2484 my $vollist = [];
941e0c42 2485 my $scsicontroller = {};
26ee04b6 2486 my $ahcicontroller = {};
cdd20088 2487 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : $defaults->{scsihw};
1e3baf05
DM
2488
2489 foreach_drive($conf, sub {
2490 my ($ds, $drive) = @_;
2491
ff1a2432 2492 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
1e3baf05 2493 push @$vollist, $drive->{file};
ff1a2432 2494 }
afdb31d5 2495
1e3baf05 2496 $use_virtio = 1 if $ds =~ m/^virtio/;
3b408e82
DM
2497
2498 if (drive_is_cdrom ($drive)) {
2499 if ($bootindex_hash->{d}) {
2500 $drive->{bootindex} = $bootindex_hash->{d};
2501 $bootindex_hash->{d} += 1;
2502 }
2503 } else {
2504 if ($bootindex_hash->{c}) {
2505 $drive->{bootindex} = $bootindex_hash->{c} if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
2506 $bootindex_hash->{c} += 1;
2507 }
2508 }
2509
941e0c42 2510 if ($drive->{interface} eq 'scsi') {
cdd20088
AD
2511
2512 my $maxdev = ($scsihw ne 'lsi') ? 256 : 7;
2513 my $controller = int($drive->{index} / $maxdev);
5bdcf937
AD
2514 $pciaddr = print_pci_addr("scsihw$controller", $bridges);
2515 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
cdd20088 2516 $scsicontroller->{$controller}=1;
941e0c42 2517 }
3b408e82 2518
26ee04b6
DA
2519 if ($drive->{interface} eq 'sata') {
2520 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
5bdcf937
AD
2521 $pciaddr = print_pci_addr("ahci$controller", $bridges);
2522 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
26ee04b6
DA
2523 $ahcicontroller->{$controller}=1;
2524 }
2525
5bdcf937
AD
2526 push @$devices, '-drive',print_drive_full($storecfg, $vmid, $drive);
2527 push @$devices, '-device',print_drivedevice_full($storecfg, $conf, $vmid, $drive, $bridges);
1e3baf05
DM
2528 });
2529
2530 push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
19672434 2531
cc4d6182 2532 for (my $i = 0; $i < $MAX_NETS; $i++) {
5f0c4c32 2533 next if !$conf->{"net$i"};
cc4d6182
DA
2534 my $d = parse_net($conf->{"net$i"});
2535 next if !$d;
1e3baf05 2536
cc4d6182 2537 $use_virtio = 1 if $d->{model} eq 'virtio';
1e3baf05 2538
cc4d6182
DA
2539 if ($bootindex_hash->{n}) {
2540 $d->{bootindex} = $bootindex_hash->{n};
2541 $bootindex_hash->{n} += 1;
2542 }
1e3baf05 2543
cc4d6182 2544 my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i");
5bdcf937
AD
2545 push @$devices, '-netdev', $netdevfull;
2546
2547 my $netdevicefull = print_netdevice_full($vmid,$conf,$d,"net$i",$bridges);
2548 push @$devices, '-device', $netdevicefull;
2549 }
1e3baf05 2550
5bdcf937
AD
2551 #bridges
2552 while (my ($k, $v) = each %$bridges) {
2553 $pciaddr = print_pci_addr("pci.$k");
2554 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
19672434
DM
2555 }
2556
1e3baf05
DM
2557
2558 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2559 # when the VM uses virtio devices.
19672434
DM
2560 if (!$use_virtio && $have_ovz) {
2561
6b64503e 2562 my $cpuunits = defined($conf->{cpuunits}) ?
1e3baf05
DM
2563 $conf->{cpuunits} : $defaults->{cpuunits};
2564
2565 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2566
2567 # fixme: cpulimit is currently ignored
2568 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2569 }
2570
2571 # add custom args
2572 if ($conf->{args}) {
3ada46c9 2573 my $aa = PVE::Tools::split_args($conf->{args});
1e3baf05
DM
2574 push @$cmd, @$aa;
2575 }
2576
5bdcf937 2577 push @$cmd, @$devices;
be190583 2578 push @$cmd, '-rtc', join(',', @$rtcFlags)
8c559505 2579 if scalar(@$rtcFlags);
be190583 2580 push @$cmd, '-machine', join(',', @$machineFlags)
8c559505
DM
2581 if scalar(@$machineFlags);
2582 push @$cmd, '-global', join(',', @$globalFlags)
2583 if scalar(@$globalFlags);
2584
1e3baf05
DM
2585 return wantarray ? ($cmd, $vollist) : $cmd;
2586}
19672434 2587
1e3baf05
DM
2588sub vnc_socket {
2589 my ($vmid) = @_;
2590 return "${var_run_tmpdir}/$vmid.vnc";
2591}
2592
943340a6 2593sub spice_port {
1011b570 2594 my ($vmid) = @_;
943340a6
DM
2595
2596 my $res = vm_mon_cmd($vmid, 'query-spice');
2597
2598 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
1011b570
DM
2599}
2600
c971c4f2
AD
2601sub qmp_socket {
2602 my ($vmid) = @_;
2603 return "${var_run_tmpdir}/$vmid.qmp";
2604}
2605
ab6a046f
AD
2606sub qga_socket {
2607 my ($vmid) = @_;
2608 return "${var_run_tmpdir}/$vmid.qga";
2609}
2610
1e3baf05
DM
2611sub pidfile_name {
2612 my ($vmid) = @_;
2613 return "${var_run_tmpdir}/$vmid.pid";
2614}
2615
86fdcfb2
DA
2616sub vm_devices_list {
2617 my ($vmid) = @_;
2618
ceea9078
DM
2619 my $res = vm_mon_cmd($vmid, 'query-pci');
2620
2621 my $devices = {};
2622 foreach my $pcibus (@$res) {
2623 foreach my $device (@{$pcibus->{devices}}) {
2624 next if !$device->{'qdev_id'};
2625 $devices->{$device->{'qdev_id'}} = $device;
1dc4f496
DM
2626 }
2627 }
86fdcfb2 2628
1dc4f496 2629 return $devices;
86fdcfb2
DA
2630}
2631
ec21aa11 2632sub vm_deviceplug {
f19d1c47 2633 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
ae57f6b3 2634
cd6ecb89
AD
2635 return 1 if !check_running($vmid);
2636
2637 if ($deviceid eq 'tablet') {
0ecf8463 2638 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
cd6ecb89
AD
2639 qemu_deviceadd($vmid, $devicefull);
2640 return 1;
2641 }
2642
2dbe827e 2643 return 1 if !$conf->{hotplug};
afdb31d5 2644
95d6343b
DA
2645 my $devices_list = vm_devices_list($vmid);
2646 return 1 if defined($devices_list->{$deviceid});
2647
40f28a9f
AD
2648 qemu_bridgeadd($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2649
5e5dcb73
DA
2650 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2651 return undef if !qemu_driveadd($storecfg, $vmid, $device);
cdd20088 2652 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
5e5dcb73
DA
2653 qemu_deviceadd($vmid, $devicefull);
2654 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2655 qemu_drivedel($vmid, $deviceid);
2656 return undef;
2657 }
f19d1c47 2658 }
cfc817c7 2659
cdd20088
AD
2660 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2661 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
cfc817c7 2662 my $pciaddr = print_pci_addr($deviceid);
cdd20088 2663 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
cfc817c7
DA
2664 qemu_deviceadd($vmid, $devicefull);
2665 return undef if(!qemu_deviceaddverify($vmid, $deviceid));
2666 }
2667
a4f091a0 2668 if ($deviceid =~ m/^(scsi)(\d+)$/) {
cdd20088
AD
2669 return 1 if ($conf->{scsihw} && $conf->{scsihw} ne 'lsi'); #virtio-scsi not yet support hotplug
2670 return undef if !qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
a4f091a0 2671 return undef if !qemu_driveadd($storecfg, $vmid, $device);
cdd20088 2672 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
a4f091a0
DA
2673 if(!qemu_deviceadd($vmid, $devicefull)) {
2674 qemu_drivedel($vmid, $deviceid);
2675 return undef;
2676 }
2677 }
2678
2630d2a9
DA
2679 if ($deviceid =~ m/^(net)(\d+)$/) {
2680 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
2681 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid);
2682 qemu_deviceadd($vmid, $netdevicefull);
2683 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2684 qemu_netdevdel($vmid, $deviceid);
2685 return undef;
2686 }
2687 }
2688
40f28a9f
AD
2689 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2690 my $bridgeid = $2;
2691 my $pciaddr = print_pci_addr($deviceid);
2692 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2693 qemu_deviceadd($vmid, $devicefull);
2694 return undef if !qemu_deviceaddverify($vmid, $deviceid);
2695 }
2696
5e5dcb73 2697 return 1;
a4dea331
DA
2698}
2699
ec21aa11 2700sub vm_deviceunplug {
f19d1c47 2701 my ($vmid, $conf, $deviceid) = @_;
873c2d69 2702
cd6ecb89
AD
2703 return 1 if !check_running ($vmid);
2704
2705 if ($deviceid eq 'tablet') {
2706 qemu_devicedel($vmid, $deviceid);
2707 return 1;
2708 }
2709
2dbe827e 2710 return 1 if !$conf->{hotplug};
873c2d69 2711
95d6343b
DA
2712 my $devices_list = vm_devices_list($vmid);
2713 return 1 if !defined($devices_list->{$deviceid});
2714
ae57f6b3 2715 die "can't unplug bootdisk" if $conf->{bootdisk} && $conf->{bootdisk} eq $deviceid;
f19d1c47 2716
5e5dcb73 2717 if ($deviceid =~ m/^(virtio)(\d+)$/) {
5e5dcb73
DA
2718 qemu_devicedel($vmid, $deviceid);
2719 return undef if !qemu_devicedelverify($vmid, $deviceid);
1f219ef5 2720 return undef if !qemu_drivedel($vmid, $deviceid);
5e5dcb73 2721 }
cfc817c7
DA
2722
2723 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2724 return undef if !qemu_devicedel($vmid, $deviceid);
2725 }
2726
a4f091a0
DA
2727 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2728 return undef if !qemu_devicedel($vmid, $deviceid);
2729 return undef if !qemu_drivedel($vmid, $deviceid);
2730 }
2731
2630d2a9 2732 if ($deviceid =~ m/^(net)(\d+)$/) {
2630d2a9
DA
2733 qemu_devicedel($vmid, $deviceid);
2734 return undef if !qemu_devicedelverify($vmid, $deviceid);
750886f8 2735 return undef if !qemu_netdevdel($vmid, $deviceid);
2630d2a9
DA
2736 }
2737
5e5dcb73
DA
2738 return 1;
2739}
2740
2741sub qemu_deviceadd {
2742 my ($vmid, $devicefull) = @_;
873c2d69 2743
d695b5b7
AD
2744 $devicefull = "driver=".$devicefull;
2745 my %options = split(/[=,]/, $devicefull);
f19d1c47 2746
d695b5b7
AD
2747 vm_mon_cmd($vmid, "device_add" , %options);
2748 return 1;
5e5dcb73 2749}
afdb31d5 2750
5e5dcb73
DA
2751sub qemu_devicedel {
2752 my($vmid, $deviceid) = @_;
5a77d8c1
AD
2753 my $ret = vm_mon_cmd($vmid, "device_del", id => $deviceid);
2754 return 1;
5e5dcb73
DA
2755}
2756
2757sub qemu_driveadd {
2758 my($storecfg, $vmid, $device) = @_;
2759
2760 my $drive = print_drive_full($storecfg, $vmid, $device);
7b7c6d1b 2761 my $ret = vm_human_monitor_command($vmid, "drive_add auto $drive");
5e5dcb73
DA
2762 # If the command succeeds qemu prints: "OK"
2763 if ($ret !~ m/OK/s) {
2764 syslog("err", "adding drive failed: $ret");
2765 return undef;
f19d1c47 2766 }
5e5dcb73
DA
2767 return 1;
2768}
afdb31d5 2769
5e5dcb73
DA
2770sub qemu_drivedel {
2771 my($vmid, $deviceid) = @_;
873c2d69 2772
7b7c6d1b 2773 my $ret = vm_human_monitor_command($vmid, "drive_del drive-$deviceid");
5e5dcb73
DA
2774 $ret =~ s/^\s+//;
2775 if ($ret =~ m/Device \'.*?\' not found/s) {
afdb31d5 2776 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
5e5dcb73
DA
2777 }
2778 elsif ($ret ne "") {
2779 syslog("err", "deleting drive $deviceid failed : $ret");
2780 return undef;
873c2d69 2781 }
5e5dcb73
DA
2782 return 1;
2783}
f19d1c47 2784
5e5dcb73
DA
2785sub qemu_deviceaddverify {
2786 my ($vmid,$deviceid) = @_;
873c2d69 2787
5e5dcb73
DA
2788 for (my $i = 0; $i <= 5; $i++) {
2789 my $devices_list = vm_devices_list($vmid);
2790 return 1 if defined($devices_list->{$deviceid});
2791 sleep 1;
afdb31d5 2792 }
5e5dcb73
DA
2793 syslog("err", "error on hotplug device $deviceid");
2794 return undef;
2795}
afdb31d5 2796
5e5dcb73
DA
2797
2798sub qemu_devicedelverify {
2799 my ($vmid,$deviceid) = @_;
2800
2801 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2802 for (my $i = 0; $i <= 5; $i++) {
2803 my $devices_list = vm_devices_list($vmid);
2804 return 1 if !defined($devices_list->{$deviceid});
2805 sleep 1;
afdb31d5 2806 }
5e5dcb73
DA
2807 syslog("err", "error on hot-unplugging device $deviceid");
2808 return undef;
873c2d69
DA
2809}
2810
cdd20088 2811sub qemu_findorcreatescsihw {
cfc817c7
DA
2812 my ($storecfg, $conf, $vmid, $device) = @_;
2813
cdd20088 2814 my $maxdev = ($conf->{scsihw} && $conf->{scsihw} ne 'lsi') ? 256 : 7;
cfc817c7 2815 my $controller = int($device->{index} / $maxdev);
cdd20088 2816 my $scsihwid="scsihw$controller";
cfc817c7
DA
2817 my $devices_list = vm_devices_list($vmid);
2818
cdd20088
AD
2819 if(!defined($devices_list->{$scsihwid})) {
2820 return undef if !vm_deviceplug($storecfg, $conf, $vmid, $scsihwid);
cfc817c7
DA
2821 }
2822 return 1;
2823}
2824
40f28a9f
AD
2825sub qemu_bridgeadd {
2826 my ($storecfg, $conf, $vmid, $device) = @_;
2827
2828 my $bridges = {};
2829 my $bridgeid = undef;
2830 print_pci_addr($device, $bridges);
2831
2832 while (my ($k, $v) = each %$bridges) {
2833 $bridgeid = $k;
2834 }
0e616534 2835 return if !$bridgeid || $bridgeid < 1;
40f28a9f
AD
2836 my $bridge = "pci.$bridgeid";
2837 my $devices_list = vm_devices_list($vmid);
2838
2839 if(!defined($devices_list->{$bridge})) {
2840 return undef if !vm_deviceplug($storecfg, $conf, $vmid, $bridge);
2841 }
2842 return 1;
2843}
2844
2630d2a9
DA
2845sub qemu_netdevadd {
2846 my ($vmid, $conf, $device, $deviceid) = @_;
2847
2848 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
73aa03b8 2849 my %options = split(/[=,]/, $netdev);
2630d2a9 2850
73aa03b8
AD
2851 vm_mon_cmd($vmid, "netdev_add", %options);
2852 return 1;
2630d2a9
DA
2853}
2854
2855sub qemu_netdevdel {
2856 my ($vmid, $deviceid) = @_;
2857
89c1e0f4
AD
2858 vm_mon_cmd($vmid, "netdev_del", id => $deviceid);
2859 return 1;
2630d2a9
DA
2860}
2861
affd2f88
AD
2862sub qemu_block_set_io_throttle {
2863 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2864
f3f323a3
AD
2865 return if !check_running($vmid) ;
2866
f3f323a3
AD
2867 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));
2868
affd2f88
AD
2869}
2870
f5eb281a 2871# old code, only used to shutdown old VM after update
dab36e1e
DM
2872sub __read_avail {
2873 my ($fh, $timeout) = @_;
2874
2875 my $sel = new IO::Select;
2876 $sel->add($fh);
2877
2878 my $res = '';
2879 my $buf;
2880
2881 my @ready;
2882 while (scalar (@ready = $sel->can_read($timeout))) {
2883 my $count;
2884 if ($count = $fh->sysread($buf, 8192)) {
2885 if ($buf =~ /^(.*)\(qemu\) $/s) {
2886 $res .= $1;
2887 last;
2888 } else {
2889 $res .= $buf;
2890 }
2891 } else {
2892 if (!defined($count)) {
2893 die "$!\n";
2894 }
2895 last;
2896 }
2897 }
2898
2899 die "monitor read timeout\n" if !scalar(@ready);
f5eb281a 2900
dab36e1e
DM
2901 return $res;
2902}
2903
f5eb281a 2904# old code, only used to shutdown old VM after update
dab36e1e
DM
2905sub vm_monitor_command {
2906 my ($vmid, $cmdstr, $nocheck) = @_;
f5eb281a 2907
dab36e1e
DM
2908 my $res;
2909
2910 eval {
2911 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
2912
2913 my $sname = "${var_run_tmpdir}/$vmid.mon";
2914
2915 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
2916 die "unable to connect to VM $vmid socket - $!\n";
2917
2918 my $timeout = 3;
2919
2920 # hack: migrate sometime blocks the monitor (when migrate_downtime
2921 # is set)
2922 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2923 $timeout = 60*60; # 1 hour
2924 }
2925
2926 # read banner;
2927 my $data = __read_avail($sock, $timeout);
2928
2929 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2930 die "got unexpected qemu monitor banner\n";
2931 }
2932
2933 my $sel = new IO::Select;
2934 $sel->add($sock);
2935
2936 if (!scalar(my @ready = $sel->can_write($timeout))) {
2937 die "monitor write error - timeout";
2938 }
2939
2940 my $fullcmd = "$cmdstr\r";
2941
2942 # syslog('info', "VM $vmid monitor command: $cmdstr");
2943
2944 my $b;
2945 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2946 die "monitor write error - $!";
2947 }
2948
2949 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2950
2951 $timeout = 20;
2952
2953 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2954 $timeout = 60*60; # 1 hour
2955 } elsif ($cmdstr =~ m/^(eject|change)/) {
2956 $timeout = 60; # note: cdrom mount command is slow
2957 }
2958 if ($res = __read_avail($sock, $timeout)) {
2959
2960 my @lines = split("\r?\n", $res);
f5eb281a 2961
dab36e1e 2962 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
f5eb281a 2963
dab36e1e
DM
2964 $res = join("\n", @lines);
2965 $res .= "\n";
2966 }
2967 };
2968
2969 my $err = $@;
2970
2971 if ($err) {
2972 syslog("err", "VM $vmid monitor command failed - $err");
2973 die $err;
2974 }
f5eb281a 2975
dab36e1e
DM
2976 return $res;
2977}
2978
c1175c92
AD
2979sub qemu_block_resize {
2980 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
2981
ed221350 2982 my $running = check_running($vmid);
c1175c92
AD
2983
2984 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
2985
2986 return if !$running;
2987
2988 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
2989
2990}
2991
1ab0057c
AD
2992sub qemu_volume_snapshot {
2993 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2994
ed221350 2995 my $running = check_running($vmid);
1ab0057c
AD
2996
2997 return if !PVE::Storage::volume_snapshot($storecfg, $volid, $snap, $running);
2998
2999 return if !$running;
3000
3001 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3002
3003}
3004
fc46aff9
AD
3005sub qemu_volume_snapshot_delete {
3006 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3007
ed221350 3008 my $running = check_running($vmid);
fc46aff9
AD
3009
3010 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3011
3012 return if !$running;
3013
18bfb361 3014 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
fc46aff9
AD
3015}
3016
3d5149c9
AD
3017sub qga_freezefs {
3018 my ($vmid) = @_;
3019
3020 #need to impplement call to qemu-ga
3021}
3022
e8f3f18e
AD
3023sub qga_unfreezefs {
3024 my ($vmid) = @_;
3025
3026 #need to impplement call to qemu-ga
3027}
3028
1e3baf05 3029sub vm_start {
952958bc 3030 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine) = @_;
1e3baf05 3031
6b64503e 3032 lock_config($vmid, sub {
7e8dcf2c 3033 my $conf = load_config($vmid, $migratedfrom);
1e3baf05 3034
8b43bc11 3035 die "you can't start a vm if it's a template\n" if is_template($conf);
3dcb98d5 3036
6b64503e 3037 check_lock($conf) if !$skiplock;
1e3baf05 3038
7e8dcf2c 3039 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
1e3baf05 3040
6c47d546
DM
3041 my $defaults = load_defaults();
3042
3043 # set environment variable useful inside network script
3044 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
3045
952958bc 3046 my ($cmd, $vollist) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
6c47d546 3047
1e3baf05
DM
3048 my $migrate_port = 0;
3049
3050 if ($statefile) {
3051 if ($statefile eq 'tcp') {
f9a971e0 3052 $migrate_port = PVE::Tools::next_migrate_port();
6c47d546
DM
3053 my $migrate_uri = "tcp:localhost:${migrate_port}";
3054 push @$cmd, '-incoming', $migrate_uri;
3055 push @$cmd, '-S';
1e3baf05 3056 } else {
6c47d546 3057 push @$cmd, '-loadstate', $statefile;
1e3baf05 3058 }
91bd6c90
DM
3059 } elsif ($paused) {
3060 push @$cmd, '-S';
1e3baf05
DM
3061 }
3062
1e3baf05 3063 # host pci devices
040b06b7
DA
3064 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3065 my $d = parse_hostpci($conf->{"hostpci$i"});
3066 next if !$d;
3067 my $info = pci_device_info("0000:$d->{pciid}");
3068 die "IOMMU not present\n" if !check_iommu_support();
3069 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3070 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub($info);
3071 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset($info);
3072 }
1e3baf05
DM
3073
3074 PVE::Storage::activate_volumes($storecfg, $vollist);
3075
585b6e28
DM
3076 eval { run_command($cmd, timeout => $statefile ? undef : 30,
3077 umask => 0077); };
1e3baf05 3078 my $err = $@;
ff1a2432 3079 die "start failed: $err" if $err;
1e3baf05 3080
6c47d546 3081 print "migration listens on port $migrate_port\n" if $migrate_port;
afdb31d5 3082
8c609afd 3083 if ($statefile && $statefile ne 'tcp') {
95381ce0 3084 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
8c609afd 3085 warn $@ if $@;
62de2cbd
DM
3086 }
3087
e18b0b99
AD
3088 if($migratedfrom) {
3089 my $capabilities = {};
3090 $capabilities->{capability} = "xbzrle";
3091 $capabilities->{state} = JSON::true;
ed221350 3092 eval { vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => [$capabilities]); };
8b1accf7 3093 }
4ec05c4c
AD
3094 else{
3095
15b1fc93 3096 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
be190583 3097 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4ec05c4c 3098 if $conf->{balloon};
be190583
DM
3099 vm_mon_cmd_nocheck($vmid, 'qom-set',
3100 path => "machine/peripheral/balloon0",
3101 property => "guest-stats-polling-interval",
4ec05c4c
AD
3102 value => 2);
3103 }
e18b0b99 3104 }
1e3baf05
DM
3105 });
3106}
3107
0eedc444
AD
3108sub vm_mon_cmd {
3109 my ($vmid, $execute, %params) = @_;
3110
26f11676
DM
3111 my $cmd = { execute => $execute, arguments => \%params };
3112 vm_qmp_command($vmid, $cmd);
0eedc444
AD
3113}
3114
3115sub vm_mon_cmd_nocheck {
3116 my ($vmid, $execute, %params) = @_;
3117
26f11676
DM
3118 my $cmd = { execute => $execute, arguments => \%params };
3119 vm_qmp_command($vmid, $cmd, 1);
0eedc444
AD
3120}
3121
c971c4f2 3122sub vm_qmp_command {
d967756b 3123 my ($vmid, $cmd, $nocheck) = @_;
97d62eb7 3124
c971c4f2 3125 my $res;
26f11676 3126
14db5366
DM
3127 my $timeout;
3128 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
3129 $timeout = $cmd->{arguments}->{timeout};
3130 delete $cmd->{arguments}->{timeout};
3131 }
be190583 3132
c971c4f2
AD
3133 eval {
3134 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
ed221350 3135 my $sname = qmp_socket($vmid);
f5eb281a 3136 if (-e $sname) {
dab36e1e
DM
3137 my $qmpclient = PVE::QMPClient->new();
3138
14db5366 3139 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
dab36e1e
DM
3140 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
3141 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3142 if scalar(%{$cmd->{arguments}});
3143 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
3144 } else {
3145 die "unable to open monitor socket\n";
3146 }
c971c4f2 3147 };
26f11676 3148 if (my $err = $@) {
c971c4f2
AD
3149 syslog("err", "VM $vmid qmp command failed - $err");
3150 die $err;
3151 }
3152
3153 return $res;
3154}
3155
9df5cbcc
DM
3156sub vm_human_monitor_command {
3157 my ($vmid, $cmdline) = @_;
3158
3159 my $res;
3160
f5eb281a 3161 my $cmd = {
9df5cbcc
DM
3162 execute => 'human-monitor-command',
3163 arguments => { 'command-line' => $cmdline},
3164 };
3165
3166 return vm_qmp_command($vmid, $cmd);
3167}
3168
1e3baf05
DM
3169sub vm_commandline {
3170 my ($storecfg, $vmid) = @_;
3171
6b64503e 3172 my $conf = load_config($vmid);
1e3baf05
DM
3173
3174 my $defaults = load_defaults();
3175
6b64503e 3176 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 3177
6b64503e 3178 return join(' ', @$cmd);
1e3baf05
DM
3179}
3180
3181sub vm_reset {
3182 my ($vmid, $skiplock) = @_;
3183
6b64503e 3184 lock_config($vmid, sub {
1e3baf05 3185
6b64503e 3186 my $conf = load_config($vmid);
1e3baf05 3187
6b64503e 3188 check_lock($conf) if !$skiplock;
1e3baf05 3189
816e2c4a 3190 vm_mon_cmd($vmid, "system_reset");
ff1a2432
DM
3191 });
3192}
3193
3194sub get_vm_volumes {
3195 my ($conf) = @_;
1e3baf05 3196
ff1a2432 3197 my $vollist = [];
d5769dc2
DM
3198 foreach_volid($conf, sub {
3199 my ($volid, $is_cdrom) = @_;
ff1a2432 3200
d5769dc2 3201 return if $volid =~ m|^/|;
ff1a2432 3202
d5769dc2
DM
3203 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
3204 return if !$sid;
ff1a2432
DM
3205
3206 push @$vollist, $volid;
1e3baf05 3207 });
ff1a2432
DM
3208
3209 return $vollist;
3210}
3211
3212sub vm_stop_cleanup {
254575e9 3213 my ($storecfg, $vmid, $conf, $keepActive) = @_;
ff1a2432 3214
745fed70
DM
3215 eval {
3216 fairsched_rmnod($vmid); # try to destroy group
ff1a2432 3217
254575e9
DM
3218 if (!$keepActive) {
3219 my $vollist = get_vm_volumes($conf);
3220 PVE::Storage::deactivate_volumes($storecfg, $vollist);
3221 }
961bfcb2 3222
ab6a046f 3223 foreach my $ext (qw(mon qmp pid vnc qga)) {
961bfcb2
DM
3224 unlink "/var/run/qemu-server/${vmid}.$ext";
3225 }
745fed70
DM
3226 };
3227 warn $@ if $@; # avoid errors - just warn
1e3baf05
DM
3228}
3229
e6c3b671 3230# Note: use $nockeck to skip tests if VM configuration file exists.
254575e9
DM
3231# We need that when migration VMs to other nodes (files already moved)
3232# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
1e3baf05 3233sub vm_stop {
af30308f 3234 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
9269013a 3235
9269013a 3236 $force = 1 if !defined($force) && !$shutdown;
1e3baf05 3237
af30308f
DM
3238 if ($migratedfrom){
3239 my $pid = check_running($vmid, $nocheck, $migratedfrom);
3240 kill 15, $pid if $pid;
3241 my $conf = load_config($vmid, $migratedfrom);
3242 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive);
3243 return;
3244 }
3245
e6c3b671 3246 lock_config($vmid, sub {
1e3baf05 3247
e6c3b671 3248 my $pid = check_running($vmid, $nocheck);
ff1a2432 3249 return if !$pid;
1e3baf05 3250
ff1a2432 3251 my $conf;
e6c3b671 3252 if (!$nocheck) {
ff1a2432 3253 $conf = load_config($vmid);
e6c3b671 3254 check_lock($conf) if !$skiplock;
7f4a5b5a
DM
3255 if (!defined($timeout) && $shutdown && $conf->{startup}) {
3256 my $opts = parse_startup($conf->{startup});
3257 $timeout = $opts->{down} if $opts->{down};
3258 }
e6c3b671 3259 }
19672434 3260
7f4a5b5a
DM
3261 $timeout = 60 if !defined($timeout);
3262
9269013a
DM
3263 eval {
3264 if ($shutdown) {
988903ca 3265 $nocheck ? vm_mon_cmd_nocheck($vmid, "system_powerdown") : vm_mon_cmd($vmid, "system_powerdown");
bcb7c9cf 3266
9269013a 3267 } else {
988903ca 3268 $nocheck ? vm_mon_cmd_nocheck($vmid, "quit") : vm_mon_cmd($vmid, "quit");
afdb31d5 3269 }
9269013a 3270 };
1e3baf05
DM
3271 my $err = $@;
3272
3273 if (!$err) {
1e3baf05 3274 my $count = 0;
e6c3b671 3275 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
3276 $count++;
3277 sleep 1;
3278 }
3279
3280 if ($count >= $timeout) {
9269013a
DM
3281 if ($force) {
3282 warn "VM still running - terminating now with SIGTERM\n";
3283 kill 15, $pid;
3284 } else {
3285 die "VM quit/powerdown failed - got timeout\n";
3286 }
3287 } else {
254575e9 3288 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
9269013a 3289 return;
1e3baf05
DM
3290 }
3291 } else {
9269013a
DM
3292 if ($force) {
3293 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3294 kill 15, $pid;
3295 } else {
afdb31d5 3296 die "VM quit/powerdown failed\n";
9269013a 3297 }
1e3baf05
DM
3298 }
3299
3300 # wait again
ff1a2432 3301 $timeout = 10;
1e3baf05
DM
3302
3303 my $count = 0;
e6c3b671 3304 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
3305 $count++;
3306 sleep 1;
3307 }
3308
3309 if ($count >= $timeout) {
ff1a2432 3310 warn "VM still running - terminating now with SIGKILL\n";
1e3baf05 3311 kill 9, $pid;
ff1a2432 3312 sleep 1;
1e3baf05
DM
3313 }
3314
254575e9 3315 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
ff1a2432 3316 });
1e3baf05
DM
3317}
3318
3319sub vm_suspend {
3320 my ($vmid, $skiplock) = @_;
3321
6b64503e 3322 lock_config($vmid, sub {
1e3baf05 3323
6b64503e 3324 my $conf = load_config($vmid);
1e3baf05 3325
051347aa 3326 check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
bcb7c9cf 3327
f77f91f3 3328 vm_mon_cmd($vmid, "stop");
1e3baf05
DM
3329 });
3330}
3331
3332sub vm_resume {
3333 my ($vmid, $skiplock) = @_;
3334
6b64503e 3335 lock_config($vmid, sub {
1e3baf05 3336
6b64503e 3337 my $conf = load_config($vmid);
1e3baf05 3338
051347aa 3339 check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
1e3baf05 3340
12060fe8 3341 vm_mon_cmd($vmid, "cont");
1e3baf05
DM
3342 });
3343}
3344
5fdbe4f0
DM
3345sub vm_sendkey {
3346 my ($vmid, $skiplock, $key) = @_;
1e3baf05 3347
6b64503e 3348 lock_config($vmid, sub {
1e3baf05 3349
6b64503e 3350 my $conf = load_config($vmid);
f5eb281a 3351
7b7c6d1b
DM
3352 # there is no qmp command, so we use the human monitor command
3353 vm_human_monitor_command($vmid, "sendkey $key");
1e3baf05
DM
3354 });
3355}
3356
3357sub vm_destroy {
3358 my ($storecfg, $vmid, $skiplock) = @_;
3359
6b64503e 3360 lock_config($vmid, sub {
1e3baf05 3361
6b64503e 3362 my $conf = load_config($vmid);
1e3baf05 3363
6b64503e 3364 check_lock($conf) if !$skiplock;
1e3baf05 3365
ff1a2432
DM
3366 if (!check_running($vmid)) {
3367 fairsched_rmnod($vmid); # try to destroy group
3368 destroy_vm($storecfg, $vmid);
3369 } else {
3370 die "VM $vmid is running - destroy failed\n";
1e3baf05
DM
3371 }
3372 });
3373}
3374
1e3baf05
DM
3375# pci helpers
3376
3377sub file_write {
3378 my ($filename, $buf) = @_;
3379
6b64503e 3380 my $fh = IO::File->new($filename, "w");
1e3baf05
DM
3381 return undef if !$fh;
3382
3383 my $res = print $fh $buf;
3384
3385 $fh->close();
3386
3387 return $res;
3388}
3389
3390sub pci_device_info {
3391 my ($name) = @_;
3392
3393 my $res;
3394
3395 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3396 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3397
3398 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
3399 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3400
3401 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
3402 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3403
3404 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
3405 return undef if !defined($product) || $product !~ s/^0x//;
3406
3407 $res = {
3408 name => $name,
3409 vendor => $vendor,
3410 product => $product,
3411 domain => $domain,
3412 bus => $bus,
3413 slot => $slot,
3414 func => $func,
3415 irq => $irq,
3416 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
3417 };
3418
3419 return $res;
3420}
3421
3422sub pci_dev_reset {
3423 my ($dev) = @_;
3424
3425 my $name = $dev->{name};
3426
3427 my $fn = "$pcisysfs/devices/$name/reset";
3428
6b64503e 3429 return file_write($fn, "1");
1e3baf05
DM
3430}
3431
3432sub pci_dev_bind_to_stub {
3433 my ($dev) = @_;
3434
3435 my $name = $dev->{name};
3436
3437 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3438 return 1 if -d $testdir;
3439
3440 my $data = "$dev->{vendor} $dev->{product}";
6b64503e 3441 return undef if !file_write("$pcisysfs/drivers/pci-stub/new_id", $data);
1e3baf05
DM
3442
3443 my $fn = "$pcisysfs/devices/$name/driver/unbind";
6b64503e 3444 if (!file_write($fn, $name)) {
1e3baf05
DM
3445 return undef if -f $fn;
3446 }
3447
3448 $fn = "$pcisysfs/drivers/pci-stub/bind";
3449 if (! -d $testdir) {
6b64503e 3450 return undef if !file_write($fn, $name);
1e3baf05
DM
3451 }
3452
3453 return -d $testdir;
3454}
3455
afdb31d5 3456sub print_pci_addr {
5bdcf937 3457 my ($id, $bridges) = @_;
6b64503e 3458
72a063e4 3459 my $res = '';
6b64503e 3460 my $devices = {
24f0d39a 3461 piix3 => { bus => 0, addr => 1 },
e5f7f8ed 3462 #addr2 : first videocard
13b5a753 3463 balloon0 => { bus => 0, addr => 3 },
0a40e8ea 3464 watchdog => { bus => 0, addr => 4 },
cdd20088
AD
3465 scsihw0 => { bus => 0, addr => 5 },
3466 scsihw1 => { bus => 0, addr => 6 },
26ee04b6 3467 ahci0 => { bus => 0, addr => 7 },
ab6a046f 3468 qga0 => { bus => 0, addr => 8 },
1011b570 3469 spice => { bus => 0, addr => 9 },
6b64503e
DM
3470 virtio0 => { bus => 0, addr => 10 },
3471 virtio1 => { bus => 0, addr => 11 },
3472 virtio2 => { bus => 0, addr => 12 },
3473 virtio3 => { bus => 0, addr => 13 },
3474 virtio4 => { bus => 0, addr => 14 },
3475 virtio5 => { bus => 0, addr => 15 },
b78ebef7
DA
3476 hostpci0 => { bus => 0, addr => 16 },
3477 hostpci1 => { bus => 0, addr => 17 },
f290f8d9
DA
3478 net0 => { bus => 0, addr => 18 },
3479 net1 => { bus => 0, addr => 19 },
3480 net2 => { bus => 0, addr => 20 },
3481 net3 => { bus => 0, addr => 21 },
3482 net4 => { bus => 0, addr => 22 },
3483 net5 => { bus => 0, addr => 23 },
e5f7f8ed 3484 #addr29 : usb-host (pve-usb.cfg)
5bdcf937
AD
3485 'pci.1' => { bus => 0, addr => 30 },
3486 'pci.2' => { bus => 0, addr => 31 },
3487 'net6' => { bus => 1, addr => 1 },
3488 'net7' => { bus => 1, addr => 2 },
3489 'net8' => { bus => 1, addr => 3 },
3490 'net9' => { bus => 1, addr => 4 },
3491 'net10' => { bus => 1, addr => 5 },
3492 'net11' => { bus => 1, addr => 6 },
3493 'net12' => { bus => 1, addr => 7 },
3494 'net13' => { bus => 1, addr => 8 },
3495 'net14' => { bus => 1, addr => 9 },
3496 'net15' => { bus => 1, addr => 10 },
3497 'net16' => { bus => 1, addr => 11 },
3498 'net17' => { bus => 1, addr => 12 },
3499 'net18' => { bus => 1, addr => 13 },
3500 'net19' => { bus => 1, addr => 14 },
3501 'net20' => { bus => 1, addr => 15 },
3502 'net21' => { bus => 1, addr => 16 },
3503 'net22' => { bus => 1, addr => 17 },
3504 'net23' => { bus => 1, addr => 18 },
3505 'net24' => { bus => 1, addr => 19 },
3506 'net25' => { bus => 1, addr => 20 },
3507 'net26' => { bus => 1, addr => 21 },
3508 'net27' => { bus => 1, addr => 22 },
3509 'net28' => { bus => 1, addr => 23 },
3510 'net29' => { bus => 1, addr => 24 },
3511 'net30' => { bus => 1, addr => 25 },
3512 'net31' => { bus => 1, addr => 26 },
3513 'virtio6' => { bus => 2, addr => 1 },
3514 'virtio7' => { bus => 2, addr => 2 },
3515 'virtio8' => { bus => 2, addr => 3 },
3516 'virtio9' => { bus => 2, addr => 4 },
3517 'virtio10' => { bus => 2, addr => 5 },
3518 'virtio11' => { bus => 2, addr => 6 },
3519 'virtio12' => { bus => 2, addr => 7 },
3520 'virtio13' => { bus => 2, addr => 8 },
3521 'virtio14' => { bus => 2, addr => 9 },
3522 'virtio15' => { bus => 2, addr => 10 },
6b64503e
DM
3523 };
3524
3525 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
72a063e4 3526 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
5bdcf937
AD
3527 my $bus = $devices->{$id}->{bus};
3528 $res = ",bus=pci.$bus,addr=$addr";
98627641 3529 $bridges->{$bus} = 1 if $bridges;
72a063e4
DA
3530 }
3531 return $res;
3532
3533}
3534
3e16d5fc
DM
3535# vzdump restore implementaion
3536
ed221350 3537sub tar_archive_read_firstfile {
3e16d5fc 3538 my $archive = shift;
afdb31d5 3539
3e16d5fc
DM
3540 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
3541
3542 # try to detect archive type first
3543 my $pid = open (TMP, "tar tf '$archive'|") ||
3544 die "unable to open file '$archive'\n";
3545 my $firstfile = <TMP>;
3546 kill 15, $pid;
3547 close TMP;
3548
3549 die "ERROR: archive contaions no data\n" if !$firstfile;
3550 chomp $firstfile;
3551
3552 return $firstfile;
3553}
3554
ed221350
DM
3555sub tar_restore_cleanup {
3556 my ($storecfg, $statfile) = @_;
3e16d5fc
DM
3557
3558 print STDERR "starting cleanup\n";
3559
3560 if (my $fd = IO::File->new($statfile, "r")) {
3561 while (defined(my $line = <$fd>)) {
3562 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3563 my $volid = $2;
3564 eval {
3565 if ($volid =~ m|^/|) {
3566 unlink $volid || die 'unlink failed\n';
3567 } else {
ed221350 3568 PVE::Storage::vdisk_free($storecfg, $volid);
3e16d5fc 3569 }
afdb31d5 3570 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3e16d5fc
DM
3571 };
3572 print STDERR "unable to cleanup '$volid' - $@" if $@;
3573 } else {
3574 print STDERR "unable to parse line in statfile - $line";
afdb31d5 3575 }
3e16d5fc
DM
3576 }
3577 $fd->close();
3578 }
3579}
3580
3581sub restore_archive {
a0d1b1a2 3582 my ($archive, $vmid, $user, $opts) = @_;
3e16d5fc 3583
91bd6c90
DM
3584 my $format = $opts->{format};
3585 my $comp;
3586
3587 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3588 $format = 'tar' if !$format;
3589 $comp = 'gzip';
3590 } elsif ($archive =~ m/\.tar$/) {
3591 $format = 'tar' if !$format;
3592 } elsif ($archive =~ m/.tar.lzo$/) {
3593 $format = 'tar' if !$format;
3594 $comp = 'lzop';
3595 } elsif ($archive =~ m/\.vma$/) {
3596 $format = 'vma' if !$format;
3597 } elsif ($archive =~ m/\.vma\.gz$/) {
3598 $format = 'vma' if !$format;
3599 $comp = 'gzip';
3600 } elsif ($archive =~ m/\.vma\.lzo$/) {
3601 $format = 'vma' if !$format;
3602 $comp = 'lzop';
3603 } else {
3604 $format = 'vma' if !$format; # default
3605 }
3606
3607 # try to detect archive format
3608 if ($format eq 'tar') {
3609 return restore_tar_archive($archive, $vmid, $user, $opts);
3610 } else {
3611 return restore_vma_archive($archive, $vmid, $user, $opts, $comp);
3612 }
3613}
3614
3615sub restore_update_config_line {
3616 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3617
3618 return if $line =~ m/^\#qmdump\#/;
3619 return if $line =~ m/^\#vzdump\#/;
3620 return if $line =~ m/^lock:/;
3621 return if $line =~ m/^unused\d+:/;
3622 return if $line =~ m/^parent:/;
ca3e4fa4 3623 return if $line =~ m/^template:/; # restored VM is never a template
91bd6c90
DM
3624
3625 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3626 # try to convert old 1.X settings
3627 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3628 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
3629 my ($model, $macaddr) = split(/\=/, $devconfig);
3630 $macaddr = PVE::Tools::random_ether_addr() if !$macaddr || $unique;
3631 my $net = {
3632 model => $model,
3633 bridge => "vmbr$ind",
3634 macaddr => $macaddr,
3635 };
3636 my $netstr = print_net($net);
3637
3638 print $outfd "net$cookie->{netcount}: $netstr\n";
3639 $cookie->{netcount}++;
3640 }
3641 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3642 my ($id, $netstr) = ($1, $2);
3643 my $net = parse_net($netstr);
3644 $net->{macaddr} = PVE::Tools::random_ether_addr() if $net->{macaddr};
3645 $netstr = print_net($net);
3646 print $outfd "$id: $netstr\n";
3647 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3648 my $virtdev = $1;
907ea891 3649 my $value = $3;
91bd6c90
DM
3650 if ($line =~ m/backup=no/) {
3651 print $outfd "#$line";
3652 } elsif ($virtdev && $map->{$virtdev}) {
ed221350 3653 my $di = parse_drive($virtdev, $value);
8fd57431 3654 delete $di->{format}; # format can change on restore
91bd6c90 3655 $di->{file} = $map->{$virtdev};
ed221350 3656 $value = print_drive($vmid, $di);
91bd6c90
DM
3657 print $outfd "$virtdev: $value\n";
3658 } else {
3659 print $outfd $line;
3660 }
3661 } else {
3662 print $outfd $line;
3663 }
3664}
3665
3666sub scan_volids {
3667 my ($cfg, $vmid) = @_;
3668
3669 my $info = PVE::Storage::vdisk_list($cfg, undef, $vmid);
3670
3671 my $volid_hash = {};
3672 foreach my $storeid (keys %$info) {
3673 foreach my $item (@{$info->{$storeid}}) {
3674 next if !($item->{volid} && $item->{size});
5996a936 3675 $item->{path} = PVE::Storage::path($cfg, $item->{volid});
91bd6c90
DM
3676 $volid_hash->{$item->{volid}} = $item;
3677 }
3678 }
3679
3680 return $volid_hash;
3681}
3682
a8e2f942
DM
3683sub get_used_paths {
3684 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3685
3686 my $used_path = {};
3687
3688 my $scan_config = sub {
3689 my ($cref, $snapname) = @_;
3690
3691 foreach my $key (keys %$cref) {
3692 my $value = $cref->{$key};
3693 if (valid_drivename($key)) {
3694 next if $skip_drive && $key eq $skip_drive;
3695 my $drive = parse_drive($key, $value);
3696 next if !$drive || !$drive->{file} || drive_is_cdrom($drive);
3697 if ($drive->{file} =~ m!^/!) {
3698 $used_path->{$drive->{file}}++; # = 1;
3699 } else {
3700 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
3701 next if !$storeid;
3702 my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1);
3703 next if !$scfg;
3704 my $path = PVE::Storage::path($storecfg, $drive->{file}, $snapname);
3705 $used_path->{$path}++; # = 1;
3706 }
3707 }
3708 }
3709 };
3710
3711 &$scan_config($conf);
3712
3713 undef $skip_drive;
3714
3715 if ($scan_snapshots) {
3716 foreach my $snapname (keys %{$conf->{snapshots}}) {
3717 &$scan_config($conf->{snapshots}->{$snapname}, $snapname);
3718 }
3719 }
3720
3721 return $used_path;
3722}
3723
91bd6c90
DM
3724sub update_disksize {
3725 my ($vmid, $conf, $volid_hash) = @_;
be190583 3726
91bd6c90
DM
3727 my $changes;
3728
3729 my $used = {};
3730
5996a936
DM
3731 # Note: it is allowed to define multiple storages with same path (alias), so
3732 # we need to check both 'volid' and real 'path' (two different volid can point
3733 # to the same path).
3734
3735 my $usedpath = {};
be190583 3736
91bd6c90
DM
3737 # update size info
3738 foreach my $opt (keys %$conf) {
ed221350
DM
3739 if (valid_drivename($opt)) {
3740 my $drive = parse_drive($opt, $conf->{$opt});
91bd6c90
DM
3741 my $volid = $drive->{file};
3742 next if !$volid;
3743
3744 $used->{$volid} = 1;
be190583 3745 if ($volid_hash->{$volid} &&
5996a936
DM
3746 (my $path = $volid_hash->{$volid}->{path})) {
3747 $usedpath->{$path} = 1;
3748 }
91bd6c90 3749
ed221350 3750 next if drive_is_cdrom($drive);
91bd6c90
DM
3751 next if !$volid_hash->{$volid};
3752
3753 $drive->{size} = $volid_hash->{$volid}->{size};
7a907ce6
DM
3754 my $new = print_drive($vmid, $drive);
3755 if ($new ne $conf->{$opt}) {
3756 $changes = 1;
3757 $conf->{$opt} = $new;
3758 }
91bd6c90
DM
3759 }
3760 }
3761
5996a936
DM
3762 # remove 'unusedX' entry if volume is used
3763 foreach my $opt (keys %$conf) {
3764 next if $opt !~ m/^unused\d+$/;
3765 my $volid = $conf->{$opt};
3766 my $path = $volid_hash->{$volid}->{path} if $volid_hash->{$volid};
be190583 3767 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5996a936
DM
3768 $changes = 1;
3769 delete $conf->{$opt};
3770 }
3771 }
3772
91bd6c90
DM
3773 foreach my $volid (sort keys %$volid_hash) {
3774 next if $volid =~ m/vm-$vmid-state-/;
3775 next if $used->{$volid};
5996a936
DM
3776 my $path = $volid_hash->{$volid}->{path};
3777 next if !$path; # just to be sure
3778 next if $usedpath->{$path};
91bd6c90 3779 $changes = 1;
ed221350 3780 add_unused_volume($conf, $volid);
05937a14 3781 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
91bd6c90
DM
3782 }
3783
3784 return $changes;
3785}
3786
3787sub rescan {
3788 my ($vmid, $nolock) = @_;
3789
3790 my $cfg = PVE::Cluster::cfs_read_file("storage.cfg");
3791
3792 my $volid_hash = scan_volids($cfg, $vmid);
3793
3794 my $updatefn = sub {
3795 my ($vmid) = @_;
3796
ed221350 3797 my $conf = load_config($vmid);
be190583 3798
ed221350 3799 check_lock($conf);
91bd6c90 3800
03da3f0d
DM
3801 my $vm_volids = {};
3802 foreach my $volid (keys %$volid_hash) {
3803 my $info = $volid_hash->{$volid};
3804 $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
3805 }
3806
3807 my $changes = update_disksize($vmid, $conf, $vm_volids);
91bd6c90 3808
ed221350 3809 update_config_nolock($vmid, $conf, 1) if $changes;
91bd6c90
DM
3810 };
3811
3812 if (defined($vmid)) {
3813 if ($nolock) {
3814 &$updatefn($vmid);
3815 } else {
ed221350 3816 lock_config($vmid, $updatefn, $vmid);
91bd6c90
DM
3817 }
3818 } else {
3819 my $vmlist = config_list();
3820 foreach my $vmid (keys %$vmlist) {
3821 if ($nolock) {
3822 &$updatefn($vmid);
3823 } else {
ed221350 3824 lock_config($vmid, $updatefn, $vmid);
be190583 3825 }
91bd6c90
DM
3826 }
3827 }
3828}
3829
3830sub restore_vma_archive {
3831 my ($archive, $vmid, $user, $opts, $comp) = @_;
3832
3833 my $input = $archive eq '-' ? "<&STDIN" : undef;
3834 my $readfrom = $archive;
3835
3836 my $uncomp = '';
3837 if ($comp) {
3838 $readfrom = '-';
3839 my $qarchive = PVE::Tools::shellquote($archive);
3840 if ($comp eq 'gzip') {
3841 $uncomp = "zcat $qarchive|";
3842 } elsif ($comp eq 'lzop') {
3843 $uncomp = "lzop -d -c $qarchive|";
3844 } else {
3845 die "unknown compression method '$comp'\n";
3846 }
be190583 3847
91bd6c90
DM
3848 }
3849
3850 my $tmpdir = "/var/tmp/vzdumptmp$$";
3851 rmtree $tmpdir;
3852
3853 # disable interrupts (always do cleanups)
3854 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
3855 warn "got interrupt - ignored\n";
3856 };
3857
3858 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3859 POSIX::mkfifo($mapfifo, 0600);
3860 my $fifofh;
3861
3862 my $openfifo = sub {
3863 open($fifofh, '>', $mapfifo) || die $!;
3864 };
3865
3866 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3867
3868 my $oldtimeout;
3869 my $timeout = 5;
3870
3871 my $devinfo = {};
3872
3873 my $rpcenv = PVE::RPCEnvironment::get();
3874
ed221350 3875 my $conffile = config_file($vmid);
91bd6c90
DM
3876 my $tmpfn = "$conffile.$$.tmp";
3877
ed221350
DM
3878 # Note: $oldconf is undef if VM does not exists
3879 my $oldconf = PVE::Cluster::cfs_read_file(cfs_config_path($vmid));
3880
91bd6c90
DM
3881 my $print_devmap = sub {
3882 my $virtdev_hash = {};
3883
3884 my $cfgfn = "$tmpdir/qemu-server.conf";
3885
3886 # we can read the config - that is already extracted
3887 my $fh = IO::File->new($cfgfn, "r") ||
3888 "unable to read qemu-server.conf - $!\n";
3889
3890 while (defined(my $line = <$fh>)) {
3891 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3892 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3893 die "archive does not contain data for drive '$virtdev'\n"
3894 if !$devinfo->{$devname};
3895 if (defined($opts->{storage})) {
3896 $storeid = $opts->{storage} || 'local';
3897 } elsif (!$storeid) {
3898 $storeid = 'local';
3899 }
3900 $format = 'raw' if !$format;
3901 $devinfo->{$devname}->{devname} = $devname;
3902 $devinfo->{$devname}->{virtdev} = $virtdev;
3903 $devinfo->{$devname}->{format} = $format;
3904 $devinfo->{$devname}->{storeid} = $storeid;
3905
be190583 3906 # check permission on storage
91bd6c90
DM
3907 my $pool = $opts->{pool}; # todo: do we need that?
3908 if ($user ne 'root@pam') {
3909 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3910 }
3911
3912 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3913 }
3914 }
3915
3916 foreach my $devname (keys %$devinfo) {
be190583
DM
3917 die "found no device mapping information for device '$devname'\n"
3918 if !$devinfo->{$devname}->{virtdev};
91bd6c90
DM
3919 }
3920
91bd6c90 3921 my $cfg = cfs_read_file('storage.cfg');
ed221350
DM
3922
3923 # create empty/temp config
be190583 3924 if ($oldconf) {
ed221350
DM
3925 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
3926 foreach_drive($oldconf, sub {
3927 my ($ds, $drive) = @_;
3928
3929 return if drive_is_cdrom($drive);
3930
3931 my $volid = $drive->{file};
3932
3933 return if !$volid || $volid =~ m|^/|;
3934
3935 my ($path, $owner) = PVE::Storage::path($cfg, $volid);
3936 return if !$path || !$owner || ($owner != $vmid);
3937
3938 # Note: only delete disk we want to restore
3939 # other volumes will become unused
3940 if ($virtdev_hash->{$ds}) {
3941 PVE::Storage::vdisk_free($cfg, $volid);
3942 }
3943 });
3944 }
3945
3946 my $map = {};
91bd6c90
DM
3947 foreach my $virtdev (sort keys %$virtdev_hash) {
3948 my $d = $virtdev_hash->{$virtdev};
3949 my $alloc_size = int(($d->{size} + 1024 - 1)/1024);
3950 my $scfg = PVE::Storage::storage_config($cfg, $d->{storeid});
8fd57431
DM
3951
3952 # test if requested format is supported
3953 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($cfg, $d->{storeid});
3954 my $supported = grep { $_ eq $d->{format} } @$validFormats;
3955 $d->{format} = $defFormat if !$supported;
3956
91bd6c90
DM
3957 my $volid = PVE::Storage::vdisk_alloc($cfg, $d->{storeid}, $vmid,
3958 $d->{format}, undef, $alloc_size);
3959 print STDERR "new volume ID is '$volid'\n";
3960 $d->{volid} = $volid;
3961 my $path = PVE::Storage::path($cfg, $volid);
3962
3963 my $write_zeros = 1;
3964 # fixme: what other storages types initialize volumes with zero?
be190583 3965 if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs' ||
013d5275 3966 $scfg->{type} eq 'sheepdog' || $scfg->{type} eq 'rbd') {
91bd6c90
DM
3967 $write_zeros = 0;
3968 }
3969
3970 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
3971
3972 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
3973 $map->{$virtdev} = $volid;
3974 }
3975
3976 $fh->seek(0, 0) || die "seek failed - $!\n";
3977
3978 my $outfd = new IO::File ($tmpfn, "w") ||
3979 die "unable to write config for VM $vmid\n";
3980
3981 my $cookie = { netcount => 0 };
3982 while (defined(my $line = <$fh>)) {
be190583 3983 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
91bd6c90
DM
3984 }
3985
3986 $fh->close();
3987 $outfd->close();
3988 };
3989
3990 eval {
3991 # enable interrupts
3992 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
3993 die "interrupted by signal\n";
3994 };
3995 local $SIG{ALRM} = sub { die "got timeout\n"; };
3996
3997 $oldtimeout = alarm($timeout);
3998
3999 my $parser = sub {
4000 my $line = shift;
4001
4002 print "$line\n";
4003
4004 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4005 my ($dev_id, $size, $devname) = ($1, $2, $3);
4006 $devinfo->{$devname} = { size => $size, dev_id => $dev_id };
4007 } elsif ($line =~ m/^CTIME: /) {
4008 &$print_devmap();
4009 print $fifofh "done\n";
4010 my $tmp = $oldtimeout || 0;
4011 $oldtimeout = undef;
4012 alarm($tmp);
4013 close($fifofh);
4014 }
4015 };
be190583 4016
91bd6c90
DM
4017 print "restore vma archive: $cmd\n";
4018 run_command($cmd, input => $input, outfunc => $parser, afterfork => $openfifo);
4019 };
4020 my $err = $@;
4021
4022 alarm($oldtimeout) if $oldtimeout;
4023
4024 unlink $mapfifo;
4025
4026 if ($err) {
4027 rmtree $tmpdir;
4028 unlink $tmpfn;
4029
4030 my $cfg = cfs_read_file('storage.cfg');
4031 foreach my $devname (keys %$devinfo) {
4032 my $volid = $devinfo->{$devname}->{volid};
4033 next if !$volid;
4034 eval {
4035 if ($volid =~ m|^/|) {
4036 unlink $volid || die 'unlink failed\n';
4037 } else {
4038 PVE::Storage::vdisk_free($cfg, $volid);
4039 }
4040 print STDERR "temporary volume '$volid' sucessfuly removed\n";
4041 };
4042 print STDERR "unable to cleanup '$volid' - $@" if $@;
4043 }
4044 die $err;
4045 }
4046
4047 rmtree $tmpdir;
ed221350
DM
4048
4049 rename($tmpfn, $conffile) ||
91bd6c90
DM
4050 die "unable to commit configuration file '$conffile'\n";
4051
ed221350
DM
4052 PVE::Cluster::cfs_update(); # make sure we read new file
4053
91bd6c90
DM
4054 eval { rescan($vmid, 1); };
4055 warn $@ if $@;
4056}
4057
4058sub restore_tar_archive {
4059 my ($archive, $vmid, $user, $opts) = @_;
4060
9c502e26 4061 if ($archive ne '-') {
ed221350 4062 my $firstfile = tar_archive_read_firstfile($archive);
9c502e26
DM
4063 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4064 if $firstfile ne 'qemu-server.conf';
4065 }
3e16d5fc 4066
ed221350 4067 my $storecfg = cfs_read_file('storage.cfg');
ebb55558 4068
ed221350 4069 # destroy existing data - keep empty config
ebb55558
DM
4070 my $vmcfgfn = PVE::QemuServer::config_file($vmid);
4071 destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
ed221350 4072
3e16d5fc
DM
4073 my $tocmd = "/usr/lib/qemu-server/qmextract";
4074
2415a446 4075 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
a0d1b1a2 4076 $tocmd .= " --pool " . PVE::Tools::shellquote($opts->{pool}) if $opts->{pool};
3e16d5fc
DM
4077 $tocmd .= ' --prealloc' if $opts->{prealloc};
4078 $tocmd .= ' --info' if $opts->{info};
4079
a0d1b1a2 4080 # tar option "xf" does not autodetect compression when read from STDIN,
9c502e26 4081 # so we pipe to zcat
2415a446
DM
4082 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
4083 PVE::Tools::shellquote("--to-command=$tocmd");
3e16d5fc
DM
4084
4085 my $tmpdir = "/var/tmp/vzdumptmp$$";
4086 mkpath $tmpdir;
4087
4088 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
4089 local $ENV{VZDUMP_VMID} = $vmid;
a0d1b1a2 4090 local $ENV{VZDUMP_USER} = $user;
3e16d5fc 4091
ed221350 4092 my $conffile = config_file($vmid);
3e16d5fc
DM
4093 my $tmpfn = "$conffile.$$.tmp";
4094
4095 # disable interrupts (always do cleanups)
4096 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
4097 print STDERR "got interrupt - ignored\n";
4098 };
4099
afdb31d5 4100 eval {
3e16d5fc
DM
4101 # enable interrupts
4102 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
4103 die "interrupted by signal\n";
4104 };
4105
9c502e26
DM
4106 if ($archive eq '-') {
4107 print "extracting archive from STDIN\n";
4108 run_command($cmd, input => "<&STDIN");
4109 } else {
4110 print "extracting archive '$archive'\n";
4111 run_command($cmd);
4112 }
3e16d5fc
DM
4113
4114 return if $opts->{info};
4115
4116 # read new mapping
4117 my $map = {};
4118 my $statfile = "$tmpdir/qmrestore.stat";
4119 if (my $fd = IO::File->new($statfile, "r")) {
4120 while (defined (my $line = <$fd>)) {
4121 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4122 $map->{$1} = $2 if $1;
4123 } else {
4124 print STDERR "unable to parse line in statfile - $line\n";
4125 }
4126 }
4127 $fd->close();
4128 }
4129
4130 my $confsrc = "$tmpdir/qemu-server.conf";
4131
4132 my $srcfd = new IO::File($confsrc, "r") ||
4133 die "unable to open file '$confsrc'\n";
4134
4135 my $outfd = new IO::File ($tmpfn, "w") ||
4136 die "unable to write config for VM $vmid\n";
4137
91bd6c90 4138 my $cookie = { netcount => 0 };
3e16d5fc 4139 while (defined (my $line = <$srcfd>)) {
be190583 4140 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
3e16d5fc
DM
4141 }
4142
4143 $srcfd->close();
4144 $outfd->close();
4145 };
4146 my $err = $@;
4147
afdb31d5 4148 if ($err) {
3e16d5fc
DM
4149
4150 unlink $tmpfn;
4151
ed221350 4152 tar_restore_cleanup($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info};
afdb31d5 4153
3e16d5fc 4154 die $err;
afdb31d5 4155 }
3e16d5fc
DM
4156
4157 rmtree $tmpdir;
4158
4159 rename $tmpfn, $conffile ||
4160 die "unable to commit configuration file '$conffile'\n";
91bd6c90 4161
ed221350
DM
4162 PVE::Cluster::cfs_update(); # make sure we read new file
4163
91bd6c90
DM
4164 eval { rescan($vmid, 1); };
4165 warn $@ if $@;
3e16d5fc
DM
4166};
4167
0d18dcfc
DM
4168
4169# Internal snapshots
4170
4171# NOTE: Snapshot create/delete involves several non-atomic
4172# action, and can take a long time.
4173# So we try to avoid locking the file and use 'lock' variable
4174# inside the config file instead.
4175
ef59d1ca
DM
4176my $snapshot_copy_config = sub {
4177 my ($source, $dest) = @_;
4178
4179 foreach my $k (keys %$source) {
4180 next if $k eq 'snapshots';
982c7f12
DM
4181 next if $k eq 'snapstate';
4182 next if $k eq 'snaptime';
18bfb361 4183 next if $k eq 'vmstate';
ef59d1ca
DM
4184 next if $k eq 'lock';
4185 next if $k eq 'digest';
db7c26e5 4186 next if $k eq 'description';
ef59d1ca 4187 next if $k =~ m/^unused\d+$/;
be190583 4188
ef59d1ca
DM
4189 $dest->{$k} = $source->{$k};
4190 }
4191};
4192
4193my $snapshot_apply_config = sub {
4194 my ($conf, $snap) = @_;
4195
4196 # copy snapshot list
4197 my $newconf = {
4198 snapshots => $conf->{snapshots},
4199 };
4200
db7c26e5 4201 # keep description and list of unused disks
ef59d1ca 4202 foreach my $k (keys %$conf) {
db7c26e5 4203 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
ef59d1ca
DM
4204 $newconf->{$k} = $conf->{$k};
4205 }
4206
4207 &$snapshot_copy_config($snap, $newconf);
4208
4209 return $newconf;
4210};
4211
18bfb361
DM
4212sub foreach_writable_storage {
4213 my ($conf, $func) = @_;
4214
4215 my $sidhash = {};
4216
4217 foreach my $ds (keys %$conf) {
4218 next if !valid_drivename($ds);
4219
4220 my $drive = parse_drive($ds, $conf->{$ds});
4221 next if !$drive;
4222 next if drive_is_cdrom($drive);
4223
4224 my $volid = $drive->{file};
4225
4226 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
be190583 4227 $sidhash->{$sid} = $sid if $sid;
18bfb361
DM
4228 }
4229
4230 foreach my $sid (sort keys %$sidhash) {
4231 &$func($sid);
4232 }
4233}
4234
4235my $alloc_vmstate_volid = sub {
4236 my ($storecfg, $vmid, $conf, $snapname) = @_;
be190583 4237
18bfb361
DM
4238 # Note: we try to be smart when selecting a $target storage
4239
4240 my $target;
4241
4242 # search shared storage first
4243 foreach_writable_storage($conf, sub {
4244 my ($sid) = @_;
4245 my $scfg = PVE::Storage::storage_config($storecfg, $sid);
4246 return if !$scfg->{shared};
4247
4248 $target = $sid if !$target || $scfg->{path}; # prefer file based storage
4249 });
4250
4251 if (!$target) {
4252 # now search local storage
4253 foreach_writable_storage($conf, sub {
4254 my ($sid) = @_;
4255 my $scfg = PVE::Storage::storage_config($storecfg, $sid);
4256 return if $scfg->{shared};
4257
4258 $target = $sid if !$target || $scfg->{path}; # prefer file based storage;
4259 });
4260 }
4261
4262 $target = 'local' if !$target;
4263
fe6249f4
DM
4264 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4265 # we abort live save after $conf->{memory}, so we need at max twice that space
4266 my $size = $conf->{memory}*2 + $driver_state_size;
18bfb361
DM
4267
4268 my $name = "vm-$vmid-state-$snapname";
4269 my $scfg = PVE::Storage::storage_config($storecfg, $target);
4270 $name .= ".raw" if $scfg->{path}; # add filename extension for file base storage
4271 my $volid = PVE::Storage::vdisk_alloc($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4272
4273 return $volid;
4274};
4275
0d18dcfc 4276my $snapshot_prepare = sub {
18bfb361 4277 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
22c377f0
DM
4278
4279 my $snap;
0d18dcfc
DM
4280
4281 my $updatefn = sub {
4282
4283 my $conf = load_config($vmid);
4284
be190583 4285 die "you can't take a snapshot if it's a template\n"
5295b23d
DM
4286 if is_template($conf);
4287
0d18dcfc
DM
4288 check_lock($conf);
4289
22c377f0
DM
4290 $conf->{lock} = 'snapshot';
4291
be190583
DM
4292 die "snapshot name '$snapname' already used\n"
4293 if defined($conf->{snapshots}->{$snapname});
0d18dcfc 4294
ee2f90b1 4295 my $storecfg = PVE::Storage::config();
7ea975ef 4296 die "snapshot feature is not available" if !has_feature('snapshot', $conf, $storecfg);
18bfb361 4297
782f4f75 4298 $snap = $conf->{snapshots}->{$snapname} = {};
0d18dcfc 4299
18bfb361
DM
4300 if ($save_vmstate && check_running($vmid)) {
4301 $snap->{vmstate} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4302 }
4303
ef59d1ca 4304 &$snapshot_copy_config($conf, $snap);
0d18dcfc 4305
782f4f75
DM
4306 $snap->{snapstate} = "prepare";
4307 $snap->{snaptime} = time();
4308 $snap->{description} = $comment if $comment;
4309
4b15803d
DM
4310 # always overwrite machine if we save vmstate. This makes sure we
4311 # can restore it later using correct machine type
4312 $snap->{machine} = get_current_qemu_machine($vmid) if $snap->{vmstate};
4313
0d18dcfc
DM
4314 update_config_nolock($vmid, $conf, 1);
4315 };
4316
4317 lock_config($vmid, $updatefn);
22c377f0
DM
4318
4319 return $snap;
0d18dcfc
DM
4320};
4321
4322my $snapshot_commit = sub {
4323 my ($vmid, $snapname) = @_;
4324
4325 my $updatefn = sub {
4326
4327 my $conf = load_config($vmid);
4328
be190583
DM
4329 die "missing snapshot lock\n"
4330 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
0d18dcfc
DM
4331
4332 my $snap = $conf->{snapshots}->{$snapname};
4333
be190583
DM
4334 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4335
4336 die "wrong snapshot state\n"
4337 if !($snap->{snapstate} && $snap->{snapstate} eq "prepare");
0d18dcfc 4338
0d18dcfc 4339 delete $snap->{snapstate};
ee2f90b1 4340 delete $conf->{lock};
0d18dcfc 4341
ef59d1ca 4342 my $newconf = &$snapshot_apply_config($conf, $snap);
0d18dcfc 4343
05e5ad3f
DM
4344 $newconf->{parent} = $snapname;
4345
0d18dcfc
DM
4346 update_config_nolock($vmid, $newconf, 1);
4347 };
4348
4349 lock_config($vmid, $updatefn);
4350};
4351
22c377f0
DM
4352sub snapshot_rollback {
4353 my ($vmid, $snapname) = @_;
4354
4355 my $snap;
4356
4357 my $prepare = 1;
4358
a3222b91 4359 my $storecfg = PVE::Storage::config();
be190583 4360
22c377f0
DM
4361 my $updatefn = sub {
4362
4363 my $conf = load_config($vmid);
4364
8b43bc11 4365 die "you can't rollback if vm is a template\n" if is_template($conf);
90b0c6b3 4366
ab33a7c2
DM
4367 $snap = $conf->{snapshots}->{$snapname};
4368
be190583 4369 die "snapshot '$snapname' does not exist\n" if !defined($snap);
ab33a7c2 4370
be190583 4371 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
ab33a7c2
DM
4372 if $snap->{snapstate};
4373
a3222b91
DM
4374 if ($prepare) {
4375 check_lock($conf);
4376 vm_stop($storecfg, $vmid, undef, undef, 5, undef, undef);
4377 }
22c377f0
DM
4378
4379 die "unable to rollback vm $vmid: vm is running\n"
4380 if check_running($vmid);
4381
4382 if ($prepare) {
4383 $conf->{lock} = 'rollback';
4384 } else {
4385 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4386 delete $conf->{lock};
4387 }
4388
4b15803d
DM
4389 my $forcemachine;
4390
22c377f0 4391 if (!$prepare) {
4b15803d
DM
4392 my $has_machine_config = defined($conf->{machine});
4393
22c377f0 4394 # copy snapshot config to current config
ef59d1ca
DM
4395 $conf = &$snapshot_apply_config($conf, $snap);
4396 $conf->{parent} = $snapname;
4b15803d 4397
d8b916fd
DM
4398 # Note: old code did not store 'machine', so we try to be smart
4399 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4400 $forcemachine = $conf->{machine} || 'pc-i440fx-1.4';
be190583 4401 # we remove the 'machine' configuration if not explicitly specified
4b15803d
DM
4402 # in the original config.
4403 delete $conf->{machine} if $snap->{vmstate} && !$has_machine_config;
22c377f0
DM
4404 }
4405
4406 update_config_nolock($vmid, $conf, 1);
a3222b91
DM
4407
4408 if (!$prepare && $snap->{vmstate}) {
4409 my $statefile = PVE::Storage::path($storecfg, $snap->{vmstate});
4b15803d 4410 vm_start($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
a3222b91 4411 }
22c377f0
DM
4412 };
4413
4414 lock_config($vmid, $updatefn);
be190583 4415
22c377f0
DM
4416 foreach_drive($snap, sub {
4417 my ($ds, $drive) = @_;
4418
4419 return if drive_is_cdrom($drive);
4420
4421 my $volid = $drive->{file};
4422 my $device = "drive-$ds";
4423
79e57b29 4424 PVE::Storage::volume_snapshot_rollback($storecfg, $volid, $snapname);
22c377f0
DM
4425 });
4426
4427 $prepare = 0;
4428 lock_config($vmid, $updatefn);
4429}
4430
9dcf4909
DM
4431my $savevm_wait = sub {
4432 my ($vmid) = @_;
4433
4434 for(;;) {
ed221350 4435 my $stat = vm_mon_cmd_nocheck($vmid, "query-savevm");
9dcf4909
DM
4436 if (!$stat->{status}) {
4437 die "savevm not active\n";
4438 } elsif ($stat->{status} eq 'active') {
4439 sleep(1);
4440 next;
4441 } elsif ($stat->{status} eq 'completed') {
4442 last;
4443 } else {
4444 die "query-savevm returned status '$stat->{status}'\n";
4445 }
4446 }
4447};
4448
0d18dcfc 4449sub snapshot_create {
18bfb361 4450 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
0d18dcfc 4451
18bfb361 4452 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
0d18dcfc 4453
18bfb361 4454 $freezefs = $save_vmstate = 0 if !$snap->{vmstate}; # vm is not running
030dd626 4455
3ee28e38
DM
4456 my $drivehash = {};
4457
18bfb361
DM
4458 my $running = check_running($vmid);
4459
0d18dcfc
DM
4460 eval {
4461 # create internal snapshots of all drives
22c377f0
DM
4462
4463 my $storecfg = PVE::Storage::config();
a3222b91
DM
4464
4465 if ($running) {
4466 if ($snap->{vmstate}) {
be190583 4467 my $path = PVE::Storage::path($storecfg, $snap->{vmstate});
9dcf4909
DM
4468 vm_mon_cmd($vmid, "savevm-start", statefile => $path);
4469 &$savevm_wait($vmid);
a3222b91 4470 } else {
9dcf4909 4471 vm_mon_cmd($vmid, "savevm-start");
a3222b91
DM
4472 }
4473 };
4474
4475 qga_freezefs($vmid) if $running && $freezefs;
be190583 4476
22c377f0
DM
4477 foreach_drive($snap, sub {
4478 my ($ds, $drive) = @_;
4479
4480 return if drive_is_cdrom($drive);
0d18dcfc 4481
22c377f0
DM
4482 my $volid = $drive->{file};
4483 my $device = "drive-$ds";
4484
4485 qemu_volume_snapshot($vmid, $device, $storecfg, $volid, $snapname);
3ee28e38 4486 $drivehash->{$ds} = 1;
22c377f0 4487 });
0d18dcfc 4488 };
22c377f0
DM
4489 my $err = $@;
4490
1a71fa73 4491 eval { qga_unfreezefs($vmid) if $running && $freezefs; };
22c377f0
DM
4492 warn $@ if $@;
4493
9dcf4909 4494 eval { vm_mon_cmd($vmid, "savevm-end") if $running; };
22c377f0
DM
4495 warn $@ if $@;
4496
4497 if ($err) {
0d18dcfc 4498 warn "snapshot create failed: starting cleanup\n";
3ee28e38 4499 eval { snapshot_delete($vmid, $snapname, 0, $drivehash); };
0d18dcfc
DM
4500 warn $@ if $@;
4501 die $err;
4502 }
4503
4504 &$snapshot_commit($vmid, $snapname);
4505}
4506
3ee28e38 4507# Note: $drivehash is only set when called from snapshot_create.
0d18dcfc 4508sub snapshot_delete {
3ee28e38 4509 my ($vmid, $snapname, $force, $drivehash) = @_;
0d18dcfc
DM
4510
4511 my $prepare = 1;
4512
22c377f0 4513 my $snap;
ee2f90b1 4514 my $unused = [];
0d18dcfc 4515
6cb1a8cf
DM
4516 my $unlink_parent = sub {
4517 my ($confref, $new_parent) = @_;
4518
4519 if ($confref->{parent} && $confref->{parent} eq $snapname) {
4520 if ($new_parent) {
4521 $confref->{parent} = $new_parent;
4522 } else {
4523 delete $confref->{parent};
4524 }
4525 }
4526 };
be190583 4527
0d18dcfc 4528 my $updatefn = sub {
2009f324 4529 my ($remove_drive) = @_;
0d18dcfc 4530
22c377f0 4531 my $conf = load_config($vmid);
0d18dcfc 4532
5295b23d
DM
4533 if (!$drivehash) {
4534 check_lock($conf);
be190583 4535 die "you can't delete a snapshot if vm is a template\n"
5295b23d
DM
4536 if is_template($conf);
4537 }
0d18dcfc 4538
22c377f0 4539 $snap = $conf->{snapshots}->{$snapname};
0d18dcfc 4540
be190583 4541 die "snapshot '$snapname' does not exist\n" if !defined($snap);
0d18dcfc
DM
4542
4543 # remove parent refs
6cb1a8cf 4544 &$unlink_parent($conf, $snap->{parent});
0d18dcfc
DM
4545 foreach my $sn (keys %{$conf->{snapshots}}) {
4546 next if $sn eq $snapname;
6cb1a8cf 4547 &$unlink_parent($conf->{snapshots}->{$sn}, $snap->{parent});
0d18dcfc
DM
4548 }
4549
2009f324 4550 if ($remove_drive) {
18bfb361
DM
4551 if ($remove_drive eq 'vmstate') {
4552 delete $snap->{$remove_drive};
4553 } else {
4554 my $drive = parse_drive($remove_drive, $snap->{$remove_drive});
4555 my $volid = $drive->{file};
4556 delete $snap->{$remove_drive};
4557 add_unused_volume($conf, $volid);
4558 }
2009f324
DM
4559 }
4560
0d18dcfc
DM
4561 if ($prepare) {
4562 $snap->{snapstate} = 'delete';
4563 } else {
4564 delete $conf->{snapshots}->{$snapname};
3ee28e38 4565 delete $conf->{lock} if $drivehash;
ee2f90b1
DM
4566 foreach my $volid (@$unused) {
4567 add_unused_volume($conf, $volid);
4568 }
0d18dcfc
DM
4569 }
4570
4571 update_config_nolock($vmid, $conf, 1);
4572 };
4573
4574 lock_config($vmid, $updatefn);
4575
18bfb361 4576 # now remove vmstate file
0d18dcfc 4577
22c377f0
DM
4578 my $storecfg = PVE::Storage::config();
4579
18bfb361
DM
4580 if ($snap->{vmstate}) {
4581 eval { PVE::Storage::vdisk_free($storecfg, $snap->{vmstate}); };
4582 if (my $err = $@) {
4583 die $err if !$force;
4584 warn $err;
4585 }
4586 # save changes (remove vmstate from snapshot)
4587 lock_config($vmid, $updatefn, 'vmstate') if !$force;
4588 };
4589
4590 # now remove all internal snapshots
4591 foreach_drive($snap, sub {
22c377f0
DM
4592 my ($ds, $drive) = @_;
4593
4594 return if drive_is_cdrom($drive);
3ee28e38 4595
22c377f0
DM
4596 my $volid = $drive->{file};
4597 my $device = "drive-$ds";
4598
2009f324
DM
4599 if (!$drivehash || $drivehash->{$ds}) {
4600 eval { qemu_volume_snapshot_delete($vmid, $device, $storecfg, $volid, $snapname); };
4601 if (my $err = $@) {
4602 die $err if !$force;
4603 warn $err;
4604 }
3ee28e38 4605 }
2009f324
DM
4606
4607 # save changes (remove drive fron snapshot)
4608 lock_config($vmid, $updatefn, $ds) if !$force;
ee2f90b1 4609 push @$unused, $volid;
22c377f0 4610 });
0d18dcfc
DM
4611
4612 # now cleanup config
4613 $prepare = 0;
4614 lock_config($vmid, $updatefn);
4615}
4616
9cd07842 4617sub has_feature {
7ea975ef
AD
4618 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4619
719893a9 4620 my $err;
7ea975ef
AD
4621 foreach_drive($conf, sub {
4622 my ($ds, $drive) = @_;
4623
4624 return if drive_is_cdrom($drive);
4625 my $volid = $drive->{file};
4626 $err = 1 if !PVE::Storage::volume_has_feature($storecfg, $feature, $volid, $snapname, $running);
4627 });
4628
719893a9 4629 return $err ? 0 : 1;
7ea975ef 4630}
04a69bb4
AD
4631
4632sub template_create {
4633 my ($vmid, $conf, $disk) = @_;
4634
04a69bb4 4635 my $storecfg = PVE::Storage::config();
04a69bb4 4636
9cd07842
DM
4637 foreach_drive($conf, sub {
4638 my ($ds, $drive) = @_;
4639
4640 return if drive_is_cdrom($drive);
4641 return if $disk && $ds ne $disk;
4642
4643 my $volid = $drive->{file};
bbd56097 4644 return if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
9cd07842 4645
04a69bb4
AD
4646 my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
4647 $drive->{file} = $voliddst;
152fe752
DM
4648 $conf->{$ds} = print_drive($vmid, $drive);
4649 update_config_nolock($vmid, $conf, 1);
04a69bb4 4650 });
04a69bb4
AD
4651}
4652
624361b3
AD
4653sub is_template {
4654 my ($conf) = @_;
4655
96d695c0 4656 return 1 if defined $conf->{template} && $conf->{template} == 1;
624361b3
AD
4657}
4658
5133de42
AD
4659sub qemu_img_convert {
4660 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4661
4662 my $storecfg = PVE::Storage::config();
4663 my ($src_storeid, $src_volname) = PVE::Storage::parse_volume_id($src_volid, 1);
4664 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
4665
4666 if ($src_storeid && $dst_storeid) {
4667 my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
4668 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
4669
4670 my $src_format = qemu_img_format($src_scfg, $src_volname);
4671 my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
4672
4673 my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
4674 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
4675
4676 my $cmd = [];
4677 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-C';
4678 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4679 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4680
4681 my $parser = sub {
4682 my $line = shift;
4683 if($line =~ m/\((\S+)\/100\%\)/){
4684 my $percent = $1;
4685 my $transferred = int($size * $percent / 100);
4686 my $remaining = $size - $transferred;
4687
4688 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4689 }
4690
4691 };
4692
4693 eval { run_command($cmd, timeout => undef, outfunc => $parser); };
4694 my $err = $@;
4695 die "copy failed: $err" if $err;
4696 }
4697}
4698
4699sub qemu_img_format {
4700 my ($scfg, $volname) = @_;
4701
ccb5c001 4702 if ($scfg->{path} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
5133de42 4703 return $1;
ccb5c001 4704 } elsif ($scfg->{type} eq 'iscsi') {
5133de42 4705 return "host_device";
be190583 4706 } else {
5133de42 4707 return "raw";
5133de42
AD
4708 }
4709}
4710
cfad42af
AD
4711sub qemu_drive_mirror {
4712 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4713
4714 my $count = 1;
4715 my $old_len = 0;
4716 my $frozen = undef;
4717
4718 my $storecfg = PVE::Storage::config();
4719 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
4720
4721 if ($dst_storeid) {
4722 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
4723
152fe752 4724 my $format;
cfad42af
AD
4725 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4726 $format = $1;
4727 }
4728
4729 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
4730
152fe752 4731 if ($format) {
be190583 4732 #fixme : sometime drive-mirror timeout, but works fine after.
152fe752 4733 # (I have see the problem with big volume > 200GB), so we need to eval
be190583 4734 eval { vm_mon_cmd($vmid, "drive-mirror", timeout => 10, device => "drive-$drive", mode => "existing",
152fe752
DM
4735 sync => "full", target => $dst_path, format => $format); };
4736 } else {
be190583 4737 eval { vm_mon_cmd($vmid, "drive-mirror", timeout => 10, device => "drive-$drive", mode => "existing",
152fe752 4738 sync => "full", target => $dst_path); };
cfad42af 4739 }
152fe752
DM
4740
4741 eval {
cfad42af 4742 while (1) {
152fe752 4743 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
cfad42af 4744 my $stat = @$stats[0];
f6ab3bdb
AD
4745 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4746 die "error job is not mirroring" if $stat->{type} ne "mirror";
4747
cfad42af
AD
4748 my $transferred = $stat->{offset};
4749 my $total = $stat->{len};
4750 my $remaining = $total - $transferred;
4751 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
cfad42af
AD
4752
4753 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4754
4755 last if ($stat->{len} == $stat->{offset});
4756 if ($old_len == $stat->{offset}) {
4757 if ($maxwait && $count > $maxwait) {
4758 # if writes to disk occurs the disk needs to be freezed
4759 # to be able to complete the migration
4760 vm_suspend($vmid,1);
4761 $count = 0;
4762 $frozen = 1;
152fe752 4763 } else {
cfad42af
AD
4764 $count++ unless $frozen;
4765 }
152fe752
DM
4766 } elsif ($frozen) {
4767 vm_resume($vmid,1);
4768 $count = 0;
cfad42af
AD
4769 }
4770 $old_len = $stat->{offset};
4771 sleep 1;
4772 }
be190583 4773
2fc6bc17 4774 if ($vmiddst == $vmid) {
be190583 4775 # switch the disk if source and destination are on the same guest
2fc6bc17
DM
4776 vm_mon_cmd($vmid, "block-job-complete", device => "drive-$drive");
4777 }
cfad42af 4778 };
4fca0153 4779 if (my $err = $@) {
152fe752 4780 eval { vm_mon_cmd($vmid, "block-job-cancel", device => "drive-$drive"); };
4fca0153 4781 die "mirroring error: $err";
cfad42af
AD
4782 }
4783
2fc6bc17
DM
4784 if ($vmiddst != $vmid) {
4785 # if we clone a disk for a new target vm, we don't switch the disk
152fe752 4786 vm_mon_cmd($vmid, "block-job-cancel", device => "drive-$drive");
cfad42af
AD
4787 }
4788 }
4789}
4790
152fe752 4791sub clone_disk {
be190583 4792 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
152fe752
DM
4793 $newvmid, $storage, $format, $full, $newvollist) = @_;
4794
4795 my $newvolid;
4796
4797 if (!$full) {
4798 print "create linked clone of drive $drivename ($drive->{file})\n";
4799 $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid);
4800 push @$newvollist, $newvolid;
4801 } else {
4802 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
4803 $storeid = $storage if $storage;
4804
1377d7b0
DM
4805 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4806 if (!$format) {
4807 $format = $drive->{format} || $defFormat;
152fe752
DM
4808 }
4809
1377d7b0
DM
4810 # test if requested format is supported - else use default
4811 my $supported = grep { $_ eq $format } @$validFormats;
4812 $format = $defFormat if !$supported;
4813
152fe752
DM
4814 my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3);
4815
4816 print "create full clone of drive $drivename ($drive->{file})\n";
4817 $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4818 push @$newvollist, $newvolid;
4819
4820 if (!$running || $snapname) {
4821 qemu_img_convert($drive->{file}, $newvolid, $size, $snapname);
4822 } else {
4823 qemu_drive_mirror($vmid, $drivename, $newvolid, $newvmid);
be190583 4824 }
152fe752
DM
4825 }
4826
4827 my ($size) = PVE::Storage::volume_size_info($storecfg, $newvolid, 3);
4828
4829 my $disk = $drive;
4830 $disk->{format} = undef;
4831 $disk->{file} = $newvolid;
4832 $disk->{size} = $size;
4833
4834 return $disk;
4835}
4836
ff556cf2
DM
4837# this only works if VM is running
4838sub get_current_qemu_machine {
4839 my ($vmid) = @_;
4840
4841 my $cmd = { execute => 'query-machines', arguments => {} };
be190583 4842 my $res = PVE::QemuServer::vm_qmp_command($vmid, $cmd);
ff556cf2
DM
4843
4844 my ($current, $default);
4845 foreach my $e (@$res) {
4846 $default = $e->{name} if $e->{'is-default'};
4847 $current = $e->{name} if $e->{'is-current'};
4848 }
4849
4850 # fallback to the default machine if current is not supported by qemu
4851 return $current || $default || 'pc';
4852}
4853
1481f3f2
AD
4854sub read_x509_subject_spice {
4855 my ($filename) = @_;
4856
4857 # read x509 subject
4858 my $bio = Net::SSLeay::BIO_new_file($filename, 'r');
4859 my $x509 = Net::SSLeay::PEM_read_bio_X509($bio);
4860 Net::SSLeay::BIO_free($bio);
4861 my $nameobj = Net::SSLeay::X509_get_subject_name($x509);
4862 my $subject = Net::SSLeay::X509_NAME_oneline($nameobj);
4863 Net::SSLeay::X509_free($x509);
4864
4865 # remote-viewer wants comma as seperator (not '/')
4866 $subject =~ s!^/!!;
4867 $subject =~ s!/(\w+=)!,$1!g;
4868
4869 return $subject;
4870}
1e3baf05 48711;