]> git.proxmox.com Git - qemu-server.git/blame_incremental - PVE/QemuServer.pm
bump version to 3.1-1
[qemu-server.git] / PVE / QemuServer.pm
... / ...
CommitLineData
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;
14use Digest::SHA;
15use Fcntl ':flock';
16use Cwd 'abs_path';
17use IPC::Open3;
18use JSON;
19use Fcntl;
20use PVE::SafeSyslog;
21use Storable qw(dclone);
22use PVE::Exception qw(raise raise_param_exc);
23use PVE::Storage;
24use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline);
25use PVE::JSONSchema qw(get_standard_option);
26use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
27use PVE::INotify;
28use PVE::ProcFSTools;
29use PVE::QMPClient;
30use PVE::RPCEnvironment;
31use Time::HiRes qw(gettimeofday);
32
33my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
34
35# Note about locking: we use flock on the config file protect
36# against concurent actions.
37# Aditionaly, we have a 'lock' setting in the config file. This
38# can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
39# allowed when such lock is set. But you can ignore this kind of
40# lock with the --skiplock flag.
41
42cfs_register_file('/qemu-server/',
43 \&parse_vm_config,
44 \&write_vm_config);
45
46PVE::JSONSchema::register_standard_option('skiplock', {
47 description => "Ignore locks - only root is allowed to use this option.",
48 type => 'boolean',
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
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
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
99 return syscall(&__NR_fairsched_mknod, int($parent), int($weight), int($desired));
100}
101
102sub fairsched_rmnod {
103 my ($id) = @_;
104
105 return syscall(&__NR_fairsched_rmnod, int($id));
106}
107
108sub fairsched_mvpr {
109 my ($pid, $newid) = @_;
110
111 return syscall(&__NR_fairsched_mvpr, int($pid), int($newid));
112}
113
114sub fairsched_vcpus {
115 my ($id, $vcpus) = @_;
116
117 return syscall(&__NR_fairsched_vcpus, int($id), int($vcpus));
118}
119
120sub fairsched_rate {
121 my ($id, $op, $rate) = @_;
122
123 return syscall(&__NR_fairsched_rate, int($id), int($op), int($rate));
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
133 my $cpulim1024 = int($limit * 1024 / 100);
134 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE : FAIRSCHED_DROP_RATE;
135
136 return fairsched_rate($id, $op, $cpulim1024);
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
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 },
166 hotplug => {
167 optional => 1,
168 type => 'boolean',
169 description => "Allow hotplug for disk and network device",
170 default => 0,
171 },
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.",
182 enum => [qw(migrate backup snapshot rollback)],
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',
202 description => "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
203 minimum => 16,
204 default => 512,
205 },
206 balloon => {
207 optional => 1,
208 type => 'integer',
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,
219 },
220 keyboard => {
221 optional => 1,
222 type => 'string',
223 description => "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
224 enum => PVE::Tools::kvmkeymaplist(),
225 default => 'en-us',
226 },
227 name => {
228 optional => 1,
229 type => 'string', format => 'dns-name',
230 description => "Set a name for the VM. Only used on the configuration web interface.",
231 },
232 scsihw => {
233 optional => 1,
234 type => 'string',
235 description => "scsi controller model",
236 enum => [qw(lsi virtio-scsi-pci megasas)],
237 default => 'lsi',
238 },
239 description => {
240 optional => 1,
241 type => 'string',
242 description => "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
243 },
244 ostype => {
245 optional => 1,
246 type => 'string',
247 enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26)],
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
259win8 => Microsoft Windows 8/2012
260l24 => Linux 2.4 Kernel
261l26 => Linux 2.6/3.X Kernel
262
263other|l24|l26 ... no special behaviour
264wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
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}',
272 default => 'cdn',
273 },
274 bootdisk => {
275 optional => 1,
276 type => 'string', format => 'pve-qm-bootdisk',
277 description => "Enable booting from specified disk.",
278 pattern => '(ide|sata|scsi|virtio)\d+',
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 },
307 agent => {
308 optional => 1,
309 type => 'boolean',
310 description => "Enable/disable Qemu GuestAgent.",
311 default => 0,
312 },
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',
322 description => "Enable/disable time drift fix.",
323 default => 0,
324 },
325 localtime => {
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',
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. You can also run without any graphic card using a serial devive as terminal.",
339 enum => [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3)],
340 },
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 },
347 startdate => {
348 optional => 1,
349 type => 'string',
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 },
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 },
361 template => {
362 optional => 1,
363 type => 'boolean',
364 description => "Enable/disable Template.",
365 default => 0,
366 },
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,
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).",
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,
391 type => 'number',
392 description => "Set maximum tolerated downtime (in seconds) for migrations.",
393 minimum => 0,
394 default => 0.1,
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',
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) ],
407 default => 'kvm64',
408 },
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 }),
413 snaptime => {
414 optional => 1,
415 description => "Timestamp for snapshots.",
416 type => 'integer',
417 minimum => 0,
418 },
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 },
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 },
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;
455my $MAX_SCSI_DISKS = 14;
456my $MAX_VIRTIO_DISKS = 16;
457my $MAX_SATA_DISKS = 6;
458my $MAX_USB_DEVICES = 5;
459my $MAX_NETS = 32;
460my $MAX_UNUSED_DISKS = 8;
461my $MAX_HOSTPCI_DEVICES = 2;
462my $MAX_SERIAL_PORTS = 4;
463my $MAX_PARALLEL_PORTS = 3;
464
465my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
466 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
467my $nic_model_list_txt = join(' ', sort @$nic_model_list);
468
469my $netdesc = {
470 optional => 1,
471 type => 'string', format => 'pve-qm-net',
472 typetext => "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
473 description => <<EODESCR,
474Specify network devices.
475
476MODEL is one of: $nic_model_list_txt
477
478XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
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;
502
503my $idedesc = {
504 optional => 1,
505 type => 'string', format => 'pve-qm-drive',
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]',
507 description => "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
508};
509PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc);
510
511my $scsidesc = {
512 optional => 1,
513 type => 'string', format => 'pve-qm-drive',
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]',
515 description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
516};
517PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
518
519my $satadesc = {
520 optional => 1,
521 type => 'string', format => 'pve-qm-drive',
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]',
523 description => "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
524};
525PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc);
526
527my $virtiodesc = {
528 optional => 1,
529 type => 'string', format => 'pve-qm-drive',
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]',
531 description => "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
532};
533PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc);
534
535my $usbdesc = {
536 optional => 1,
537 type => 'string', format => 'pve-qm-usb-device',
538 typetext => 'host=HOSTUSBDEVICE|spice',
539 description => <<EODESCR,
540Configure an USB device (n is 0 to 4). This can be used to
541pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
542
543'bus-port(.port)*' (decimal numbers) or
544'vendor_id:product_id' (hexadeciaml numbers)
545
546You can use the 'lsusb -t' command to list existing usb devices.
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
550The value 'spice' can be used to add a usb redirection devices for spice.
551
552EODESCR
553};
554PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
555
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
574my $serialdesc = {
575 optional => 1,
576 type => 'string',
577 pattern => '(/dev/ttyS\d+|socket)',
578 description => <<EODESCR,
579Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device, or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
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};
586
587my $paralleldesc= {
588 optional => 1,
589 type => 'string',
590 pattern => '/dev/parport\d+|/dev/usb/lp\d+',
591 description => <<EODESCR,
592Map host parallel devices (n is 0 to 2).
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};
599
600for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
601 $confdesc->{"parallel$i"} = $paralleldesc;
602}
603
604for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
605 $confdesc->{"serial$i"} = $serialdesc;
606}
607
608for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
609 $confdesc->{"hostpci$i"} = $hostpcidesc;
610}
611
612for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
613 $drivename_hash->{"ide$i"} = 1;
614 $confdesc->{"ide$i"} = $idedesc;
615}
616
617for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
618 $drivename_hash->{"sata$i"} = 1;
619 $confdesc->{"sata$i"} = $satadesc;
620}
621
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
652 my $fh = IO::File->new("</dev/kvm") ||
653 return 0;
654
655 if (my $v = $fh->ioctl(KVM_GET_API_VERSION(), 0)) {
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`;
673
674 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
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
686 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
687 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
688 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
689 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
690}
691
692sub valid_drivename {
693 my $dev = shift;
694
695 return defined($drivename_hash->{$dev});
696}
697
698sub option_exists {
699 my $key = shift;
700 return defined($confdesc->{$key});
701}
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',
717 win8 => 'Windows 8/2012',
718 l24 => 'Linux 2.4',
719 l26 => 'Linux 2.6',
720 };
721}
722
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 {
744 return PVE::Storage::path($storecfg, $cdrom);
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/^([^:]+):(.+)$/)) {
754
755 return undef if $file =~ m|/|;
756
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') {
774 $etype = 'images';
775 } elsif ($media eq 'cdrom') {
776 $etype = 'iso';
777 } else {
778 die "internal error";
779 }
780
781 return if ($vtype eq $etype);
782
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/^([^:]+):(.+)$/) &&
794 ($drive->{file} !~ m/^\d+$/)) {
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
808 my $filename = config_file($vmid);
809
810 die "configuration file '$filename' already exists\n" if -f $filename;
811
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
830my $parse_size = sub {
831 my ($value) = @_;
832
833 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
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
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]
866# [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
867# [,aio=native|threads]
868
869sub parse_drive {
870 my ($key, $data) = @_;
871
872 my $res = {};
873
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
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)=(.+)$/) {
889 my ($k, $v) = ($1, $2);
890
891 $k = 'file' if $k eq 'volume';
892
893 return undef if defined $res->{$k};
894
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 }
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
912 if($res->{file} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
913 $res->{format} = $1;
914 }
915
916 return undef if $res->{cache} &&
917 $res->{cache} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
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
930
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
938 return undef if $res->{iops_rd} && $res->{iops};
939 return undef if $res->{iops_wr} && $res->{iops};
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
945 if ($res->{size}) {
946 return undef if !defined($res->{size} = &$parse_size($res->{size}));
947 }
948
949 if ($res->{media} && ($res->{media} eq 'cdrom')) {
950 return undef if $res->{snapshot} || $res->{trans} || $res->{format};
951 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
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
963my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
964
965sub print_drive {
966 my ($vmid, $drive) = @_;
967
968 my $opts = '';
969 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
970 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
971 }
972
973 if ($drive->{size}) {
974 $opts .= ",size=" . &$format_size($drive->{size});
975 }
976
977 return "$drive->{file}$opts";
978}
979
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 }
992 my $version = unpack("I", $versionbuf);
993 if ($version < 30000) {
994 die "scsi generic interface too old\n" if !$noerr;
995 return undef;
996 }
997
998 my $buf = "\x00" x 36;
999 my $sensebuf = "\x00" x 8;
1000 my $cmd = pack("C x3 C x1", 0x12, 36);
1001
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
1005 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1006 length($sensebuf), 0, length($buf), $buf,
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 }
1014
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 = {};
1022 (my $byte0, my $byte1, $res->{vendor},
1023 $res->{product}, $res->{revision}) = unpack("C C x6 A8 A16 A4", $buf);
1024
1025 $res->{removable} = $byte1 & 128 ? 1 : 0;
1026 $res->{type} = $byte0 & 31;
1027
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
1041sub print_drivedevice_full {
1042 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1043
1044 my $device = '';
1045 my $maxdev = 0;
1046
1047 if ($drive->{interface} eq 'virtio') {
1048 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}", $bridges);
1049 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1050 } elsif ($drive->{interface} eq 'scsi') {
1051 $maxdev = ($conf->{scsihw} && $conf->{scsihw} ne 'lsi') ? 256 : 7;
1052 my $controller = int($drive->{index} / $maxdev);
1053 my $unit = $drive->{index} % $maxdev;
1054 my $devicetype = 'hd';
1055 my $path = '';
1056 if (drive_is_cdrom($drive)) {
1057 $devicetype = 'cd';
1058 } else {
1059 if ($drive->{file} =~ m|^/|) {
1060 $path = $drive->{file};
1061 } else {
1062 $path = PVE::Storage::path($storecfg, $drive->{file});
1063 }
1064
1065 if($path =~ m/^iscsi\:\/\//){
1066 $devicetype = 'generic';
1067 } else {
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 }
1075 }
1076 }
1077
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
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
1090 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
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}";
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";
1100 }
1101
1102 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
1103
1104 return $device;
1105}
1106
1107sub print_drive_full {
1108 my ($storecfg, $vmid, $drive) = @_;
1109
1110 my $opts = '';
1111 foreach my $o (@qemu_drive_options) {
1112 next if $o eq 'bootindex';
1113 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1114 }
1115
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
1121 # use linux-aio by default (qemu default is threads)
1122 $opts .= ",aio=native" if !$drive->{aio};
1123
1124 my $path;
1125 my $volid = $drive->{file};
1126 if (drive_is_cdrom($drive)) {
1127 $path = get_iso_path($storecfg, $vmid, $volid);
1128 } else {
1129 if ($volid =~ m|^/|) {
1130 $path = $volid;
1131 } else {
1132 $path = PVE::Storage::path($storecfg, $volid);
1133 }
1134 }
1135
1136 $opts .= ",cache=none" if !$drive->{cache} && !drive_is_cdrom($drive);
1137
1138 my $pathinfo = $path ? "file=$path," : '';
1139
1140 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1141}
1142
1143sub print_netdevice_full {
1144 my ($vmid, $conf, $net, $netid, $bridges) = @_;
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=," : '';
1156 my $pciaddr = print_pci_addr("$netid", $bridges);
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}
1189
1190sub drive_is_cdrom {
1191 my ($drive) = @_;
1192
1193 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
1194
1195}
1196
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
1213# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1214sub parse_net {
1215 my ($data) = @_;
1216
1217 my $res = {};
1218
1219 foreach my $kvp (split(/,/, $data)) {
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) {
1222 my $model = lc($1);
1223 my $mac = defined($3) ? uc($3) : PVE::Tools::random_ether_addr();
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;
1230 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1231 $res->{tag} = $1;
1232 } else {
1233 return undef;
1234 }
1235
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};
1250 $res .= ",tag=$net->{tag}" if $net->{tag};
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 {
1267 my ($config, $volid) = @_;
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;
1276 }
1277 }
1278
1279 die "To many unused volume - please delete them first.\n" if !$key;
1280
1281 $config->{$key} = $volid;
1282
1283 return $key;
1284}
1285
1286PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
1287sub verify_bootdisk {
1288 my ($value, $noerr) = @_;
1289
1290 return $value if valid_drivename($value);
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;
1304
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
1312 return $value if parse_drive(undef, $value);
1313
1314 return undef if $noerr;
1315
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
1323 return $value if parse_hostpci($value);
1324
1325 return undef if $noerr;
1326
1327 die "unable to parse pci id\n";
1328}
1329
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;
1337
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
1348 foreach my $p (split(/,/, $value)) {
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
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
1398sub parse_usb_device {
1399 my ($value) = @_;
1400
1401 return undef if !$value;
1402
1403 my @dl = split(/,/, $value);
1404 my $found;
1405
1406 my $res = {};
1407 foreach my $v (@dl) {
1408 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1409 $found = 1;
1410 $res->{vendorid} = $2;
1411 $res->{productid} = $4;
1412 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1413 $found = 1;
1414 $res->{hostbus} = $1;
1415 $res->{hostport} = $2;
1416 } elsif ($v =~ m/^spice$/) {
1417 $found = 1;
1418 $res->{spice} = 1;
1419 } else {
1420 return undef;
1421 }
1422 }
1423 return undef if !$found;
1424
1425 return $res;
1426}
1427
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;
1435
1436 die "unable to parse usb device\n";
1437}
1438
1439# add JSON properties for create and set function
1440sub json_config_properties {
1441 my $prop = shift;
1442
1443 foreach my $opt (keys %$confdesc) {
1444 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
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
1458 if (!defined($value)) {
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') {
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";
1470 } elsif ($type eq 'integer') {
1471 return int($1) if $value =~ m/^(\d+)$/;
1472 die "type check ('integer') failed - got '$value'\n";
1473 } elsif ($type eq 'number') {
1474 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1475 die "type check ('number') failed - got '$value'\n";
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()
1480 my $drive = parse_drive($key, $value);
1481 return $value if $drive;
1482 die "unable to parse drive options\n";
1483 }
1484 PVE::JSONSchema::check_format($fmt, $value);
1485 return $value;
1486 }
1487 $value =~ s/^\"(.*)\"$/$1/;
1488 return $value;
1489 } else {
1490 die "internal error"
1491 }
1492}
1493
1494sub lock_config_full {
1495 my ($vmid, $timeout, $code, @param) = @_;
1496
1497 my $filename = config_file_lock($vmid);
1498
1499 my $res = lock_file($filename, $timeout, $code, @param);
1500
1501 die $@ if $@;
1502
1503 return $res;
1504}
1505
1506sub lock_config_mode {
1507 my ($vmid, $timeout, $shared, $code, @param) = @_;
1508
1509 my $filename = config_file_lock($vmid);
1510
1511 my $res = lock_file_full($filename, $timeout, $shared, $code, @param);
1512
1513 die $@ if $@;
1514
1515 return $res;
1516}
1517
1518sub lock_config {
1519 my ($vmid, $code, @param) = @_;
1520
1521 return lock_config_full($vmid, 10, $code, @param);
1522}
1523
1524sub cfs_config_path {
1525 my ($vmid, $node) = @_;
1526
1527 $node = $nodename if !$node;
1528 return "nodes/$node/qemu-server/$vmid.conf";
1529}
1530
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
1540sub config_file {
1541 my ($vmid, $node) = @_;
1542
1543 my $cfspath = cfs_config_path($vmid, $node);
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
1556 my $conf = config_file($vmid);
1557 utime undef, undef, $conf;
1558}
1559
1560sub destroy_vm {
1561 my ($storecfg, $vmid, $keep_empty_config) = @_;
1562
1563 my $conffile = config_file($vmid);
1564
1565 my $conf = load_config($vmid);
1566
1567 check_lock($conf);
1568
1569 # only remove disks owned by this VM
1570 foreach_drive($conf, sub {
1571 my ($ds, $drive) = @_;
1572
1573 return if drive_is_cdrom($drive);
1574
1575 my $volid = $drive->{file};
1576
1577 return if !$volid || $volid =~ m|^/|;
1578
1579 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
1580 return if !$path || !$owner || ($owner != $vmid);
1581
1582 PVE::Storage::vdisk_free($storecfg, $volid);
1583 });
1584
1585 if ($keep_empty_config) {
1586 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
1587 } else {
1588 unlink $conffile;
1589 }
1590
1591 # also remove unused disk
1592 eval {
1593 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1594
1595 eval {
1596 PVE::Storage::foreach_volid($dl, sub {
1597 my ($volid, $sid, $volname, $d) = @_;
1598 PVE::Storage::vdisk_free($storecfg, $volid);
1599 });
1600 };
1601 warn $@ if $@;
1602
1603 };
1604 warn $@ if $@;
1605}
1606
1607sub load_config {
1608 my ($vmid, $node) = @_;
1609
1610 my $cfspath = cfs_config_path($vmid, $node);
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;
1617}
1618
1619sub parse_vm_config {
1620 my ($filename, $raw) = @_;
1621
1622 return undef if !defined($raw);
1623
1624 my $res = {
1625 digest => Digest::SHA::sha1_hex($raw),
1626 snapshots => {},
1627 };
1628
1629 $filename =~ m|/qemu-server/(\d+)\.conf$|
1630 || die "got strange filename '$filename'";
1631
1632 my $vmid = $1;
1633
1634 my $conf = $res;
1635 my $descr = '';
1636
1637 my @lines = split(/\n/, $raw);
1638 foreach my $line (@lines) {
1639 next if $line =~ m/^\s*$/;
1640
1641 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1642 my $snapname = $1;
1643 $conf->{description} = $descr if $descr;
1644 $descr = '';
1645 $conf = $res->{snapshots}->{$snapname} = {};
1646 next;
1647 }
1648
1649 if ($line =~ m/^\#(.*)\s*$/) {
1650 $descr .= PVE::Tools::decode_text($1) . "\n";
1651 next;
1652 }
1653
1654 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1655 $descr .= PVE::Tools::decode_text($2);
1656 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1657 $conf->{snapstate} = $1;
1658 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1659 my $key = $1;
1660 my $value = $2;
1661 $conf->{$key} = $value;
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;
1674 $value = print_drive($vmid, $v);
1675 } else {
1676 warn "vm $vmid - unable to parse value of '$key'\n";
1677 next;
1678 }
1679 }
1680
1681 if ($key eq 'cdrom') {
1682 $conf->{ide2} = $value;
1683 } else {
1684 $conf->{$key} = $value;
1685 }
1686 }
1687 }
1688 }
1689
1690 $conf->{description} = $descr if $descr;
1691
1692 delete $res->{snapstate}; # just to be sure
1693
1694 return $res;
1695}
1696
1697sub write_vm_config {
1698 my ($filename, $conf) = @_;
1699
1700 delete $conf->{snapstate}; # just to be sure
1701
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 }
1707
1708 # we do not use 'smp' any longer
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};
1715 }
1716
1717 my $used_volids = {};
1718
1719 my $cleanup_config = sub {
1720 my ($cref, $snapname) = @_;
1721
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 $@;
1728
1729 $cref->{$key} = $value;
1730
1731 if (!$snapname && valid_drivename($key)) {
1732 my $drive = parse_drive($key, $value);
1733 $used_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
1734 }
1735 }
1736 };
1737
1738 &$cleanup_config($conf);
1739 foreach my $snapname (keys %{$conf->{snapshots}}) {
1740 &$cleanup_config($conf->{snapshots}->{$snapname}, $snapname);
1741 }
1742
1743 # remove 'unusedX' settings if we re-add a volume
1744 foreach my $key (keys %$conf) {
1745 my $value = $conf->{$key};
1746 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1747 delete $conf->{$key};
1748 }
1749 }
1750
1751 my $generate_raw_config = sub {
1752 my ($conf) = @_;
1753
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 };
1768
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});
1773 }
1774
1775 return $raw;
1776}
1777
1778sub update_config_nolock {
1779 my ($vmid, $conf, $skiplock) = @_;
1780
1781 check_lock($conf) if !$skiplock;
1782
1783 my $cfspath = cfs_config_path($vmid);
1784
1785 PVE::Cluster::cfs_write_file($cfspath, $conf);
1786}
1787
1788sub update_config {
1789 my ($vmid, $conf, $skiplock) = @_;
1790
1791 lock_config($vmid, &update_config_nolock, $conf, $skiplock);
1792}
1793
1794sub load_defaults {
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 }
1804
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
1817 foreach my $vmid (keys %$ids) {
1818 my $d = $ids->{$vmid};
1819 next if !$d->{node} || $d->{node} ne $nodename;
1820 next if !$d->{type} || $d->{type} ne 'qemu';
1821 $res->{$vmid}->{exists} = 1;
1822 }
1823 return $res;
1824}
1825
1826# test if VM uses local resources (to prevent migration)
1827sub check_local_resources {
1828 my ($conf, $noerr) = @_;
1829
1830 my $loc_res = 0;
1831
1832 $loc_res = 1 if $conf->{hostusb}; # old syntax
1833 $loc_res = 1 if $conf->{hostpci}; # old syntax
1834
1835 foreach my $k (keys %$conf) {
1836 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1837 }
1838
1839 die "VM uses local resources\n" if $loc_res && !$noerr;
1840
1841 return $loc_res;
1842}
1843
1844# check if used storages are available on all nodes (use by migrate)
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
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();
1870
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
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
1906 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
1907 if (defined($fh)) {
1908 my $line = <$fh>;
1909 $fh->close;
1910 return undef if !$line;
1911 my @param = split(/\0/, $line);
1912
1913 my $cmd = $param[0];
1914 return if !$cmd || ($cmd !~ m|kvm$| && $cmd !~ m|qemu-system-x86_64$|);
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 {
1930 my ($vmid, $nocheck, $node) = @_;
1931
1932 my $filename = config_file($vmid, $node);
1933
1934 die "unable to find configuration file for VM $vmid - no such machine\n"
1935 if !$nocheck && ! -f $filename;
1936
1937 my $pidfile = pidfile_name($vmid);
1938
1939 if (my $fd = IO::File->new("<$pidfile")) {
1940 my $st = stat($fd);
1941 my $line = <$fd>;
1942 close($fd);
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;
1951 if (check_cmdline($pidfile, $pid)) {
1952 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
1953 return $pid;
1954 }
1955 }
1956 }
1957 }
1958
1959 return undef;
1960}
1961
1962sub vzlist {
1963
1964 my $vzlist = config_list();
1965
1966 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1967
1968 while (defined(my $de = $fd->read)) {
1969 next if $de !~ m/^(\d+)\.pid$/;
1970 my $vmid = $1;
1971 next if !defined($vzlist->{$vmid});
1972 if (my $pid = check_running($vmid)) {
1973 $vzlist->{$vmid}->{pid} = $pid;
1974 }
1975 }
1976
1977 return $vzlist;
1978}
1979
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
1997 return $drive->{size};
1998}
1999
2000my $last_proc_pid_stat;
2001
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)
2005sub vmstatus {
2006 my ($opt_vmid, $full) = @_;
2007
2008 my $res = {};
2009
2010 my $storecfg = PVE::Storage::config();
2011
2012 my $list = vzlist();
2013 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
2014
2015 my $cpucount = $cpuinfo->{cpus} || 1;
2016
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
2029 my $size = disksize($storecfg, $conf);
2030 if (defined($size)) {
2031 $d->{disk} = 0; # no info available
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);
2039 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
2040
2041 $d->{name} = $conf->{name} || "VM $vmid";
2042 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
2043
2044 if ($conf->{balloon}) {
2045 $d->{balloon_min} = $conf->{balloon}*(1024*1024);
2046 $d->{shares} = defined($conf->{shares}) ? $conf->{shares} : 1000;
2047 }
2048
2049 $d->{uptime} = 0;
2050 $d->{cpu} = 0;
2051 $d->{mem} = 0;
2052
2053 $d->{netout} = 0;
2054 $d->{netin} = 0;
2055
2056 $d->{diskread} = 0;
2057 $d->{diskwrite} = 0;
2058
2059 $d->{template} = is_template($conf);
2060
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;
2070
2071 $d->{netout} += $netdev->{$dev}->{receive};
2072 $d->{netin} += $netdev->{$dev}->{transmit};
2073 }
2074
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
2083 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
2084 next if !$pstat; # not running
2085
2086 my $used = $pstat->{utime} + $pstat->{stime};
2087
2088 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
2089
2090 if ($pstat->{vsize}) {
2091 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
2092 }
2093
2094 my $old = $last_proc_pid_stat->{$pid};
2095 if (!$old) {
2096 $last_proc_pid_stat->{$pid} = {
2097 time => $ctime,
2098 used => $used,
2099 cpu => 0,
2100 };
2101 next;
2102 }
2103
2104 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
2105
2106 if ($dtime > 1000) {
2107 my $dutime = $used - $old->{used};
2108
2109 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
2110 $last_proc_pid_stat->{$pid} = {
2111 time => $ctime,
2112 used => $used,
2113 cpu => $d->{cpu},
2114 };
2115 } else {
2116 $d->{cpu} = $old->{cpu};
2117 }
2118 }
2119
2120 return $res if !$full;
2121
2122 my $qmpclient = PVE::QMPClient->new();
2123
2124 my $ballooncb = sub {
2125 my ($vmid, $resp) = @_;
2126
2127 my $info = $resp->{'return'};
2128 return if !$info->{max_mem};
2129
2130 my $d = $res->{$vmid};
2131
2132 # use memory assigned to VM
2133 $d->{maxmem} = $info->{max_mem};
2134 $d->{balloon} = $info->{actual};
2135
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
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) = @_;
2158
2159 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
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');
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
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
2195 my $drive = parse_drive($ds, $conf->{$ds});
2196 next if !$drive;
2197
2198 &$func($ds, $drive);
2199 }
2200}
2201
2202sub foreach_volid {
2203 my ($conf, $func) = @_;
2204
2205 my $volhash = {};
2206
2207 my $test_volid = sub {
2208 my ($volid, $is_cdrom) = @_;
2209
2210 return if !$volid;
2211
2212 $volhash->{$volid} = $is_cdrom || 0;
2213 };
2214
2215 foreach_drive($conf, sub {
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);
2223 foreach_drive($snap, sub {
2224 my ($ds, $drive) = @_;
2225 &$test_volid($drive->{file}, drive_is_cdrom($drive));
2226 });
2227 }
2228
2229 foreach my $volid (keys %$volhash) {
2230 &$func($volid, $volhash->{$volid});
2231 }
2232}
2233
2234sub vga_conf_has_spice {
2235 my ($vga) = @_;
2236
2237 return $vga && ($vga eq 'qxl');
2238}
2239
2240sub config_to_command {
2241 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2242
2243 my $cmd = [];
2244 my $globalFlags = [];
2245 my $machineFlags = [];
2246 my $rtcFlags = [];
2247 my $cpuFlags = [];
2248 my $devices = [];
2249 my $pciaddr = '';
2250 my $bridges = {};
2251 my $kvmver = kvm_user_version();
2252 my $vernum = 0; # unknown
2253 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2254 $vernum = $1*1000000+$2*1000;
2255 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2256 $vernum = $1*1000000+$2*1000+$3;
2257 }
2258
2259 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2260
2261 my $have_ovz = -f '/proc/vz/vestat';
2262
2263 push @$cmd, '/usr/bin/kvm';
2264
2265 push @$cmd, '-id', $vmid;
2266
2267 my $use_virtio = 0;
2268
2269 my $qmpsocket = qmp_socket($vmid);
2270 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2271 push @$cmd, '-mon', "chardev=qmp,mode=control";
2272
2273 my $socket = vnc_socket($vmid);
2274 push @$cmd, '-vnc', "unix:$socket,x509,password";
2275
2276 push @$cmd, '-pidfile' , pidfile_name($vmid);
2277
2278 push @$cmd, '-daemonize';
2279
2280 $pciaddr = print_pci_addr("piix3", $bridges);
2281 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2282
2283 my $use_usb2 = 0;
2284 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2285 next if !$conf->{"usb$i"};
2286 $use_usb2 = 1;
2287 }
2288 # include usb device config
2289 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2290
2291 my $vga = $conf->{vga};
2292 if (!$vga) {
2293 if ($conf->{ostype} && ($conf->{ostype} eq 'win8' ||
2294 $conf->{ostype} eq 'win7' ||
2295 $conf->{ostype} eq 'w2k8')) {
2296 $vga = 'std';
2297 } else {
2298 $vga = 'cirrus';
2299 }
2300 }
2301
2302 # enable absolute mouse coordinates (needed by vnc)
2303 my $tablet;
2304 if (defined($conf->{tablet})) {
2305 $tablet = $conf->{tablet};
2306 } else {
2307 $tablet = $defaults->{tablet};
2308 $tablet = 0 if vga_conf_has_spice($vga); # disable for spice because it is not needed
2309 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2310 }
2311
2312 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2313
2314 # host pci devices
2315 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2316 my $d = parse_hostpci($conf->{"hostpci$i"});
2317 next if !$d;
2318 $pciaddr = print_pci_addr("hostpci$i", $bridges);
2319 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2320 }
2321
2322 # usb devices
2323 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2324 my $d = parse_usb_device($conf->{"usb$i"});
2325 next if !$d;
2326 if ($d->{vendorid} && $d->{productid}) {
2327 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2328 } elsif (defined($d->{hostbus}) && defined($d->{hostport})) {
2329 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2330 } elsif ($d->{spice}) {
2331 # usb redir support for spice
2332 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2333 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2334 }
2335 }
2336
2337 # serial devices
2338 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2339 if (my $path = $conf->{"serial$i"}) {
2340 if ($path eq 'socket') {
2341 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2342 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2343 push @$devices, '-device', "isa-serial,chardev=serial$i";
2344 } else {
2345 die "no such serial device\n" if ! -c $path;
2346 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2347 push @$devices, '-device', "isa-serial,chardev=serial$i";
2348 }
2349 }
2350 }
2351
2352 # parallel devices
2353 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2354 if (my $path = $conf->{"parallel$i"}) {
2355 die "no such parallel device\n" if ! -c $path;
2356 push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
2357 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2358 }
2359 }
2360
2361 my $vmname = $conf->{name} || "vm$vmid";
2362
2363 push @$cmd, '-name', $vmname;
2364
2365 my $sockets = 1;
2366 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
2367 $sockets = $conf->{sockets} if $conf->{sockets};
2368
2369 my $cores = $conf->{cores} || 1;
2370 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2371
2372 push @$cmd, '-nodefaults';
2373
2374 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
2375
2376 my $bootindex_hash = {};
2377 my $i = 1;
2378 foreach my $o (split(//, $bootorder)) {
2379 $bootindex_hash->{$o} = $i*100;
2380 $i++;
2381 }
2382
2383 push @$cmd, '-boot', "menu=on";
2384
2385 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
2386
2387 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
2388
2389 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2390
2391 # time drift fix
2392 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
2393
2394 my $nokvm = defined($conf->{kvm}) && $conf->{kvm} == 0 ? 1 : 0;
2395 my $useLocaltime = $conf->{localtime};
2396
2397 if (my $ost = $conf->{ostype}) {
2398 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26
2399
2400 if ($ost =~ m/^w/) { # windows
2401 $useLocaltime = 1 if !defined($conf->{localtime});
2402
2403 # use time drift fix when acpi is enabled
2404 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
2405 $tdf = 1 if !defined($conf->{tdf});
2406 }
2407 }
2408
2409 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2410 $ost eq 'wvista') {
2411 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2412 push @$cmd, '-no-hpet';
2413 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2414 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2415 }
2416
2417 if ($ost eq 'win7' || $ost eq 'win8') {
2418 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2419 }
2420 }
2421
2422 push @$rtcFlags, 'driftfix=slew' if $tdf;
2423
2424 if ($nokvm) {
2425 push @$machineFlags, 'accel=tcg';
2426 } else {
2427 die "No accelerator found!\n" if !$cpuinfo->{hvm};
2428 }
2429
2430 my $machine_type = $forcemachine || $conf->{machine};
2431 if ($machine_type) {
2432 push @$machineFlags, "type=${machine_type}";
2433 }
2434
2435 if ($conf->{startdate}) {
2436 push @$rtcFlags, "base=$conf->{startdate}";
2437 } elsif ($useLocaltime) {
2438 push @$rtcFlags, 'base=localtime';
2439 }
2440
2441 my $cpu = $nokvm ? "qemu64" : "kvm64";
2442 $cpu = $conf->{cpu} if $conf->{cpu};
2443
2444 push @$cpuFlags , '+x2apic' if !$nokvm;
2445
2446 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2447
2448 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2449
2450 push @$cmd, '-cpu', $cpu;
2451
2452 push @$cmd, '-S' if $conf->{freeze};
2453
2454 # set keyboard layout
2455 my $kb = $conf->{keyboard} || $defaults->{keyboard};
2456 push @$cmd, '-k', $kb if $kb;
2457
2458 # enable sound
2459 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2460 #push @$cmd, '-soundhw', 'es1370';
2461 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2462
2463 if($conf->{agent}) {
2464 my $qgasocket = qga_socket($vmid);
2465 my $pciaddr = print_pci_addr("qga0", $bridges);
2466 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2467 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2468 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2469 }
2470
2471 my $spice_port;
2472 if (vga_conf_has_spice($vga)) {
2473 my $pciaddr = print_pci_addr("spice", $bridges);
2474
2475 $spice_port = PVE::Tools::next_unused_port(61000, 61099);
2476
2477 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2478
2479 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2480 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2481 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2482 }
2483
2484 # enable balloon by default, unless explicitly disabled
2485 if (!defined($conf->{balloon}) || $conf->{balloon}) {
2486 $pciaddr = print_pci_addr("balloon0", $bridges);
2487 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2488 }
2489
2490 if ($conf->{watchdog}) {
2491 my $wdopts = parse_watchdog($conf->{watchdog});
2492 $pciaddr = print_pci_addr("watchdog", $bridges);
2493 my $watchdog = $wdopts->{model} || 'i6300esb';
2494 push @$devices, '-device', "$watchdog$pciaddr";
2495 push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
2496 }
2497
2498 my $vollist = [];
2499 my $scsicontroller = {};
2500 my $ahcicontroller = {};
2501 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : $defaults->{scsihw};
2502
2503 foreach_drive($conf, sub {
2504 my ($ds, $drive) = @_;
2505
2506 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
2507 push @$vollist, $drive->{file};
2508 }
2509
2510 $use_virtio = 1 if $ds =~ m/^virtio/;
2511
2512 if (drive_is_cdrom ($drive)) {
2513 if ($bootindex_hash->{d}) {
2514 $drive->{bootindex} = $bootindex_hash->{d};
2515 $bootindex_hash->{d} += 1;
2516 }
2517 } else {
2518 if ($bootindex_hash->{c}) {
2519 $drive->{bootindex} = $bootindex_hash->{c} if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
2520 $bootindex_hash->{c} += 1;
2521 }
2522 }
2523
2524 if ($drive->{interface} eq 'scsi') {
2525
2526 my $maxdev = ($scsihw ne 'lsi') ? 256 : 7;
2527 my $controller = int($drive->{index} / $maxdev);
2528 $pciaddr = print_pci_addr("scsihw$controller", $bridges);
2529 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2530 $scsicontroller->{$controller}=1;
2531 }
2532
2533 if ($drive->{interface} eq 'sata') {
2534 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2535 $pciaddr = print_pci_addr("ahci$controller", $bridges);
2536 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2537 $ahcicontroller->{$controller}=1;
2538 }
2539
2540 push @$devices, '-drive',print_drive_full($storecfg, $vmid, $drive);
2541 push @$devices, '-device',print_drivedevice_full($storecfg, $conf, $vmid, $drive, $bridges);
2542 });
2543
2544 push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
2545
2546 for (my $i = 0; $i < $MAX_NETS; $i++) {
2547 next if !$conf->{"net$i"};
2548 my $d = parse_net($conf->{"net$i"});
2549 next if !$d;
2550
2551 $use_virtio = 1 if $d->{model} eq 'virtio';
2552
2553 if ($bootindex_hash->{n}) {
2554 $d->{bootindex} = $bootindex_hash->{n};
2555 $bootindex_hash->{n} += 1;
2556 }
2557
2558 my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i");
2559 push @$devices, '-netdev', $netdevfull;
2560
2561 my $netdevicefull = print_netdevice_full($vmid,$conf,$d,"net$i",$bridges);
2562 push @$devices, '-device', $netdevicefull;
2563 }
2564
2565 #bridges
2566 while (my ($k, $v) = each %$bridges) {
2567 $pciaddr = print_pci_addr("pci.$k");
2568 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2569 }
2570
2571
2572 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2573 # when the VM uses virtio devices.
2574 if (!$use_virtio && $have_ovz) {
2575
2576 my $cpuunits = defined($conf->{cpuunits}) ?
2577 $conf->{cpuunits} : $defaults->{cpuunits};
2578
2579 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2580
2581 # fixme: cpulimit is currently ignored
2582 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2583 }
2584
2585 # add custom args
2586 if ($conf->{args}) {
2587 my $aa = PVE::Tools::split_args($conf->{args});
2588 push @$cmd, @$aa;
2589 }
2590
2591 push @$cmd, @$devices;
2592 push @$cmd, '-rtc', join(',', @$rtcFlags)
2593 if scalar(@$rtcFlags);
2594 push @$cmd, '-machine', join(',', @$machineFlags)
2595 if scalar(@$machineFlags);
2596 push @$cmd, '-global', join(',', @$globalFlags)
2597 if scalar(@$globalFlags);
2598
2599 return wantarray ? ($cmd, $vollist, $spice_port) : $cmd;
2600}
2601
2602sub vnc_socket {
2603 my ($vmid) = @_;
2604 return "${var_run_tmpdir}/$vmid.vnc";
2605}
2606
2607sub spice_port {
2608 my ($vmid) = @_;
2609
2610 my $res = vm_mon_cmd($vmid, 'query-spice');
2611
2612 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2613}
2614
2615sub qmp_socket {
2616 my ($vmid) = @_;
2617 return "${var_run_tmpdir}/$vmid.qmp";
2618}
2619
2620sub qga_socket {
2621 my ($vmid) = @_;
2622 return "${var_run_tmpdir}/$vmid.qga";
2623}
2624
2625sub pidfile_name {
2626 my ($vmid) = @_;
2627 return "${var_run_tmpdir}/$vmid.pid";
2628}
2629
2630sub vm_devices_list {
2631 my ($vmid) = @_;
2632
2633 my $res = vm_mon_cmd($vmid, 'query-pci');
2634
2635 my $devices = {};
2636 foreach my $pcibus (@$res) {
2637 foreach my $device (@{$pcibus->{devices}}) {
2638 next if !$device->{'qdev_id'};
2639 $devices->{$device->{'qdev_id'}} = $device;
2640 }
2641 }
2642
2643 return $devices;
2644}
2645
2646sub vm_deviceplug {
2647 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2648
2649 return 1 if !check_running($vmid);
2650
2651 if ($deviceid eq 'tablet') {
2652 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2653 qemu_deviceadd($vmid, $devicefull);
2654 return 1;
2655 }
2656
2657 return 1 if !$conf->{hotplug};
2658
2659 my $devices_list = vm_devices_list($vmid);
2660 return 1 if defined($devices_list->{$deviceid});
2661
2662 qemu_bridgeadd($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2663
2664 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2665 return undef if !qemu_driveadd($storecfg, $vmid, $device);
2666 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
2667 qemu_deviceadd($vmid, $devicefull);
2668 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2669 qemu_drivedel($vmid, $deviceid);
2670 return undef;
2671 }
2672 }
2673
2674 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2675 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
2676 my $pciaddr = print_pci_addr($deviceid);
2677 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2678 qemu_deviceadd($vmid, $devicefull);
2679 return undef if(!qemu_deviceaddverify($vmid, $deviceid));
2680 }
2681
2682 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2683 return 1 if ($conf->{scsihw} && $conf->{scsihw} ne 'lsi'); #virtio-scsi not yet support hotplug
2684 return undef if !qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
2685 return undef if !qemu_driveadd($storecfg, $vmid, $device);
2686 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
2687 if(!qemu_deviceadd($vmid, $devicefull)) {
2688 qemu_drivedel($vmid, $deviceid);
2689 return undef;
2690 }
2691 }
2692
2693 if ($deviceid =~ m/^(net)(\d+)$/) {
2694 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
2695 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid);
2696 qemu_deviceadd($vmid, $netdevicefull);
2697 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2698 qemu_netdevdel($vmid, $deviceid);
2699 return undef;
2700 }
2701 }
2702
2703 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2704 my $bridgeid = $2;
2705 my $pciaddr = print_pci_addr($deviceid);
2706 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2707 qemu_deviceadd($vmid, $devicefull);
2708 return undef if !qemu_deviceaddverify($vmid, $deviceid);
2709 }
2710
2711 return 1;
2712}
2713
2714sub vm_deviceunplug {
2715 my ($vmid, $conf, $deviceid) = @_;
2716
2717 return 1 if !check_running ($vmid);
2718
2719 if ($deviceid eq 'tablet') {
2720 qemu_devicedel($vmid, $deviceid);
2721 return 1;
2722 }
2723
2724 return 1 if !$conf->{hotplug};
2725
2726 my $devices_list = vm_devices_list($vmid);
2727 return 1 if !defined($devices_list->{$deviceid});
2728
2729 die "can't unplug bootdisk" if $conf->{bootdisk} && $conf->{bootdisk} eq $deviceid;
2730
2731 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2732 qemu_devicedel($vmid, $deviceid);
2733 return undef if !qemu_devicedelverify($vmid, $deviceid);
2734 return undef if !qemu_drivedel($vmid, $deviceid);
2735 }
2736
2737 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2738 return undef if !qemu_devicedel($vmid, $deviceid);
2739 }
2740
2741 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2742 return undef if !qemu_devicedel($vmid, $deviceid);
2743 return undef if !qemu_drivedel($vmid, $deviceid);
2744 }
2745
2746 if ($deviceid =~ m/^(net)(\d+)$/) {
2747 qemu_devicedel($vmid, $deviceid);
2748 return undef if !qemu_devicedelverify($vmid, $deviceid);
2749 return undef if !qemu_netdevdel($vmid, $deviceid);
2750 }
2751
2752 return 1;
2753}
2754
2755sub qemu_deviceadd {
2756 my ($vmid, $devicefull) = @_;
2757
2758 $devicefull = "driver=".$devicefull;
2759 my %options = split(/[=,]/, $devicefull);
2760
2761 vm_mon_cmd($vmid, "device_add" , %options);
2762 return 1;
2763}
2764
2765sub qemu_devicedel {
2766 my($vmid, $deviceid) = @_;
2767 my $ret = vm_mon_cmd($vmid, "device_del", id => $deviceid);
2768 return 1;
2769}
2770
2771sub qemu_driveadd {
2772 my($storecfg, $vmid, $device) = @_;
2773
2774 my $drive = print_drive_full($storecfg, $vmid, $device);
2775 my $ret = vm_human_monitor_command($vmid, "drive_add auto $drive");
2776 # If the command succeeds qemu prints: "OK"
2777 if ($ret !~ m/OK/s) {
2778 syslog("err", "adding drive failed: $ret");
2779 return undef;
2780 }
2781 return 1;
2782}
2783
2784sub qemu_drivedel {
2785 my($vmid, $deviceid) = @_;
2786
2787 my $ret = vm_human_monitor_command($vmid, "drive_del drive-$deviceid");
2788 $ret =~ s/^\s+//;
2789 if ($ret =~ m/Device \'.*?\' not found/s) {
2790 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2791 }
2792 elsif ($ret ne "") {
2793 syslog("err", "deleting drive $deviceid failed : $ret");
2794 return undef;
2795 }
2796 return 1;
2797}
2798
2799sub qemu_deviceaddverify {
2800 my ($vmid,$deviceid) = @_;
2801
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;
2806 }
2807 syslog("err", "error on hotplug device $deviceid");
2808 return undef;
2809}
2810
2811
2812sub qemu_devicedelverify {
2813 my ($vmid,$deviceid) = @_;
2814
2815 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2816 for (my $i = 0; $i <= 5; $i++) {
2817 my $devices_list = vm_devices_list($vmid);
2818 return 1 if !defined($devices_list->{$deviceid});
2819 sleep 1;
2820 }
2821 syslog("err", "error on hot-unplugging device $deviceid");
2822 return undef;
2823}
2824
2825sub qemu_findorcreatescsihw {
2826 my ($storecfg, $conf, $vmid, $device) = @_;
2827
2828 my $maxdev = ($conf->{scsihw} && $conf->{scsihw} ne 'lsi') ? 256 : 7;
2829 my $controller = int($device->{index} / $maxdev);
2830 my $scsihwid="scsihw$controller";
2831 my $devices_list = vm_devices_list($vmid);
2832
2833 if(!defined($devices_list->{$scsihwid})) {
2834 return undef if !vm_deviceplug($storecfg, $conf, $vmid, $scsihwid);
2835 }
2836 return 1;
2837}
2838
2839sub qemu_bridgeadd {
2840 my ($storecfg, $conf, $vmid, $device) = @_;
2841
2842 my $bridges = {};
2843 my $bridgeid = undef;
2844 print_pci_addr($device, $bridges);
2845
2846 while (my ($k, $v) = each %$bridges) {
2847 $bridgeid = $k;
2848 }
2849 return if !$bridgeid || $bridgeid < 1;
2850 my $bridge = "pci.$bridgeid";
2851 my $devices_list = vm_devices_list($vmid);
2852
2853 if(!defined($devices_list->{$bridge})) {
2854 return undef if !vm_deviceplug($storecfg, $conf, $vmid, $bridge);
2855 }
2856 return 1;
2857}
2858
2859sub qemu_netdevadd {
2860 my ($vmid, $conf, $device, $deviceid) = @_;
2861
2862 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
2863 my %options = split(/[=,]/, $netdev);
2864
2865 vm_mon_cmd($vmid, "netdev_add", %options);
2866 return 1;
2867}
2868
2869sub qemu_netdevdel {
2870 my ($vmid, $deviceid) = @_;
2871
2872 vm_mon_cmd($vmid, "netdev_del", id => $deviceid);
2873 return 1;
2874}
2875
2876sub qemu_block_set_io_throttle {
2877 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2878
2879 return if !check_running($vmid) ;
2880
2881 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));
2882
2883}
2884
2885# old code, only used to shutdown old VM after update
2886sub __read_avail {
2887 my ($fh, $timeout) = @_;
2888
2889 my $sel = new IO::Select;
2890 $sel->add($fh);
2891
2892 my $res = '';
2893 my $buf;
2894
2895 my @ready;
2896 while (scalar (@ready = $sel->can_read($timeout))) {
2897 my $count;
2898 if ($count = $fh->sysread($buf, 8192)) {
2899 if ($buf =~ /^(.*)\(qemu\) $/s) {
2900 $res .= $1;
2901 last;
2902 } else {
2903 $res .= $buf;
2904 }
2905 } else {
2906 if (!defined($count)) {
2907 die "$!\n";
2908 }
2909 last;
2910 }
2911 }
2912
2913 die "monitor read timeout\n" if !scalar(@ready);
2914
2915 return $res;
2916}
2917
2918# old code, only used to shutdown old VM after update
2919sub vm_monitor_command {
2920 my ($vmid, $cmdstr, $nocheck) = @_;
2921
2922 my $res;
2923
2924 eval {
2925 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
2926
2927 my $sname = "${var_run_tmpdir}/$vmid.mon";
2928
2929 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
2930 die "unable to connect to VM $vmid socket - $!\n";
2931
2932 my $timeout = 3;
2933
2934 # hack: migrate sometime blocks the monitor (when migrate_downtime
2935 # is set)
2936 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2937 $timeout = 60*60; # 1 hour
2938 }
2939
2940 # read banner;
2941 my $data = __read_avail($sock, $timeout);
2942
2943 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2944 die "got unexpected qemu monitor banner\n";
2945 }
2946
2947 my $sel = new IO::Select;
2948 $sel->add($sock);
2949
2950 if (!scalar(my @ready = $sel->can_write($timeout))) {
2951 die "monitor write error - timeout";
2952 }
2953
2954 my $fullcmd = "$cmdstr\r";
2955
2956 # syslog('info', "VM $vmid monitor command: $cmdstr");
2957
2958 my $b;
2959 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2960 die "monitor write error - $!";
2961 }
2962
2963 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2964
2965 $timeout = 20;
2966
2967 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2968 $timeout = 60*60; # 1 hour
2969 } elsif ($cmdstr =~ m/^(eject|change)/) {
2970 $timeout = 60; # note: cdrom mount command is slow
2971 }
2972 if ($res = __read_avail($sock, $timeout)) {
2973
2974 my @lines = split("\r?\n", $res);
2975
2976 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2977
2978 $res = join("\n", @lines);
2979 $res .= "\n";
2980 }
2981 };
2982
2983 my $err = $@;
2984
2985 if ($err) {
2986 syslog("err", "VM $vmid monitor command failed - $err");
2987 die $err;
2988 }
2989
2990 return $res;
2991}
2992
2993sub qemu_block_resize {
2994 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
2995
2996 my $running = check_running($vmid);
2997
2998 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
2999
3000 return if !$running;
3001
3002 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3003
3004}
3005
3006sub qemu_volume_snapshot {
3007 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3008
3009 my $running = check_running($vmid);
3010
3011 return if !PVE::Storage::volume_snapshot($storecfg, $volid, $snap, $running);
3012
3013 return if !$running;
3014
3015 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3016
3017}
3018
3019sub qemu_volume_snapshot_delete {
3020 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3021
3022 my $running = check_running($vmid);
3023
3024 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3025
3026 return if !$running;
3027
3028 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
3029}
3030
3031sub qga_freezefs {
3032 my ($vmid) = @_;
3033
3034 #need to impplement call to qemu-ga
3035}
3036
3037sub qga_unfreezefs {
3038 my ($vmid) = @_;
3039
3040 #need to impplement call to qemu-ga
3041}
3042
3043sub vm_start {
3044 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3045
3046 lock_config($vmid, sub {
3047 my $conf = load_config($vmid, $migratedfrom);
3048
3049 die "you can't start a vm if it's a template\n" if is_template($conf);
3050
3051 check_lock($conf) if !$skiplock;
3052
3053 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
3054
3055 my $defaults = load_defaults();
3056
3057 # set environment variable useful inside network script
3058 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
3059
3060 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
3061
3062 my $migrate_port = 0;
3063 my $migrate_uri;
3064 if ($statefile) {
3065 if ($statefile eq 'tcp') {
3066 my $localip = "localhost";
3067 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
3068 if ($datacenterconf->{migration_unsecure}) {
3069 my $nodename = PVE::INotify::nodename();
3070 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
3071 }
3072 $migrate_port = PVE::Tools::next_migrate_port();
3073 $migrate_uri = "tcp:${localip}:${migrate_port}";
3074 push @$cmd, '-incoming', $migrate_uri;
3075 push @$cmd, '-S';
3076 } else {
3077 push @$cmd, '-loadstate', $statefile;
3078 }
3079 } elsif ($paused) {
3080 push @$cmd, '-S';
3081 }
3082
3083 # host pci devices
3084 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3085 my $d = parse_hostpci($conf->{"hostpci$i"});
3086 next if !$d;
3087 my $info = pci_device_info("0000:$d->{pciid}");
3088 die "IOMMU not present\n" if !check_iommu_support();
3089 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3090 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub($info);
3091 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset($info);
3092 }
3093
3094 PVE::Storage::activate_volumes($storecfg, $vollist);
3095
3096 eval { run_command($cmd, timeout => $statefile ? undef : 30,
3097 umask => 0077); };
3098 my $err = $@;
3099 die "start failed: $err" if $err;
3100
3101 print "migration listens on $migrate_uri\n" if $migrate_uri;
3102
3103 if ($statefile && $statefile ne 'tcp') {
3104 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
3105 warn $@ if $@;
3106 }
3107
3108 if ($migratedfrom) {
3109 my $capabilities = {};
3110 $capabilities->{capability} = "xbzrle";
3111 $capabilities->{state} = JSON::true;
3112 eval { vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => [$capabilities]); };
3113 warn $@ if $@;
3114
3115 if ($spice_port) {
3116 print "spice listens on port $spice_port\n";
3117 if ($spice_ticket) {
3118 PVE::QemuServer::vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice', password => $spice_ticket);
3119 PVE::QemuServer::vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice', time => "+30");
3120 }
3121 }
3122
3123 } else {
3124
3125 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
3126 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
3127 if $conf->{balloon};
3128 vm_mon_cmd_nocheck($vmid, 'qom-set',
3129 path => "machine/peripheral/balloon0",
3130 property => "guest-stats-polling-interval",
3131 value => 2);
3132 }
3133 }
3134 });
3135}
3136
3137sub vm_mon_cmd {
3138 my ($vmid, $execute, %params) = @_;
3139
3140 my $cmd = { execute => $execute, arguments => \%params };
3141 vm_qmp_command($vmid, $cmd);
3142}
3143
3144sub vm_mon_cmd_nocheck {
3145 my ($vmid, $execute, %params) = @_;
3146
3147 my $cmd = { execute => $execute, arguments => \%params };
3148 vm_qmp_command($vmid, $cmd, 1);
3149}
3150
3151sub vm_qmp_command {
3152 my ($vmid, $cmd, $nocheck) = @_;
3153
3154 my $res;
3155
3156 my $timeout;
3157 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
3158 $timeout = $cmd->{arguments}->{timeout};
3159 delete $cmd->{arguments}->{timeout};
3160 }
3161
3162 eval {
3163 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3164 my $sname = qmp_socket($vmid);
3165 if (-e $sname) {
3166 my $qmpclient = PVE::QMPClient->new();
3167
3168 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3169 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
3170 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3171 if scalar(%{$cmd->{arguments}});
3172 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
3173 } else {
3174 die "unable to open monitor socket\n";
3175 }
3176 };
3177 if (my $err = $@) {
3178 syslog("err", "VM $vmid qmp command failed - $err");
3179 die $err;
3180 }
3181
3182 return $res;
3183}
3184
3185sub vm_human_monitor_command {
3186 my ($vmid, $cmdline) = @_;
3187
3188 my $res;
3189
3190 my $cmd = {
3191 execute => 'human-monitor-command',
3192 arguments => { 'command-line' => $cmdline},
3193 };
3194
3195 return vm_qmp_command($vmid, $cmd);
3196}
3197
3198sub vm_commandline {
3199 my ($storecfg, $vmid) = @_;
3200
3201 my $conf = load_config($vmid);
3202
3203 my $defaults = load_defaults();
3204
3205 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
3206
3207 return join(' ', @$cmd);
3208}
3209
3210sub vm_reset {
3211 my ($vmid, $skiplock) = @_;
3212
3213 lock_config($vmid, sub {
3214
3215 my $conf = load_config($vmid);
3216
3217 check_lock($conf) if !$skiplock;
3218
3219 vm_mon_cmd($vmid, "system_reset");
3220 });
3221}
3222
3223sub get_vm_volumes {
3224 my ($conf) = @_;
3225
3226 my $vollist = [];
3227 foreach_volid($conf, sub {
3228 my ($volid, $is_cdrom) = @_;
3229
3230 return if $volid =~ m|^/|;
3231
3232 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
3233 return if !$sid;
3234
3235 push @$vollist, $volid;
3236 });
3237
3238 return $vollist;
3239}
3240
3241sub vm_stop_cleanup {
3242 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3243
3244 eval {
3245 fairsched_rmnod($vmid); # try to destroy group
3246
3247 if (!$keepActive) {
3248 my $vollist = get_vm_volumes($conf);
3249 PVE::Storage::deactivate_volumes($storecfg, $vollist);
3250 }
3251
3252 foreach my $ext (qw(mon qmp pid vnc qga)) {
3253 unlink "/var/run/qemu-server/${vmid}.$ext";
3254 }
3255 };
3256 warn $@ if $@; # avoid errors - just warn
3257}
3258
3259# Note: use $nockeck to skip tests if VM configuration file exists.
3260# We need that when migration VMs to other nodes (files already moved)
3261# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3262sub vm_stop {
3263 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3264
3265 $force = 1 if !defined($force) && !$shutdown;
3266
3267 if ($migratedfrom){
3268 my $pid = check_running($vmid, $nocheck, $migratedfrom);
3269 kill 15, $pid if $pid;
3270 my $conf = load_config($vmid, $migratedfrom);
3271 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive);
3272 return;
3273 }
3274
3275 lock_config($vmid, sub {
3276
3277 my $pid = check_running($vmid, $nocheck);
3278 return if !$pid;
3279
3280 my $conf;
3281 if (!$nocheck) {
3282 $conf = load_config($vmid);
3283 check_lock($conf) if !$skiplock;
3284 if (!defined($timeout) && $shutdown && $conf->{startup}) {
3285 my $opts = parse_startup($conf->{startup});
3286 $timeout = $opts->{down} if $opts->{down};
3287 }
3288 }
3289
3290 $timeout = 60 if !defined($timeout);
3291
3292 eval {
3293 if ($shutdown) {
3294 $nocheck ? vm_mon_cmd_nocheck($vmid, "system_powerdown") : vm_mon_cmd($vmid, "system_powerdown");
3295
3296 } else {
3297 $nocheck ? vm_mon_cmd_nocheck($vmid, "quit") : vm_mon_cmd($vmid, "quit");
3298 }
3299 };
3300 my $err = $@;
3301
3302 if (!$err) {
3303 my $count = 0;
3304 while (($count < $timeout) && check_running($vmid, $nocheck)) {
3305 $count++;
3306 sleep 1;
3307 }
3308
3309 if ($count >= $timeout) {
3310 if ($force) {
3311 warn "VM still running - terminating now with SIGTERM\n";
3312 kill 15, $pid;
3313 } else {
3314 die "VM quit/powerdown failed - got timeout\n";
3315 }
3316 } else {
3317 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
3318 return;
3319 }
3320 } else {
3321 if ($force) {
3322 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3323 kill 15, $pid;
3324 } else {
3325 die "VM quit/powerdown failed\n";
3326 }
3327 }
3328
3329 # wait again
3330 $timeout = 10;
3331
3332 my $count = 0;
3333 while (($count < $timeout) && check_running($vmid, $nocheck)) {
3334 $count++;
3335 sleep 1;
3336 }
3337
3338 if ($count >= $timeout) {
3339 warn "VM still running - terminating now with SIGKILL\n";
3340 kill 9, $pid;
3341 sleep 1;
3342 }
3343
3344 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
3345 });
3346}
3347
3348sub vm_suspend {
3349 my ($vmid, $skiplock) = @_;
3350
3351 lock_config($vmid, sub {
3352
3353 my $conf = load_config($vmid);
3354
3355 check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3356
3357 vm_mon_cmd($vmid, "stop");
3358 });
3359}
3360
3361sub vm_resume {
3362 my ($vmid, $skiplock) = @_;
3363
3364 lock_config($vmid, sub {
3365
3366 my $conf = load_config($vmid);
3367
3368 check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3369
3370 vm_mon_cmd($vmid, "cont");
3371 });
3372}
3373
3374sub vm_sendkey {
3375 my ($vmid, $skiplock, $key) = @_;
3376
3377 lock_config($vmid, sub {
3378
3379 my $conf = load_config($vmid);
3380
3381 # there is no qmp command, so we use the human monitor command
3382 vm_human_monitor_command($vmid, "sendkey $key");
3383 });
3384}
3385
3386sub vm_destroy {
3387 my ($storecfg, $vmid, $skiplock) = @_;
3388
3389 lock_config($vmid, sub {
3390
3391 my $conf = load_config($vmid);
3392
3393 check_lock($conf) if !$skiplock;
3394
3395 if (!check_running($vmid)) {
3396 fairsched_rmnod($vmid); # try to destroy group
3397 destroy_vm($storecfg, $vmid);
3398 } else {
3399 die "VM $vmid is running - destroy failed\n";
3400 }
3401 });
3402}
3403
3404# pci helpers
3405
3406sub file_write {
3407 my ($filename, $buf) = @_;
3408
3409 my $fh = IO::File->new($filename, "w");
3410 return undef if !$fh;
3411
3412 my $res = print $fh $buf;
3413
3414 $fh->close();
3415
3416 return $res;
3417}
3418
3419sub pci_device_info {
3420 my ($name) = @_;
3421
3422 my $res;
3423
3424 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3425 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3426
3427 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
3428 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3429
3430 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
3431 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3432
3433 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
3434 return undef if !defined($product) || $product !~ s/^0x//;
3435
3436 $res = {
3437 name => $name,
3438 vendor => $vendor,
3439 product => $product,
3440 domain => $domain,
3441 bus => $bus,
3442 slot => $slot,
3443 func => $func,
3444 irq => $irq,
3445 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
3446 };
3447
3448 return $res;
3449}
3450
3451sub pci_dev_reset {
3452 my ($dev) = @_;
3453
3454 my $name = $dev->{name};
3455
3456 my $fn = "$pcisysfs/devices/$name/reset";
3457
3458 return file_write($fn, "1");
3459}
3460
3461sub pci_dev_bind_to_stub {
3462 my ($dev) = @_;
3463
3464 my $name = $dev->{name};
3465
3466 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3467 return 1 if -d $testdir;
3468
3469 my $data = "$dev->{vendor} $dev->{product}";
3470 return undef if !file_write("$pcisysfs/drivers/pci-stub/new_id", $data);
3471
3472 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3473 if (!file_write($fn, $name)) {
3474 return undef if -f $fn;
3475 }
3476
3477 $fn = "$pcisysfs/drivers/pci-stub/bind";
3478 if (! -d $testdir) {
3479 return undef if !file_write($fn, $name);
3480 }
3481
3482 return -d $testdir;
3483}
3484
3485sub print_pci_addr {
3486 my ($id, $bridges) = @_;
3487
3488 my $res = '';
3489 my $devices = {
3490 piix3 => { bus => 0, addr => 1 },
3491 #addr2 : first videocard
3492 balloon0 => { bus => 0, addr => 3 },
3493 watchdog => { bus => 0, addr => 4 },
3494 scsihw0 => { bus => 0, addr => 5 },
3495 scsihw1 => { bus => 0, addr => 6 },
3496 ahci0 => { bus => 0, addr => 7 },
3497 qga0 => { bus => 0, addr => 8 },
3498 spice => { bus => 0, addr => 9 },
3499 virtio0 => { bus => 0, addr => 10 },
3500 virtio1 => { bus => 0, addr => 11 },
3501 virtio2 => { bus => 0, addr => 12 },
3502 virtio3 => { bus => 0, addr => 13 },
3503 virtio4 => { bus => 0, addr => 14 },
3504 virtio5 => { bus => 0, addr => 15 },
3505 hostpci0 => { bus => 0, addr => 16 },
3506 hostpci1 => { bus => 0, addr => 17 },
3507 net0 => { bus => 0, addr => 18 },
3508 net1 => { bus => 0, addr => 19 },
3509 net2 => { bus => 0, addr => 20 },
3510 net3 => { bus => 0, addr => 21 },
3511 net4 => { bus => 0, addr => 22 },
3512 net5 => { bus => 0, addr => 23 },
3513 #addr29 : usb-host (pve-usb.cfg)
3514 'pci.1' => { bus => 0, addr => 30 },
3515 'pci.2' => { bus => 0, addr => 31 },
3516 'net6' => { bus => 1, addr => 1 },
3517 'net7' => { bus => 1, addr => 2 },
3518 'net8' => { bus => 1, addr => 3 },
3519 'net9' => { bus => 1, addr => 4 },
3520 'net10' => { bus => 1, addr => 5 },
3521 'net11' => { bus => 1, addr => 6 },
3522 'net12' => { bus => 1, addr => 7 },
3523 'net13' => { bus => 1, addr => 8 },
3524 'net14' => { bus => 1, addr => 9 },
3525 'net15' => { bus => 1, addr => 10 },
3526 'net16' => { bus => 1, addr => 11 },
3527 'net17' => { bus => 1, addr => 12 },
3528 'net18' => { bus => 1, addr => 13 },
3529 'net19' => { bus => 1, addr => 14 },
3530 'net20' => { bus => 1, addr => 15 },
3531 'net21' => { bus => 1, addr => 16 },
3532 'net22' => { bus => 1, addr => 17 },
3533 'net23' => { bus => 1, addr => 18 },
3534 'net24' => { bus => 1, addr => 19 },
3535 'net25' => { bus => 1, addr => 20 },
3536 'net26' => { bus => 1, addr => 21 },
3537 'net27' => { bus => 1, addr => 22 },
3538 'net28' => { bus => 1, addr => 23 },
3539 'net29' => { bus => 1, addr => 24 },
3540 'net30' => { bus => 1, addr => 25 },
3541 'net31' => { bus => 1, addr => 26 },
3542 'virtio6' => { bus => 2, addr => 1 },
3543 'virtio7' => { bus => 2, addr => 2 },
3544 'virtio8' => { bus => 2, addr => 3 },
3545 'virtio9' => { bus => 2, addr => 4 },
3546 'virtio10' => { bus => 2, addr => 5 },
3547 'virtio11' => { bus => 2, addr => 6 },
3548 'virtio12' => { bus => 2, addr => 7 },
3549 'virtio13' => { bus => 2, addr => 8 },
3550 'virtio14' => { bus => 2, addr => 9 },
3551 'virtio15' => { bus => 2, addr => 10 },
3552 };
3553
3554 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
3555 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
3556 my $bus = $devices->{$id}->{bus};
3557 $res = ",bus=pci.$bus,addr=$addr";
3558 $bridges->{$bus} = 1 if $bridges;
3559 }
3560 return $res;
3561
3562}
3563
3564# vzdump restore implementaion
3565
3566sub tar_archive_read_firstfile {
3567 my $archive = shift;
3568
3569 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
3570
3571 # try to detect archive type first
3572 my $pid = open (TMP, "tar tf '$archive'|") ||
3573 die "unable to open file '$archive'\n";
3574 my $firstfile = <TMP>;
3575 kill 15, $pid;
3576 close TMP;
3577
3578 die "ERROR: archive contaions no data\n" if !$firstfile;
3579 chomp $firstfile;
3580
3581 return $firstfile;
3582}
3583
3584sub tar_restore_cleanup {
3585 my ($storecfg, $statfile) = @_;
3586
3587 print STDERR "starting cleanup\n";
3588
3589 if (my $fd = IO::File->new($statfile, "r")) {
3590 while (defined(my $line = <$fd>)) {
3591 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3592 my $volid = $2;
3593 eval {
3594 if ($volid =~ m|^/|) {
3595 unlink $volid || die 'unlink failed\n';
3596 } else {
3597 PVE::Storage::vdisk_free($storecfg, $volid);
3598 }
3599 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3600 };
3601 print STDERR "unable to cleanup '$volid' - $@" if $@;
3602 } else {
3603 print STDERR "unable to parse line in statfile - $line";
3604 }
3605 }
3606 $fd->close();
3607 }
3608}
3609
3610sub restore_archive {
3611 my ($archive, $vmid, $user, $opts) = @_;
3612
3613 my $format = $opts->{format};
3614 my $comp;
3615
3616 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3617 $format = 'tar' if !$format;
3618 $comp = 'gzip';
3619 } elsif ($archive =~ m/\.tar$/) {
3620 $format = 'tar' if !$format;
3621 } elsif ($archive =~ m/.tar.lzo$/) {
3622 $format = 'tar' if !$format;
3623 $comp = 'lzop';
3624 } elsif ($archive =~ m/\.vma$/) {
3625 $format = 'vma' if !$format;
3626 } elsif ($archive =~ m/\.vma\.gz$/) {
3627 $format = 'vma' if !$format;
3628 $comp = 'gzip';
3629 } elsif ($archive =~ m/\.vma\.lzo$/) {
3630 $format = 'vma' if !$format;
3631 $comp = 'lzop';
3632 } else {
3633 $format = 'vma' if !$format; # default
3634 }
3635
3636 # try to detect archive format
3637 if ($format eq 'tar') {
3638 return restore_tar_archive($archive, $vmid, $user, $opts);
3639 } else {
3640 return restore_vma_archive($archive, $vmid, $user, $opts, $comp);
3641 }
3642}
3643
3644sub restore_update_config_line {
3645 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3646
3647 return if $line =~ m/^\#qmdump\#/;
3648 return if $line =~ m/^\#vzdump\#/;
3649 return if $line =~ m/^lock:/;
3650 return if $line =~ m/^unused\d+:/;
3651 return if $line =~ m/^parent:/;
3652 return if $line =~ m/^template:/; # restored VM is never a template
3653
3654 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3655 # try to convert old 1.X settings
3656 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3657 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
3658 my ($model, $macaddr) = split(/\=/, $devconfig);
3659 $macaddr = PVE::Tools::random_ether_addr() if !$macaddr || $unique;
3660 my $net = {
3661 model => $model,
3662 bridge => "vmbr$ind",
3663 macaddr => $macaddr,
3664 };
3665 my $netstr = print_net($net);
3666
3667 print $outfd "net$cookie->{netcount}: $netstr\n";
3668 $cookie->{netcount}++;
3669 }
3670 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3671 my ($id, $netstr) = ($1, $2);
3672 my $net = parse_net($netstr);
3673 $net->{macaddr} = PVE::Tools::random_ether_addr() if $net->{macaddr};
3674 $netstr = print_net($net);
3675 print $outfd "$id: $netstr\n";
3676 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3677 my $virtdev = $1;
3678 my $value = $3;
3679 if ($line =~ m/backup=no/) {
3680 print $outfd "#$line";
3681 } elsif ($virtdev && $map->{$virtdev}) {
3682 my $di = parse_drive($virtdev, $value);
3683 delete $di->{format}; # format can change on restore
3684 $di->{file} = $map->{$virtdev};
3685 $value = print_drive($vmid, $di);
3686 print $outfd "$virtdev: $value\n";
3687 } else {
3688 print $outfd $line;
3689 }
3690 } else {
3691 print $outfd $line;
3692 }
3693}
3694
3695sub scan_volids {
3696 my ($cfg, $vmid) = @_;
3697
3698 my $info = PVE::Storage::vdisk_list($cfg, undef, $vmid);
3699
3700 my $volid_hash = {};
3701 foreach my $storeid (keys %$info) {
3702 foreach my $item (@{$info->{$storeid}}) {
3703 next if !($item->{volid} && $item->{size});
3704 $item->{path} = PVE::Storage::path($cfg, $item->{volid});
3705 $volid_hash->{$item->{volid}} = $item;
3706 }
3707 }
3708
3709 return $volid_hash;
3710}
3711
3712sub get_used_paths {
3713 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3714
3715 my $used_path = {};
3716
3717 my $scan_config = sub {
3718 my ($cref, $snapname) = @_;
3719
3720 foreach my $key (keys %$cref) {
3721 my $value = $cref->{$key};
3722 if (valid_drivename($key)) {
3723 next if $skip_drive && $key eq $skip_drive;
3724 my $drive = parse_drive($key, $value);
3725 next if !$drive || !$drive->{file} || drive_is_cdrom($drive);
3726 if ($drive->{file} =~ m!^/!) {
3727 $used_path->{$drive->{file}}++; # = 1;
3728 } else {
3729 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
3730 next if !$storeid;
3731 my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1);
3732 next if !$scfg;
3733 my $path = PVE::Storage::path($storecfg, $drive->{file}, $snapname);
3734 $used_path->{$path}++; # = 1;
3735 }
3736 }
3737 }
3738 };
3739
3740 &$scan_config($conf);
3741
3742 undef $skip_drive;
3743
3744 if ($scan_snapshots) {
3745 foreach my $snapname (keys %{$conf->{snapshots}}) {
3746 &$scan_config($conf->{snapshots}->{$snapname}, $snapname);
3747 }
3748 }
3749
3750 return $used_path;
3751}
3752
3753sub update_disksize {
3754 my ($vmid, $conf, $volid_hash) = @_;
3755
3756 my $changes;
3757
3758 my $used = {};
3759
3760 # Note: it is allowed to define multiple storages with same path (alias), so
3761 # we need to check both 'volid' and real 'path' (two different volid can point
3762 # to the same path).
3763
3764 my $usedpath = {};
3765
3766 # update size info
3767 foreach my $opt (keys %$conf) {
3768 if (valid_drivename($opt)) {
3769 my $drive = parse_drive($opt, $conf->{$opt});
3770 my $volid = $drive->{file};
3771 next if !$volid;
3772
3773 $used->{$volid} = 1;
3774 if ($volid_hash->{$volid} &&
3775 (my $path = $volid_hash->{$volid}->{path})) {
3776 $usedpath->{$path} = 1;
3777 }
3778
3779 next if drive_is_cdrom($drive);
3780 next if !$volid_hash->{$volid};
3781
3782 $drive->{size} = $volid_hash->{$volid}->{size};
3783 my $new = print_drive($vmid, $drive);
3784 if ($new ne $conf->{$opt}) {
3785 $changes = 1;
3786 $conf->{$opt} = $new;
3787 }
3788 }
3789 }
3790
3791 # remove 'unusedX' entry if volume is used
3792 foreach my $opt (keys %$conf) {
3793 next if $opt !~ m/^unused\d+$/;
3794 my $volid = $conf->{$opt};
3795 my $path = $volid_hash->{$volid}->{path} if $volid_hash->{$volid};
3796 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3797 $changes = 1;
3798 delete $conf->{$opt};
3799 }
3800 }
3801
3802 foreach my $volid (sort keys %$volid_hash) {
3803 next if $volid =~ m/vm-$vmid-state-/;
3804 next if $used->{$volid};
3805 my $path = $volid_hash->{$volid}->{path};
3806 next if !$path; # just to be sure
3807 next if $usedpath->{$path};
3808 $changes = 1;
3809 add_unused_volume($conf, $volid);
3810 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3811 }
3812
3813 return $changes;
3814}
3815
3816sub rescan {
3817 my ($vmid, $nolock) = @_;
3818
3819 my $cfg = PVE::Cluster::cfs_read_file("storage.cfg");
3820
3821 my $volid_hash = scan_volids($cfg, $vmid);
3822
3823 my $updatefn = sub {
3824 my ($vmid) = @_;
3825
3826 my $conf = load_config($vmid);
3827
3828 check_lock($conf);
3829
3830 my $vm_volids = {};
3831 foreach my $volid (keys %$volid_hash) {
3832 my $info = $volid_hash->{$volid};
3833 $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
3834 }
3835
3836 my $changes = update_disksize($vmid, $conf, $vm_volids);
3837
3838 update_config_nolock($vmid, $conf, 1) if $changes;
3839 };
3840
3841 if (defined($vmid)) {
3842 if ($nolock) {
3843 &$updatefn($vmid);
3844 } else {
3845 lock_config($vmid, $updatefn, $vmid);
3846 }
3847 } else {
3848 my $vmlist = config_list();
3849 foreach my $vmid (keys %$vmlist) {
3850 if ($nolock) {
3851 &$updatefn($vmid);
3852 } else {
3853 lock_config($vmid, $updatefn, $vmid);
3854 }
3855 }
3856 }
3857}
3858
3859sub restore_vma_archive {
3860 my ($archive, $vmid, $user, $opts, $comp) = @_;
3861
3862 my $input = $archive eq '-' ? "<&STDIN" : undef;
3863 my $readfrom = $archive;
3864
3865 my $uncomp = '';
3866 if ($comp) {
3867 $readfrom = '-';
3868 my $qarchive = PVE::Tools::shellquote($archive);
3869 if ($comp eq 'gzip') {
3870 $uncomp = "zcat $qarchive|";
3871 } elsif ($comp eq 'lzop') {
3872 $uncomp = "lzop -d -c $qarchive|";
3873 } else {
3874 die "unknown compression method '$comp'\n";
3875 }
3876
3877 }
3878
3879 my $tmpdir = "/var/tmp/vzdumptmp$$";
3880 rmtree $tmpdir;
3881
3882 # disable interrupts (always do cleanups)
3883 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
3884 warn "got interrupt - ignored\n";
3885 };
3886
3887 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3888 POSIX::mkfifo($mapfifo, 0600);
3889 my $fifofh;
3890
3891 my $openfifo = sub {
3892 open($fifofh, '>', $mapfifo) || die $!;
3893 };
3894
3895 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3896
3897 my $oldtimeout;
3898 my $timeout = 5;
3899
3900 my $devinfo = {};
3901
3902 my $rpcenv = PVE::RPCEnvironment::get();
3903
3904 my $conffile = config_file($vmid);
3905 my $tmpfn = "$conffile.$$.tmp";
3906
3907 # Note: $oldconf is undef if VM does not exists
3908 my $oldconf = PVE::Cluster::cfs_read_file(cfs_config_path($vmid));
3909
3910 my $print_devmap = sub {
3911 my $virtdev_hash = {};
3912
3913 my $cfgfn = "$tmpdir/qemu-server.conf";
3914
3915 # we can read the config - that is already extracted
3916 my $fh = IO::File->new($cfgfn, "r") ||
3917 "unable to read qemu-server.conf - $!\n";
3918
3919 while (defined(my $line = <$fh>)) {
3920 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3921 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3922 die "archive does not contain data for drive '$virtdev'\n"
3923 if !$devinfo->{$devname};
3924 if (defined($opts->{storage})) {
3925 $storeid = $opts->{storage} || 'local';
3926 } elsif (!$storeid) {
3927 $storeid = 'local';
3928 }
3929 $format = 'raw' if !$format;
3930 $devinfo->{$devname}->{devname} = $devname;
3931 $devinfo->{$devname}->{virtdev} = $virtdev;
3932 $devinfo->{$devname}->{format} = $format;
3933 $devinfo->{$devname}->{storeid} = $storeid;
3934
3935 # check permission on storage
3936 my $pool = $opts->{pool}; # todo: do we need that?
3937 if ($user ne 'root@pam') {
3938 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3939 }
3940
3941 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3942 }
3943 }
3944
3945 foreach my $devname (keys %$devinfo) {
3946 die "found no device mapping information for device '$devname'\n"
3947 if !$devinfo->{$devname}->{virtdev};
3948 }
3949
3950 my $cfg = cfs_read_file('storage.cfg');
3951
3952 # create empty/temp config
3953 if ($oldconf) {
3954 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
3955 foreach_drive($oldconf, sub {
3956 my ($ds, $drive) = @_;
3957
3958 return if drive_is_cdrom($drive);
3959
3960 my $volid = $drive->{file};
3961
3962 return if !$volid || $volid =~ m|^/|;
3963
3964 my ($path, $owner) = PVE::Storage::path($cfg, $volid);
3965 return if !$path || !$owner || ($owner != $vmid);
3966
3967 # Note: only delete disk we want to restore
3968 # other volumes will become unused
3969 if ($virtdev_hash->{$ds}) {
3970 PVE::Storage::vdisk_free($cfg, $volid);
3971 }
3972 });
3973 }
3974
3975 my $map = {};
3976 foreach my $virtdev (sort keys %$virtdev_hash) {
3977 my $d = $virtdev_hash->{$virtdev};
3978 my $alloc_size = int(($d->{size} + 1024 - 1)/1024);
3979 my $scfg = PVE::Storage::storage_config($cfg, $d->{storeid});
3980
3981 # test if requested format is supported
3982 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($cfg, $d->{storeid});
3983 my $supported = grep { $_ eq $d->{format} } @$validFormats;
3984 $d->{format} = $defFormat if !$supported;
3985
3986 my $volid = PVE::Storage::vdisk_alloc($cfg, $d->{storeid}, $vmid,
3987 $d->{format}, undef, $alloc_size);
3988 print STDERR "new volume ID is '$volid'\n";
3989 $d->{volid} = $volid;
3990 my $path = PVE::Storage::path($cfg, $volid);
3991
3992 my $write_zeros = 1;
3993 # fixme: what other storages types initialize volumes with zero?
3994 if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs' ||
3995 $scfg->{type} eq 'sheepdog' || $scfg->{type} eq 'rbd') {
3996 $write_zeros = 0;
3997 }
3998
3999 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4000
4001 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4002 $map->{$virtdev} = $volid;
4003 }
4004
4005 $fh->seek(0, 0) || die "seek failed - $!\n";
4006
4007 my $outfd = new IO::File ($tmpfn, "w") ||
4008 die "unable to write config for VM $vmid\n";
4009
4010 my $cookie = { netcount => 0 };
4011 while (defined(my $line = <$fh>)) {
4012 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
4013 }
4014
4015 $fh->close();
4016 $outfd->close();
4017 };
4018
4019 eval {
4020 # enable interrupts
4021 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
4022 die "interrupted by signal\n";
4023 };
4024 local $SIG{ALRM} = sub { die "got timeout\n"; };
4025
4026 $oldtimeout = alarm($timeout);
4027
4028 my $parser = sub {
4029 my $line = shift;
4030
4031 print "$line\n";
4032
4033 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4034 my ($dev_id, $size, $devname) = ($1, $2, $3);
4035 $devinfo->{$devname} = { size => $size, dev_id => $dev_id };
4036 } elsif ($line =~ m/^CTIME: /) {
4037 &$print_devmap();
4038 print $fifofh "done\n";
4039 my $tmp = $oldtimeout || 0;
4040 $oldtimeout = undef;
4041 alarm($tmp);
4042 close($fifofh);
4043 }
4044 };
4045
4046 print "restore vma archive: $cmd\n";
4047 run_command($cmd, input => $input, outfunc => $parser, afterfork => $openfifo);
4048 };
4049 my $err = $@;
4050
4051 alarm($oldtimeout) if $oldtimeout;
4052
4053 unlink $mapfifo;
4054
4055 if ($err) {
4056 rmtree $tmpdir;
4057 unlink $tmpfn;
4058
4059 my $cfg = cfs_read_file('storage.cfg');
4060 foreach my $devname (keys %$devinfo) {
4061 my $volid = $devinfo->{$devname}->{volid};
4062 next if !$volid;
4063 eval {
4064 if ($volid =~ m|^/|) {
4065 unlink $volid || die 'unlink failed\n';
4066 } else {
4067 PVE::Storage::vdisk_free($cfg, $volid);
4068 }
4069 print STDERR "temporary volume '$volid' sucessfuly removed\n";
4070 };
4071 print STDERR "unable to cleanup '$volid' - $@" if $@;
4072 }
4073 die $err;
4074 }
4075
4076 rmtree $tmpdir;
4077
4078 rename($tmpfn, $conffile) ||
4079 die "unable to commit configuration file '$conffile'\n";
4080
4081 PVE::Cluster::cfs_update(); # make sure we read new file
4082
4083 eval { rescan($vmid, 1); };
4084 warn $@ if $@;
4085}
4086
4087sub restore_tar_archive {
4088 my ($archive, $vmid, $user, $opts) = @_;
4089
4090 if ($archive ne '-') {
4091 my $firstfile = tar_archive_read_firstfile($archive);
4092 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4093 if $firstfile ne 'qemu-server.conf';
4094 }
4095
4096 my $storecfg = cfs_read_file('storage.cfg');
4097
4098 # destroy existing data - keep empty config
4099 my $vmcfgfn = PVE::QemuServer::config_file($vmid);
4100 destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
4101
4102 my $tocmd = "/usr/lib/qemu-server/qmextract";
4103
4104 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
4105 $tocmd .= " --pool " . PVE::Tools::shellquote($opts->{pool}) if $opts->{pool};
4106 $tocmd .= ' --prealloc' if $opts->{prealloc};
4107 $tocmd .= ' --info' if $opts->{info};
4108
4109 # tar option "xf" does not autodetect compression when read from STDIN,
4110 # so we pipe to zcat
4111 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
4112 PVE::Tools::shellquote("--to-command=$tocmd");
4113
4114 my $tmpdir = "/var/tmp/vzdumptmp$$";
4115 mkpath $tmpdir;
4116
4117 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
4118 local $ENV{VZDUMP_VMID} = $vmid;
4119 local $ENV{VZDUMP_USER} = $user;
4120
4121 my $conffile = config_file($vmid);
4122 my $tmpfn = "$conffile.$$.tmp";
4123
4124 # disable interrupts (always do cleanups)
4125 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
4126 print STDERR "got interrupt - ignored\n";
4127 };
4128
4129 eval {
4130 # enable interrupts
4131 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
4132 die "interrupted by signal\n";
4133 };
4134
4135 if ($archive eq '-') {
4136 print "extracting archive from STDIN\n";
4137 run_command($cmd, input => "<&STDIN");
4138 } else {
4139 print "extracting archive '$archive'\n";
4140 run_command($cmd);
4141 }
4142
4143 return if $opts->{info};
4144
4145 # read new mapping
4146 my $map = {};
4147 my $statfile = "$tmpdir/qmrestore.stat";
4148 if (my $fd = IO::File->new($statfile, "r")) {
4149 while (defined (my $line = <$fd>)) {
4150 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4151 $map->{$1} = $2 if $1;
4152 } else {
4153 print STDERR "unable to parse line in statfile - $line\n";
4154 }
4155 }
4156 $fd->close();
4157 }
4158
4159 my $confsrc = "$tmpdir/qemu-server.conf";
4160
4161 my $srcfd = new IO::File($confsrc, "r") ||
4162 die "unable to open file '$confsrc'\n";
4163
4164 my $outfd = new IO::File ($tmpfn, "w") ||
4165 die "unable to write config for VM $vmid\n";
4166
4167 my $cookie = { netcount => 0 };
4168 while (defined (my $line = <$srcfd>)) {
4169 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
4170 }
4171
4172 $srcfd->close();
4173 $outfd->close();
4174 };
4175 my $err = $@;
4176
4177 if ($err) {
4178
4179 unlink $tmpfn;
4180
4181 tar_restore_cleanup($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info};
4182
4183 die $err;
4184 }
4185
4186 rmtree $tmpdir;
4187
4188 rename $tmpfn, $conffile ||
4189 die "unable to commit configuration file '$conffile'\n";
4190
4191 PVE::Cluster::cfs_update(); # make sure we read new file
4192
4193 eval { rescan($vmid, 1); };
4194 warn $@ if $@;
4195};
4196
4197
4198# Internal snapshots
4199
4200# NOTE: Snapshot create/delete involves several non-atomic
4201# action, and can take a long time.
4202# So we try to avoid locking the file and use 'lock' variable
4203# inside the config file instead.
4204
4205my $snapshot_copy_config = sub {
4206 my ($source, $dest) = @_;
4207
4208 foreach my $k (keys %$source) {
4209 next if $k eq 'snapshots';
4210 next if $k eq 'snapstate';
4211 next if $k eq 'snaptime';
4212 next if $k eq 'vmstate';
4213 next if $k eq 'lock';
4214 next if $k eq 'digest';
4215 next if $k eq 'description';
4216 next if $k =~ m/^unused\d+$/;
4217
4218 $dest->{$k} = $source->{$k};
4219 }
4220};
4221
4222my $snapshot_apply_config = sub {
4223 my ($conf, $snap) = @_;
4224
4225 # copy snapshot list
4226 my $newconf = {
4227 snapshots => $conf->{snapshots},
4228 };
4229
4230 # keep description and list of unused disks
4231 foreach my $k (keys %$conf) {
4232 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4233 $newconf->{$k} = $conf->{$k};
4234 }
4235
4236 &$snapshot_copy_config($snap, $newconf);
4237
4238 return $newconf;
4239};
4240
4241sub foreach_writable_storage {
4242 my ($conf, $func) = @_;
4243
4244 my $sidhash = {};
4245
4246 foreach my $ds (keys %$conf) {
4247 next if !valid_drivename($ds);
4248
4249 my $drive = parse_drive($ds, $conf->{$ds});
4250 next if !$drive;
4251 next if drive_is_cdrom($drive);
4252
4253 my $volid = $drive->{file};
4254
4255 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4256 $sidhash->{$sid} = $sid if $sid;
4257 }
4258
4259 foreach my $sid (sort keys %$sidhash) {
4260 &$func($sid);
4261 }
4262}
4263
4264my $alloc_vmstate_volid = sub {
4265 my ($storecfg, $vmid, $conf, $snapname) = @_;
4266
4267 # Note: we try to be smart when selecting a $target storage
4268
4269 my $target;
4270
4271 # search shared storage first
4272 foreach_writable_storage($conf, sub {
4273 my ($sid) = @_;
4274 my $scfg = PVE::Storage::storage_config($storecfg, $sid);
4275 return if !$scfg->{shared};
4276
4277 $target = $sid if !$target || $scfg->{path}; # prefer file based storage
4278 });
4279
4280 if (!$target) {
4281 # now search local storage
4282 foreach_writable_storage($conf, sub {
4283 my ($sid) = @_;
4284 my $scfg = PVE::Storage::storage_config($storecfg, $sid);
4285 return if $scfg->{shared};
4286
4287 $target = $sid if !$target || $scfg->{path}; # prefer file based storage;
4288 });
4289 }
4290
4291 $target = 'local' if !$target;
4292
4293 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4294 # we abort live save after $conf->{memory}, so we need at max twice that space
4295 my $size = $conf->{memory}*2 + $driver_state_size;
4296
4297 my $name = "vm-$vmid-state-$snapname";
4298 my $scfg = PVE::Storage::storage_config($storecfg, $target);
4299 $name .= ".raw" if $scfg->{path}; # add filename extension for file base storage
4300 my $volid = PVE::Storage::vdisk_alloc($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4301
4302 return $volid;
4303};
4304
4305my $snapshot_prepare = sub {
4306 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4307
4308 my $snap;
4309
4310 my $updatefn = sub {
4311
4312 my $conf = load_config($vmid);
4313
4314 die "you can't take a snapshot if it's a template\n"
4315 if is_template($conf);
4316
4317 check_lock($conf);
4318
4319 $conf->{lock} = 'snapshot';
4320
4321 die "snapshot name '$snapname' already used\n"
4322 if defined($conf->{snapshots}->{$snapname});
4323
4324 my $storecfg = PVE::Storage::config();
4325 die "snapshot feature is not available" if !has_feature('snapshot', $conf, $storecfg);
4326
4327 $snap = $conf->{snapshots}->{$snapname} = {};
4328
4329 if ($save_vmstate && check_running($vmid)) {
4330 $snap->{vmstate} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4331 }
4332
4333 &$snapshot_copy_config($conf, $snap);
4334
4335 $snap->{snapstate} = "prepare";
4336 $snap->{snaptime} = time();
4337 $snap->{description} = $comment if $comment;
4338
4339 # always overwrite machine if we save vmstate. This makes sure we
4340 # can restore it later using correct machine type
4341 $snap->{machine} = get_current_qemu_machine($vmid) if $snap->{vmstate};
4342
4343 update_config_nolock($vmid, $conf, 1);
4344 };
4345
4346 lock_config($vmid, $updatefn);
4347
4348 return $snap;
4349};
4350
4351my $snapshot_commit = sub {
4352 my ($vmid, $snapname) = @_;
4353
4354 my $updatefn = sub {
4355
4356 my $conf = load_config($vmid);
4357
4358 die "missing snapshot lock\n"
4359 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4360
4361 my $snap = $conf->{snapshots}->{$snapname};
4362
4363 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4364
4365 die "wrong snapshot state\n"
4366 if !($snap->{snapstate} && $snap->{snapstate} eq "prepare");
4367
4368 delete $snap->{snapstate};
4369 delete $conf->{lock};
4370
4371 my $newconf = &$snapshot_apply_config($conf, $snap);
4372
4373 $newconf->{parent} = $snapname;
4374
4375 update_config_nolock($vmid, $newconf, 1);
4376 };
4377
4378 lock_config($vmid, $updatefn);
4379};
4380
4381sub snapshot_rollback {
4382 my ($vmid, $snapname) = @_;
4383
4384 my $snap;
4385
4386 my $prepare = 1;
4387
4388 my $storecfg = PVE::Storage::config();
4389
4390 my $updatefn = sub {
4391
4392 my $conf = load_config($vmid);
4393
4394 die "you can't rollback if vm is a template\n" if is_template($conf);
4395
4396 $snap = $conf->{snapshots}->{$snapname};
4397
4398 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4399
4400 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4401 if $snap->{snapstate};
4402
4403 if ($prepare) {
4404 check_lock($conf);
4405 vm_stop($storecfg, $vmid, undef, undef, 5, undef, undef);
4406 }
4407
4408 die "unable to rollback vm $vmid: vm is running\n"
4409 if check_running($vmid);
4410
4411 if ($prepare) {
4412 $conf->{lock} = 'rollback';
4413 } else {
4414 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4415 delete $conf->{lock};
4416 }
4417
4418 my $forcemachine;
4419
4420 if (!$prepare) {
4421 my $has_machine_config = defined($conf->{machine});
4422
4423 # copy snapshot config to current config
4424 $conf = &$snapshot_apply_config($conf, $snap);
4425 $conf->{parent} = $snapname;
4426
4427 # Note: old code did not store 'machine', so we try to be smart
4428 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4429 $forcemachine = $conf->{machine} || 'pc-i440fx-1.4';
4430 # we remove the 'machine' configuration if not explicitly specified
4431 # in the original config.
4432 delete $conf->{machine} if $snap->{vmstate} && !$has_machine_config;
4433 }
4434
4435 update_config_nolock($vmid, $conf, 1);
4436
4437 if (!$prepare && $snap->{vmstate}) {
4438 my $statefile = PVE::Storage::path($storecfg, $snap->{vmstate});
4439 vm_start($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4440 }
4441 };
4442
4443 lock_config($vmid, $updatefn);
4444
4445 foreach_drive($snap, sub {
4446 my ($ds, $drive) = @_;
4447
4448 return if drive_is_cdrom($drive);
4449
4450 my $volid = $drive->{file};
4451 my $device = "drive-$ds";
4452
4453 PVE::Storage::volume_snapshot_rollback($storecfg, $volid, $snapname);
4454 });
4455
4456 $prepare = 0;
4457 lock_config($vmid, $updatefn);
4458}
4459
4460my $savevm_wait = sub {
4461 my ($vmid) = @_;
4462
4463 for(;;) {
4464 my $stat = vm_mon_cmd_nocheck($vmid, "query-savevm");
4465 if (!$stat->{status}) {
4466 die "savevm not active\n";
4467 } elsif ($stat->{status} eq 'active') {
4468 sleep(1);
4469 next;
4470 } elsif ($stat->{status} eq 'completed') {
4471 last;
4472 } else {
4473 die "query-savevm returned status '$stat->{status}'\n";
4474 }
4475 }
4476};
4477
4478sub snapshot_create {
4479 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4480
4481 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4482
4483 $freezefs = $save_vmstate = 0 if !$snap->{vmstate}; # vm is not running
4484
4485 my $drivehash = {};
4486
4487 my $running = check_running($vmid);
4488
4489 eval {
4490 # create internal snapshots of all drives
4491
4492 my $storecfg = PVE::Storage::config();
4493
4494 if ($running) {
4495 if ($snap->{vmstate}) {
4496 my $path = PVE::Storage::path($storecfg, $snap->{vmstate});
4497 vm_mon_cmd($vmid, "savevm-start", statefile => $path);
4498 &$savevm_wait($vmid);
4499 } else {
4500 vm_mon_cmd($vmid, "savevm-start");
4501 }
4502 };
4503
4504 qga_freezefs($vmid) if $running && $freezefs;
4505
4506 foreach_drive($snap, sub {
4507 my ($ds, $drive) = @_;
4508
4509 return if drive_is_cdrom($drive);
4510
4511 my $volid = $drive->{file};
4512 my $device = "drive-$ds";
4513
4514 qemu_volume_snapshot($vmid, $device, $storecfg, $volid, $snapname);
4515 $drivehash->{$ds} = 1;
4516 });
4517 };
4518 my $err = $@;
4519
4520 eval { qga_unfreezefs($vmid) if $running && $freezefs; };
4521 warn $@ if $@;
4522
4523 eval { vm_mon_cmd($vmid, "savevm-end") if $running; };
4524 warn $@ if $@;
4525
4526 if ($err) {
4527 warn "snapshot create failed: starting cleanup\n";
4528 eval { snapshot_delete($vmid, $snapname, 0, $drivehash); };
4529 warn $@ if $@;
4530 die $err;
4531 }
4532
4533 &$snapshot_commit($vmid, $snapname);
4534}
4535
4536# Note: $drivehash is only set when called from snapshot_create.
4537sub snapshot_delete {
4538 my ($vmid, $snapname, $force, $drivehash) = @_;
4539
4540 my $prepare = 1;
4541
4542 my $snap;
4543 my $unused = [];
4544
4545 my $unlink_parent = sub {
4546 my ($confref, $new_parent) = @_;
4547
4548 if ($confref->{parent} && $confref->{parent} eq $snapname) {
4549 if ($new_parent) {
4550 $confref->{parent} = $new_parent;
4551 } else {
4552 delete $confref->{parent};
4553 }
4554 }
4555 };
4556
4557 my $updatefn = sub {
4558 my ($remove_drive) = @_;
4559
4560 my $conf = load_config($vmid);
4561
4562 if (!$drivehash) {
4563 check_lock($conf);
4564 die "you can't delete a snapshot if vm is a template\n"
4565 if is_template($conf);
4566 }
4567
4568 $snap = $conf->{snapshots}->{$snapname};
4569
4570 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4571
4572 # remove parent refs
4573 &$unlink_parent($conf, $snap->{parent});
4574 foreach my $sn (keys %{$conf->{snapshots}}) {
4575 next if $sn eq $snapname;
4576 &$unlink_parent($conf->{snapshots}->{$sn}, $snap->{parent});
4577 }
4578
4579 if ($remove_drive) {
4580 if ($remove_drive eq 'vmstate') {
4581 delete $snap->{$remove_drive};
4582 } else {
4583 my $drive = parse_drive($remove_drive, $snap->{$remove_drive});
4584 my $volid = $drive->{file};
4585 delete $snap->{$remove_drive};
4586 add_unused_volume($conf, $volid);
4587 }
4588 }
4589
4590 if ($prepare) {
4591 $snap->{snapstate} = 'delete';
4592 } else {
4593 delete $conf->{snapshots}->{$snapname};
4594 delete $conf->{lock} if $drivehash;
4595 foreach my $volid (@$unused) {
4596 add_unused_volume($conf, $volid);
4597 }
4598 }
4599
4600 update_config_nolock($vmid, $conf, 1);
4601 };
4602
4603 lock_config($vmid, $updatefn);
4604
4605 # now remove vmstate file
4606
4607 my $storecfg = PVE::Storage::config();
4608
4609 if ($snap->{vmstate}) {
4610 eval { PVE::Storage::vdisk_free($storecfg, $snap->{vmstate}); };
4611 if (my $err = $@) {
4612 die $err if !$force;
4613 warn $err;
4614 }
4615 # save changes (remove vmstate from snapshot)
4616 lock_config($vmid, $updatefn, 'vmstate') if !$force;
4617 };
4618
4619 # now remove all internal snapshots
4620 foreach_drive($snap, sub {
4621 my ($ds, $drive) = @_;
4622
4623 return if drive_is_cdrom($drive);
4624
4625 my $volid = $drive->{file};
4626 my $device = "drive-$ds";
4627
4628 if (!$drivehash || $drivehash->{$ds}) {
4629 eval { qemu_volume_snapshot_delete($vmid, $device, $storecfg, $volid, $snapname); };
4630 if (my $err = $@) {
4631 die $err if !$force;
4632 warn $err;
4633 }
4634 }
4635
4636 # save changes (remove drive fron snapshot)
4637 lock_config($vmid, $updatefn, $ds) if !$force;
4638 push @$unused, $volid;
4639 });
4640
4641 # now cleanup config
4642 $prepare = 0;
4643 lock_config($vmid, $updatefn);
4644}
4645
4646sub has_feature {
4647 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4648
4649 my $err;
4650 foreach_drive($conf, sub {
4651 my ($ds, $drive) = @_;
4652
4653 return if drive_is_cdrom($drive);
4654 my $volid = $drive->{file};
4655 $err = 1 if !PVE::Storage::volume_has_feature($storecfg, $feature, $volid, $snapname, $running);
4656 });
4657
4658 return $err ? 0 : 1;
4659}
4660
4661sub template_create {
4662 my ($vmid, $conf, $disk) = @_;
4663
4664 my $storecfg = PVE::Storage::config();
4665
4666 foreach_drive($conf, sub {
4667 my ($ds, $drive) = @_;
4668
4669 return if drive_is_cdrom($drive);
4670 return if $disk && $ds ne $disk;
4671
4672 my $volid = $drive->{file};
4673 return if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
4674
4675 my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
4676 $drive->{file} = $voliddst;
4677 $conf->{$ds} = print_drive($vmid, $drive);
4678 update_config_nolock($vmid, $conf, 1);
4679 });
4680}
4681
4682sub is_template {
4683 my ($conf) = @_;
4684
4685 return 1 if defined $conf->{template} && $conf->{template} == 1;
4686}
4687
4688sub qemu_img_convert {
4689 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4690
4691 my $storecfg = PVE::Storage::config();
4692 my ($src_storeid, $src_volname) = PVE::Storage::parse_volume_id($src_volid, 1);
4693 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
4694
4695 if ($src_storeid && $dst_storeid) {
4696 my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
4697 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
4698
4699 my $src_format = qemu_img_format($src_scfg, $src_volname);
4700 my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
4701
4702 my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
4703 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
4704
4705 my $cmd = [];
4706 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-C';
4707 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4708 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4709
4710 my $parser = sub {
4711 my $line = shift;
4712 if($line =~ m/\((\S+)\/100\%\)/){
4713 my $percent = $1;
4714 my $transferred = int($size * $percent / 100);
4715 my $remaining = $size - $transferred;
4716
4717 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4718 }
4719
4720 };
4721
4722 eval { run_command($cmd, timeout => undef, outfunc => $parser); };
4723 my $err = $@;
4724 die "copy failed: $err" if $err;
4725 }
4726}
4727
4728sub qemu_img_format {
4729 my ($scfg, $volname) = @_;
4730
4731 if ($scfg->{path} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4732 return $1;
4733 } elsif ($scfg->{type} eq 'iscsi') {
4734 return "host_device";
4735 } else {
4736 return "raw";
4737 }
4738}
4739
4740sub qemu_drive_mirror {
4741 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4742
4743 my $count = 1;
4744 my $old_len = 0;
4745 my $frozen = undef;
4746
4747 my $storecfg = PVE::Storage::config();
4748 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
4749
4750 if ($dst_storeid) {
4751 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
4752
4753 my $format;
4754 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4755 $format = $1;
4756 }
4757
4758 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
4759
4760 if ($format) {
4761 #fixme : sometime drive-mirror timeout, but works fine after.
4762 # (I have see the problem with big volume > 200GB), so we need to eval
4763 eval { vm_mon_cmd($vmid, "drive-mirror", timeout => 10, device => "drive-$drive", mode => "existing",
4764 sync => "full", target => $dst_path, format => $format); };
4765 } else {
4766 eval { vm_mon_cmd($vmid, "drive-mirror", timeout => 10, device => "drive-$drive", mode => "existing",
4767 sync => "full", target => $dst_path); };
4768 }
4769
4770 eval {
4771 while (1) {
4772 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
4773 my $stat = @$stats[0];
4774 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4775 die "error job is not mirroring" if $stat->{type} ne "mirror";
4776
4777 my $transferred = $stat->{offset};
4778 my $total = $stat->{len};
4779 my $remaining = $total - $transferred;
4780 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4781
4782 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4783
4784 last if ($stat->{len} == $stat->{offset});
4785 if ($old_len == $stat->{offset}) {
4786 if ($maxwait && $count > $maxwait) {
4787 # if writes to disk occurs the disk needs to be freezed
4788 # to be able to complete the migration
4789 vm_suspend($vmid,1);
4790 $count = 0;
4791 $frozen = 1;
4792 } else {
4793 $count++ unless $frozen;
4794 }
4795 } elsif ($frozen) {
4796 vm_resume($vmid,1);
4797 $count = 0;
4798 }
4799 $old_len = $stat->{offset};
4800 sleep 1;
4801 }
4802
4803 if ($vmiddst == $vmid) {
4804 # switch the disk if source and destination are on the same guest
4805 vm_mon_cmd($vmid, "block-job-complete", device => "drive-$drive");
4806 }
4807 };
4808 if (my $err = $@) {
4809 eval { vm_mon_cmd($vmid, "block-job-cancel", device => "drive-$drive"); };
4810 die "mirroring error: $err";
4811 }
4812
4813 if ($vmiddst != $vmid) {
4814 # if we clone a disk for a new target vm, we don't switch the disk
4815 vm_mon_cmd($vmid, "block-job-cancel", device => "drive-$drive");
4816 }
4817 }
4818}
4819
4820sub clone_disk {
4821 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4822 $newvmid, $storage, $format, $full, $newvollist) = @_;
4823
4824 my $newvolid;
4825
4826 if (!$full) {
4827 print "create linked clone of drive $drivename ($drive->{file})\n";
4828 $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid);
4829 push @$newvollist, $newvolid;
4830 } else {
4831 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
4832 $storeid = $storage if $storage;
4833
4834 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4835 if (!$format) {
4836 $format = $drive->{format} || $defFormat;
4837 }
4838
4839 # test if requested format is supported - else use default
4840 my $supported = grep { $_ eq $format } @$validFormats;
4841 $format = $defFormat if !$supported;
4842
4843 my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3);
4844
4845 print "create full clone of drive $drivename ($drive->{file})\n";
4846 $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4847 push @$newvollist, $newvolid;
4848
4849 if (!$running || $snapname) {
4850 qemu_img_convert($drive->{file}, $newvolid, $size, $snapname);
4851 } else {
4852 qemu_drive_mirror($vmid, $drivename, $newvolid, $newvmid);
4853 }
4854 }
4855
4856 my ($size) = PVE::Storage::volume_size_info($storecfg, $newvolid, 3);
4857
4858 my $disk = $drive;
4859 $disk->{format} = undef;
4860 $disk->{file} = $newvolid;
4861 $disk->{size} = $size;
4862
4863 return $disk;
4864}
4865
4866# this only works if VM is running
4867sub get_current_qemu_machine {
4868 my ($vmid) = @_;
4869
4870 my $cmd = { execute => 'query-machines', arguments => {} };
4871 my $res = PVE::QemuServer::vm_qmp_command($vmid, $cmd);
4872
4873 my ($current, $default);
4874 foreach my $e (@$res) {
4875 $default = $e->{name} if $e->{'is-default'};
4876 $current = $e->{name} if $e->{'is-current'};
4877 }
4878
4879 # fallback to the default machine if current is not supported by qemu
4880 return $current || $default || 'pc';
4881}
4882
4883sub read_x509_subject_spice {
4884 my ($filename) = @_;
4885
4886 # read x509 subject
4887 my $bio = Net::SSLeay::BIO_new_file($filename, 'r');
4888 my $x509 = Net::SSLeay::PEM_read_bio_X509($bio);
4889 Net::SSLeay::BIO_free($bio);
4890 my $nameobj = Net::SSLeay::X509_get_subject_name($x509);
4891 my $subject = Net::SSLeay::X509_NAME_oneline($nameobj);
4892 Net::SSLeay::X509_free($x509);
4893
4894 # remote-viewer wants comma as seperator (not '/')
4895 $subject =~ s!^/!!;
4896 $subject =~ s!/(\w+=)!,$1!g;
4897
4898 return $subject;
4899}
49001;