]> git.proxmox.com Git - qemu-server.git/blame_incremental - PVE/QemuServer.pm
cleanup warning messages
[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::SHA1;
15use Fcntl ':flock';
16use Cwd 'abs_path';
17use IPC::Open3;
18use Fcntl;
19use PVE::SafeSyslog;
20use Storable qw(dclone);
21use PVE::Exception qw(raise raise_param_exc);
22use PVE::Storage;
23use PVE::Tools qw(run_command lock_file file_read_firstline);
24use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
25use PVE::INotify;
26use PVE::ProcFSTools;
27use Time::HiRes qw(gettimeofday);
28
29my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
30
31# Note about locking: we use flock on the config file protect
32# against concurent actions.
33# Aditionaly, we have a 'lock' setting in the config file. This
34# can be set to 'migrate' or 'backup'. Most actions are not
35# allowed when such lock is set. But you can ignore this kind of
36# lock with the --skiplock flag.
37
38cfs_register_file('/qemu-server/', \&parse_vm_config);
39
40PVE::JSONSchema::register_standard_option('skiplock', {
41 description => "Ignore locks - only root is allowed to use this option.",
42 type => 'boolean',
43 optional => 1,
44});
45
46PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
47 description => "Some command save/restore state from this location.",
48 type => 'string',
49 maxLength => 128,
50 optional => 1,
51});
52
53#no warnings 'redefine';
54
55unless(defined(&_VZSYSCALLS_H_)) {
56 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_);
57 require 'sys/syscall.ph';
58 if(defined(&__x86_64__)) {
59 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus);
60 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod);
61 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod);
62 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt);
63 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr);
64 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate);
65 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid);
66 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit);
67 }
68 elsif(defined( &__i386__) ) {
69 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod);
70 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod);
71 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt);
72 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr);
73 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate);
74 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus);
75 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid);
76 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit);
77 } else {
78 die("no fairsched syscall for this arch");
79 }
80 require 'asm/ioctl.ph';
81 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION);
82}
83
84sub fairsched_mknod {
85 my ($parent, $weight, $desired) = @_;
86
87 return syscall(&__NR_fairsched_mknod, int($parent), int($weight), int($desired));
88}
89
90sub fairsched_rmnod {
91 my ($id) = @_;
92
93 return syscall(&__NR_fairsched_rmnod, int($id));
94}
95
96sub fairsched_mvpr {
97 my ($pid, $newid) = @_;
98
99 return syscall(&__NR_fairsched_mvpr, int($pid), int($newid));
100}
101
102sub fairsched_vcpus {
103 my ($id, $vcpus) = @_;
104
105 return syscall(&__NR_fairsched_vcpus, int($id), int($vcpus));
106}
107
108sub fairsched_rate {
109 my ($id, $op, $rate) = @_;
110
111 return syscall(&__NR_fairsched_rate, int($id), int($op), int($rate));
112}
113
114use constant FAIRSCHED_SET_RATE => 0;
115use constant FAIRSCHED_DROP_RATE => 1;
116use constant FAIRSCHED_GET_RATE => 2;
117
118sub fairsched_cpulimit {
119 my ($id, $limit) = @_;
120
121 my $cpulim1024 = int($limit * 1024 / 100);
122 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE : FAIRSCHED_DROP_RATE;
123
124 return fairsched_rate($id, $op, $cpulim1024);
125}
126
127my $nodename = PVE::INotify::nodename();
128
129mkdir "/etc/pve/nodes/$nodename";
130my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
131mkdir $confdir;
132
133my $var_run_tmpdir = "/var/run/qemu-server";
134mkdir $var_run_tmpdir;
135
136my $lock_dir = "/var/lock/qemu-server";
137mkdir $lock_dir;
138
139my $pcisysfs = "/sys/bus/pci";
140
141my $confdesc = {
142 onboot => {
143 optional => 1,
144 type => 'boolean',
145 description => "Specifies whether a VM will be started during system bootup.",
146 default => 0,
147 },
148 autostart => {
149 optional => 1,
150 type => 'boolean',
151 description => "Automatic restart after crash (currently ignored).",
152 default => 0,
153 },
154 hotplug => {
155 optional => 1,
156 type => 'boolean',
157 description => "Activate hotplug for disk and network device",
158 default => 0,
159 },
160 reboot => {
161 optional => 1,
162 type => 'boolean',
163 description => "Allow reboot. If set to '0' the VM exit on reboot.",
164 default => 1,
165 },
166 lock => {
167 optional => 1,
168 type => 'string',
169 description => "Lock/unlock the VM.",
170 enum => [qw(migrate backup)],
171 },
172 cpulimit => {
173 optional => 1,
174 type => 'integer',
175 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.",
176 minimum => 0,
177 default => 0,
178 },
179 cpuunits => {
180 optional => 1,
181 type => 'integer',
182 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.",
183 minimum => 0,
184 maximum => 500000,
185 default => 1000,
186 },
187 memory => {
188 optional => 1,
189 type => 'integer',
190 description => "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
191 minimum => 16,
192 default => 512,
193 },
194 balloon => {
195 optional => 1,
196 type => 'integer',
197 description => "Amount of target RAM for the VM in MB.",
198 minimum => 16,
199 },
200 keyboard => {
201 optional => 1,
202 type => 'string',
203 description => "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
204 enum => PVE::Tools::kvmkeymaplist(),
205 default => 'en-us',
206 },
207 name => {
208 optional => 1,
209 type => 'string',
210 description => "Set a name for the VM. Only used on the configuration web interface.",
211 },
212 description => {
213 optional => 1,
214 type => 'string',
215 description => "Description for the VM. Only used on the configuration web interface.",
216 },
217 ostype => {
218 optional => 1,
219 type => 'string',
220 enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 l24 l26)],
221 description => <<EODESC,
222Used to enable special optimization/features for specific
223operating systems:
224
225other => unspecified OS
226wxp => Microsoft Windows XP
227w2k => Microsoft Windows 2000
228w2k3 => Microsoft Windows 2003
229w2k8 => Microsoft Windows 2008
230wvista => Microsoft Windows Vista
231win7 => Microsoft Windows 7
232l24 => Linux 2.4 Kernel
233l26 => Linux 2.6/3.X Kernel
234
235other|l24|l26 ... no special behaviour
236wxp|w2k|w2k3|w2k8|wvista|win7 ... use --localtime switch
237EODESC
238 },
239 boot => {
240 optional => 1,
241 type => 'string',
242 description => "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
243 pattern => '[acdn]{1,4}',
244 default => 'cdn',
245 },
246 bootdisk => {
247 optional => 1,
248 type => 'string', format => 'pve-qm-bootdisk',
249 description => "Enable booting from specified disk.",
250 pattern => '(ide|scsi|virtio)\d+',
251 },
252 smp => {
253 optional => 1,
254 type => 'integer',
255 description => "The number of CPUs. Please use option -sockets instead.",
256 minimum => 1,
257 default => 1,
258 },
259 sockets => {
260 optional => 1,
261 type => 'integer',
262 description => "The number of CPU sockets.",
263 minimum => 1,
264 default => 1,
265 },
266 cores => {
267 optional => 1,
268 type => 'integer',
269 description => "The number of cores per socket.",
270 minimum => 1,
271 default => 1,
272 },
273 acpi => {
274 optional => 1,
275 type => 'boolean',
276 description => "Enable/disable ACPI.",
277 default => 1,
278 },
279 kvm => {
280 optional => 1,
281 type => 'boolean',
282 description => "Enable/disable KVM hardware virtualization.",
283 default => 1,
284 },
285 tdf => {
286 optional => 1,
287 type => 'boolean',
288 description => "Enable/disable time drift fix.",
289 default => 1,
290 },
291 localtime => {
292 optional => 1,
293 type => 'boolean',
294 description => "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
295 },
296 freeze => {
297 optional => 1,
298 type => 'boolean',
299 description => "Freeze CPU at startup (use 'c' monitor command to start execution).",
300 },
301 vga => {
302 optional => 1,
303 type => 'string',
304 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 win7/w2k8, and 'cirrur' for other OS types",
305 enum => [qw(std cirrus vmware)],
306 },
307 watchdog => {
308 optional => 1,
309 type => 'string', format => 'pve-qm-watchdog',
310 typetext => '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
311 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)",
312 },
313 startdate => {
314 optional => 1,
315 type => 'string',
316 typetext => "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
317 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'.",
318 pattern => '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
319 default => 'now',
320 },
321 args => {
322 optional => 1,
323 type => 'string',
324 description => <<EODESCR,
325Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
326
327args: -no-reboot -no-hpet
328EODESCR
329 },
330 tablet => {
331 optional => 1,
332 type => 'boolean',
333 default => 1,
334 description => "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning. 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.",
335 },
336 migrate_speed => {
337 optional => 1,
338 type => 'integer',
339 description => "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
340 minimum => 0,
341 default => 0,
342 },
343 migrate_downtime => {
344 optional => 1,
345 type => 'integer',
346 description => "Set maximum tolerated downtime (in seconds) for migrations.",
347 minimum => 0,
348 default => 1,
349 },
350 cdrom => {
351 optional => 1,
352 type => 'string', format => 'pve-qm-drive',
353 typetext => 'volume',
354 description => "This is an alias for option -ide2",
355 },
356 cpu => {
357 optional => 1,
358 description => "Emulated CPU type.",
359 type => 'string',
360 enum => [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom host) ],
361 default => 'qemu64',
362 },
363};
364
365# what about other qemu settings ?
366#cpu => 'string',
367#machine => 'string',
368#fda => 'file',
369#fdb => 'file',
370#mtdblock => 'file',
371#sd => 'file',
372#pflash => 'file',
373#snapshot => 'bool',
374#bootp => 'file',
375##tftp => 'dir',
376##smb => 'dir',
377#kernel => 'file',
378#append => 'string',
379#initrd => 'file',
380##soundhw => 'string',
381
382while (my ($k, $v) = each %$confdesc) {
383 PVE::JSONSchema::register_standard_option("pve-qm-$k", $v);
384}
385
386my $MAX_IDE_DISKS = 4;
387my $MAX_SCSI_DISKS = 14;
388my $MAX_VIRTIO_DISKS = 6;
389my $MAX_USB_DEVICES = 5;
390my $MAX_NETS = 6;
391my $MAX_UNUSED_DISKS = 8;
392my $MAX_HOSTPCI_DEVICES = 2;
393my $MAX_SERIAL_PORTS = 4;
394my $MAX_PARALLEL_PORTS = 3;
395
396my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
397 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
398my $nic_model_list_txt = join(' ', sort @$nic_model_list);
399
400# fixme:
401my $netdesc = {
402 optional => 1,
403 type => 'string', format => 'pve-qm-net',
404 typetext => "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>]",
405 description => <<EODESCR,
406Specify network devices.
407
408MODEL is one of: $nic_model_list_txt
409
410XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
411automatically generated if not specified.
412
413The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
414
415Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
416
417If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
418
41910.0.2.2 Gateway
42010.0.2.3 DNS Server
42110.0.2.4 SMB Server
422
423The DHCP server assign addresses to the guest starting from 10.0.2.15.
424
425EODESCR
426};
427PVE::JSONSchema::register_standard_option("pve-qm-net", $netdesc);
428
429for (my $i = 0; $i < $MAX_NETS; $i++) {
430 $confdesc->{"net$i"} = $netdesc;
431}
432
433my $drivename_hash;
434
435my $idedesc = {
436 optional => 1,
437 type => 'string', format => 'pve-qm-drive',
438 typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]',
439 description => "Use volume as IDE hard disk or CD-ROM (n is 0 to 3).",
440};
441PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc);
442
443my $scsidesc = {
444 optional => 1,
445 type => 'string', format => 'pve-qm-drive',
446 typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]',
447 description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13).",
448};
449PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
450
451my $virtiodesc = {
452 optional => 1,
453 type => 'string', format => 'pve-qm-drive',
454 typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]',
455 description => "Use volume as VIRTIO hard disk (n is 0 to 5).",
456};
457PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc);
458
459my $usbdesc = {
460 optional => 1,
461 type => 'string', format => 'pve-qm-usb-device',
462 typetext => 'host=HOSTUSBDEVICE',
463 description => <<EODESCR,
464Configure an USB device (n is 0 to 4). This can be used to
465pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
466
467'bus-port(.port)*' (decimal numbers) or
468'vendor_id:product_id' (hexadeciaml numbers)
469
470You can use the 'lsusb -t' command to list existing usb devices.
471
472Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
473
474EODESCR
475};
476PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
477
478my $hostpcidesc = {
479 optional => 1,
480 type => 'string', format => 'pve-qm-hostpci',
481 typetext => "HOSTPCIDEVICE",
482 description => <<EODESCR,
483Map host pci devices. HOSTPCIDEVICE syntax is:
484
485'bus:dev.func' (hexadecimal numbers)
486
487You can us the 'lspci' command to list existing pci devices.
488
489Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
490
491Experimental: user reported problems with this option.
492EODESCR
493};
494PVE::JSONSchema::register_standard_option("pve-qm-hostpci", $hostpcidesc);
495
496my $serialdesc = {
497 optional => 1,
498 type => 'string',
499 pattern => '/dev/ttyS\d+',
500 description => <<EODESCR,
501Map host serial devices (n is 0 to 3).
502
503Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
504
505Experimental: user reported problems with this option.
506EODESCR
507};
508
509my $paralleldesc= {
510 optional => 1,
511 type => 'string',
512 pattern => '/dev/parport\d+',
513 description => <<EODESCR,
514Map host parallel devices (n is 0 to 2).
515
516Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
517
518Experimental: user reported problems with this option.
519EODESCR
520};
521
522for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
523 $confdesc->{"parallel$i"} = $paralleldesc;
524}
525
526for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
527 $confdesc->{"serial$i"} = $serialdesc;
528}
529
530for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
531 $confdesc->{"hostpci$i"} = $hostpcidesc;
532}
533
534for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
535 $drivename_hash->{"ide$i"} = 1;
536 $confdesc->{"ide$i"} = $idedesc;
537}
538
539for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
540 $drivename_hash->{"scsi$i"} = 1;
541 $confdesc->{"scsi$i"} = $scsidesc ;
542}
543
544for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
545 $drivename_hash->{"virtio$i"} = 1;
546 $confdesc->{"virtio$i"} = $virtiodesc;
547}
548
549for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
550 $confdesc->{"usb$i"} = $usbdesc;
551}
552
553my $unuseddesc = {
554 optional => 1,
555 type => 'string', format => 'pve-volume-id',
556 description => "Reference to unused volumes.",
557};
558
559for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
560 $confdesc->{"unused$i"} = $unuseddesc;
561}
562
563my $kvm_api_version = 0;
564
565sub kvm_version {
566
567 return $kvm_api_version if $kvm_api_version;
568
569 my $fh = IO::File->new("</dev/kvm") ||
570 return 0;
571
572 if (my $v = $fh->ioctl(KVM_GET_API_VERSION(), 0)) {
573 $kvm_api_version = $v;
574 }
575
576 $fh->close();
577
578 return $kvm_api_version;
579}
580
581my $kvm_user_version;
582
583sub kvm_user_version {
584
585 return $kvm_user_version if $kvm_user_version;
586
587 $kvm_user_version = 'unknown';
588
589 my $tmp = `kvm -help 2>/dev/null`;
590
591 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?) /) {
592 $kvm_user_version = $2;
593 }
594
595 return $kvm_user_version;
596
597}
598
599my $kernel_has_vhost_net = -c '/dev/vhost-net';
600
601sub disknames {
602 # order is important - used to autoselect boot disk
603 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
604 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
605 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))));
606}
607
608sub valid_drivename {
609 my $dev = shift;
610
611 return defined($drivename_hash->{$dev});
612}
613
614sub option_exists {
615 my $key = shift;
616 return defined($confdesc->{$key});
617}
618
619sub nic_models {
620 return $nic_model_list;
621}
622
623sub os_list_description {
624
625 return {
626 other => 'Other',
627 wxp => 'Windows XP',
628 w2k => 'Windows 2000',
629 w2k3 =>, 'Windows 2003',
630 w2k8 => 'Windows 2008',
631 wvista => 'Windows Vista',
632 win7 => 'Windows 7',
633 l24 => 'Linux 2.4',
634 l26 => 'Linux 2.6',
635 };
636}
637
638sub disk_devive_info {
639 my $dev = shift;
640
641 die "unknown disk device format '$dev'" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/;
642
643 my $bus = $1;
644 my $index = $2;
645 my $maxdev = 1024;
646
647 if ($bus eq 'ide') {
648 $maxdev = 2;
649 } elsif ($bus eq 'scsi') {
650 $maxdev = 7;
651 }
652
653 my $controller = int($index / $maxdev);
654 my $unit = $index % $maxdev;
655
656
657 return { bus => $bus, desc => uc($bus) . " $controller:$unit",
658 controller => $controller, unit => $unit, index => $index };
659
660}
661
662sub qemu_drive_name {
663 my ($dev, $media) = @_;
664
665 my $info = disk_devive_info($dev);
666 my $mediastr = '';
667
668 if (($info->{bus} eq 'ide') || ($info->{bus} eq 'scsi')) {
669 $mediastr = ($media eq 'cdrom') ? "-cd" : "-hd";
670 return sprintf("%s%i%s%i", $info->{bus}, $info->{controller},
671 $mediastr, $info->{unit});
672 } else {
673 return sprintf("%s%i", $info->{bus}, $info->{index});
674 }
675}
676
677my $cdrom_path;
678
679sub get_cdrom_path {
680
681 return $cdrom_path if $cdrom_path;
682
683 return $cdrom_path = "/dev/cdrom" if -l "/dev/cdrom";
684 return $cdrom_path = "/dev/cdrom1" if -l "/dev/cdrom1";
685 return $cdrom_path = "/dev/cdrom2" if -l "/dev/cdrom2";
686}
687
688sub get_iso_path {
689 my ($storecfg, $vmid, $cdrom) = @_;
690
691 if ($cdrom eq 'cdrom') {
692 return get_cdrom_path();
693 } elsif ($cdrom eq 'none') {
694 return '';
695 } elsif ($cdrom =~ m|^/|) {
696 return $cdrom;
697 } else {
698 return PVE::Storage::path($storecfg, $cdrom);
699 }
700}
701
702# try to convert old style file names to volume IDs
703sub filename_to_volume_id {
704 my ($vmid, $file, $media) = @_;
705
706 if (!($file eq 'none' || $file eq 'cdrom' ||
707 $file =~ m|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
708
709 return undef if $file =~ m|/|;
710
711 if ($media && $media eq 'cdrom') {
712 $file = "local:iso/$file";
713 } else {
714 $file = "local:$vmid/$file";
715 }
716 }
717
718 return $file;
719}
720
721sub verify_media_type {
722 my ($opt, $vtype, $media) = @_;
723
724 return if !$media;
725
726 my $etype;
727 if ($media eq 'disk') {
728 $etype = 'image';
729 } elsif ($media eq 'cdrom') {
730 $etype = 'iso';
731 } else {
732 die "internal error";
733 }
734
735 return if ($vtype eq $etype);
736
737 raise_param_exc({ $opt => "unexpected media type ($vtype != $etype)" });
738}
739
740sub cleanup_drive_path {
741 my ($opt, $storecfg, $drive) = @_;
742
743 # try to convert filesystem paths to volume IDs
744
745 if (($drive->{file} !~ m/^(cdrom|none)$/) &&
746 ($drive->{file} !~ m|^/dev/.+|) &&
747 ($drive->{file} !~ m/^([^:]+):(.+)$/) &&
748 ($drive->{file} !~ m/^\d+$/)) {
749 my ($vtype, $volid) = PVE::Storage::path_to_volume_id($storecfg, $drive->{file});
750 raise_param_exc({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
751 $drive->{media} = 'cdrom' if !$drive->{media} && $vtype eq 'iso';
752 verify_media_type($opt, $vtype, $drive->{media});
753 $drive->{file} = $volid;
754 }
755
756 $drive->{media} = 'cdrom' if !$drive->{media} && $drive->{file} =~ m/^(cdrom|none)$/;
757}
758
759sub create_conf_nolock {
760 my ($vmid, $settings) = @_;
761
762 my $filename = config_file($vmid);
763
764 die "configuration file '$filename' already exists\n" if -f $filename;
765
766 my $defaults = load_defaults();
767
768 $settings->{name} = "vm$vmid" if !$settings->{name};
769 $settings->{memory} = $defaults->{memory} if !$settings->{memory};
770
771 my $data = '';
772 foreach my $opt (keys %$settings) {
773 next if !$confdesc->{$opt};
774
775 my $value = $settings->{$opt};
776 next if !$value;
777
778 $data .= "$opt: $value\n";
779 }
780
781 PVE::Tools::file_set_contents($filename, $data);
782}
783
784# ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
785# [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
786# [,aio=native|threads]
787
788sub parse_drive {
789 my ($key, $data) = @_;
790
791 my $res = {};
792
793 # $key may be undefined - used to verify JSON parameters
794 if (!defined($key)) {
795 $res->{interface} = 'unknown'; # should not harm when used to verify parameters
796 $res->{index} = 0;
797 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
798 $res->{interface} = $1;
799 $res->{index} = $2;
800 } else {
801 return undef;
802 }
803
804 foreach my $p (split (/,/, $data)) {
805 next if $p =~ m/^\s*$/;
806
807 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio)=(.+)$/) {
808 my ($k, $v) = ($1, $2);
809
810 $k = 'file' if $k eq 'volume';
811
812 return undef if defined $res->{$k};
813
814 $res->{$k} = $v;
815 } else {
816 if (!$res->{file} && $p !~ m/=/) {
817 $res->{file} = $p;
818 } else {
819 return undef;
820 }
821 }
822 }
823
824 return undef if !$res->{file};
825
826 return undef if $res->{cache} &&
827 $res->{cache} !~ m/^(off|none|writethrough|writeback|unsafe)$/;
828 return undef if $res->{snapshot} && $res->{snapshot} !~ m/^(on|off)$/;
829 return undef if $res->{cyls} && $res->{cyls} !~ m/^\d+$/;
830 return undef if $res->{heads} && $res->{heads} !~ m/^\d+$/;
831 return undef if $res->{secs} && $res->{secs} !~ m/^\d+$/;
832 return undef if $res->{media} && $res->{media} !~ m/^(disk|cdrom)$/;
833 return undef if $res->{trans} && $res->{trans} !~ m/^(none|lba|auto)$/;
834 return undef if $res->{format} && $res->{format} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
835 return undef if $res->{rerror} && $res->{rerror} !~ m/^(ignore|report|stop)$/;
836 return undef if $res->{werror} && $res->{werror} !~ m/^(enospc|ignore|report|stop)$/;
837 return undef if $res->{backup} && $res->{backup} !~ m/^(yes|no)$/;
838 return undef if $res->{aio} && $res->{aio} !~ m/^(native|threads)$/;
839
840 if ($res->{media} && ($res->{media} eq 'cdrom')) {
841 return undef if $res->{snapshot} || $res->{trans} || $res->{format};
842 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
843 return undef if $res->{interface} eq 'virtio';
844 }
845
846 # rerror does not work with scsi drives
847 if ($res->{rerror}) {
848 return undef if $res->{interface} eq 'scsi';
849 }
850
851 return $res;
852}
853
854my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio);
855
856sub print_drive {
857 my ($vmid, $drive) = @_;
858
859 my $opts = '';
860 foreach my $o (@qemu_drive_options, 'backup') {
861 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
862 }
863
864 return "$drive->{file}$opts";
865}
866
867sub print_drivedevice_full {
868 my ($storecfg, $vmid, $drive) = @_;
869
870 my $device = '';
871 my $maxdev = 0;
872
873 if ($drive->{interface} eq 'virtio') {
874 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}");
875 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
876 } elsif ($drive->{interface} eq 'scsi') {
877 $maxdev = 7;
878 my $controller = int($drive->{index} / $maxdev);
879 my $unit = $drive->{index} % $maxdev;
880 my $devicetype = 'hd';
881 my $path = '';
882 if (drive_is_cdrom($drive)) {
883 $devicetype = 'cd';
884 } else {
885 if ($drive->{file} =~ m|^/|) {
886 $path = $drive->{file};
887 } else {
888 $path = PVE::Storage::path($storecfg, $drive->{file});
889 }
890 if ($path =~ m|^/dev/| ) {
891 $devicetype = 'block';
892 }
893 }
894
895 $device = "scsi-$devicetype,bus=lsi$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
896 } elsif ($drive->{interface} eq 'ide'){
897 $maxdev = 2;
898 my $controller = int($drive->{index} / $maxdev);
899 my $unit = $drive->{index} % $maxdev;
900 my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
901
902 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
903 } elsif ($drive->{interface} eq 'usb') {
904 die "implement me";
905 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
906 } else {
907 die "unsupported interface type";
908 }
909
910 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
911
912 return $device;
913}
914
915sub print_drive_full {
916 my ($storecfg, $vmid, $drive) = @_;
917
918 my $opts = '';
919 foreach my $o (@qemu_drive_options) {
920 next if $o eq 'bootindex';
921 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
922 }
923
924 # use linux-aio by default (qemu default is threads)
925 $opts .= ",aio=native" if !$drive->{aio};
926
927 my $path;
928 my $volid = $drive->{file};
929 if (drive_is_cdrom($drive)) {
930 $path = get_iso_path($storecfg, $vmid, $volid);
931 } else {
932 if ($volid =~ m|^/|) {
933 $path = $volid;
934 } else {
935 $path = PVE::Storage::path($storecfg, $volid);
936 }
937 if (!$drive->{cache} && ($path =~ m|^/dev/| || $path =~ m|\.raw$|)) {
938 $opts .= ",cache=none";
939 }
940 }
941
942 my $pathinfo = $path ? "file=$path," : '';
943
944 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
945}
946
947sub print_netdevice_full {
948 my ($vmid, $conf, $net, $netid) = @_;
949
950 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
951
952 my $device = $net->{model};
953 if ($net->{model} eq 'virtio') {
954 $device = 'virtio-net-pci';
955 };
956
957 # qemu > 0.15 always try to boot from network - we disable that by
958 # not loading the pxe rom file
959 my $extra = ($bootorder !~ m/n/) ? "romfile=," : '';
960 my $pciaddr = print_pci_addr("$netid");
961 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
962 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex} ;
963 return $tmpstr;
964}
965
966sub print_netdev_full {
967 my ($vmid, $conf, $net, $netid) = @_;
968
969 my $i = '';
970 if ($netid =~ m/^net(\d+)$/) {
971 $i = int($1);
972 }
973
974 die "got strange net id '$i'\n" if $i >= ${MAX_NETS};
975
976 my $ifname = "tap${vmid}i$i";
977
978 # kvm uses TUNSETIFF ioctl, and that limits ifname length
979 die "interface name '$ifname' is too long (max 15 character)\n"
980 if length($ifname) >= 16;
981
982 my $vhostparam = '';
983 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model} eq 'virtio';
984
985 my $vmname = $conf->{name} || "vm$vmid";
986
987 if ($net->{bridge}) {
988 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
989 } else {
990 return "type=user,id=$netid,hostname=$vmname";
991 }
992}
993
994sub drive_is_cdrom {
995 my ($drive) = @_;
996
997 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
998
999}
1000
1001sub parse_hostpci {
1002 my ($value) = @_;
1003
1004 return undef if !$value;
1005
1006 my $res = {};
1007
1008 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1009 $res->{pciid} = $value;
1010 } else {
1011 return undef;
1012 }
1013
1014 return $res;
1015}
1016
1017# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1018sub parse_net {
1019 my ($data) = @_;
1020
1021 my $res = {};
1022
1023 foreach my $kvp (split(/,/, $data)) {
1024
1025 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1026 my $model = lc($1);
1027 my $mac = uc($3) || PVE::Tools::random_ether_addr();
1028 $res->{model} = $model;
1029 $res->{macaddr} = $mac;
1030 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1031 $res->{bridge} = $1;
1032 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1033 $res->{rate} = $1;
1034 } else {
1035 return undef;
1036 }
1037
1038 }
1039
1040 return undef if !$res->{model};
1041
1042 return $res;
1043}
1044
1045sub print_net {
1046 my $net = shift;
1047
1048 my $res = "$net->{model}";
1049 $res .= "=$net->{macaddr}" if $net->{macaddr};
1050 $res .= ",bridge=$net->{bridge}" if $net->{bridge};
1051 $res .= ",rate=$net->{rate}" if $net->{rate};
1052
1053 return $res;
1054}
1055
1056sub add_random_macs {
1057 my ($settings) = @_;
1058
1059 foreach my $opt (keys %$settings) {
1060 next if $opt !~ m/^net(\d+)$/;
1061 my $net = parse_net($settings->{$opt});
1062 next if !$net;
1063 $settings->{$opt} = print_net($net);
1064 }
1065}
1066
1067sub add_unused_volume {
1068 my ($config, $volid, $vmid) = @_;
1069
1070 my $key;
1071 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1072 my $test = "unused$ind";
1073 if (my $vid = $config->{$test}) {
1074 return if $vid eq $volid; # do not add duplicates
1075 } else {
1076 $key = $test;
1077 }
1078 }
1079
1080 die "To many unused volume - please delete them first.\n" if !$key;
1081
1082 PVE::QemuServer::change_config_nolock($vmid, { $key => $volid }, {}, 1);
1083 $config->{$key} = $volid;
1084}
1085
1086# fixme: remove all thos $noerr parameters?
1087
1088PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
1089sub verify_bootdisk {
1090 my ($value, $noerr) = @_;
1091
1092 return $value if valid_drivename($value);
1093
1094 return undef if $noerr;
1095
1096 die "invalid boot disk '$value'\n";
1097}
1098
1099PVE::JSONSchema::register_format('pve-qm-net', \&verify_net);
1100sub verify_net {
1101 my ($value, $noerr) = @_;
1102
1103 return $value if parse_net($value);
1104
1105 return undef if $noerr;
1106
1107 die "unable to parse network options\n";
1108}
1109
1110PVE::JSONSchema::register_format('pve-qm-drive', \&verify_drive);
1111sub verify_drive {
1112 my ($value, $noerr) = @_;
1113
1114 return $value if parse_drive(undef, $value);
1115
1116 return undef if $noerr;
1117
1118 die "unable to parse drive options\n";
1119}
1120
1121PVE::JSONSchema::register_format('pve-qm-hostpci', \&verify_hostpci);
1122sub verify_hostpci {
1123 my ($value, $noerr) = @_;
1124
1125 return $value if parse_hostpci($value);
1126
1127 return undef if $noerr;
1128
1129 die "unable to parse pci id\n";
1130}
1131
1132PVE::JSONSchema::register_format('pve-qm-watchdog', \&verify_watchdog);
1133sub verify_watchdog {
1134 my ($value, $noerr) = @_;
1135
1136 return $value if parse_watchdog($value);
1137
1138 return undef if $noerr;
1139
1140 die "unable to parse watchdog options\n";
1141}
1142
1143sub parse_watchdog {
1144 my ($value) = @_;
1145
1146 return undef if !$value;
1147
1148 my $res = {};
1149
1150 foreach my $p (split(/,/, $value)) {
1151 next if $p =~ m/^\s*$/;
1152
1153 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1154 $res->{model} = $2;
1155 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1156 $res->{action} = $2;
1157 } else {
1158 return undef;
1159 }
1160 }
1161
1162 return $res;
1163}
1164
1165sub parse_usb_device {
1166 my ($value) = @_;
1167
1168 return undef if !$value;
1169
1170 my @dl = split(/,/, $value);
1171 my $found;
1172
1173 my $res = {};
1174 foreach my $v (@dl) {
1175 if ($v =~ m/^host=([0-9A-Fa-f]{4}):([0-9A-Fa-f]{4})$/) {
1176 $found = 1;
1177 $res->{vendorid} = $1;
1178 $res->{productid} = $2;
1179 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1180 $found = 1;
1181 $res->{hostbus} = $1;
1182 $res->{hostport} = $2;
1183 } else {
1184 return undef;
1185 }
1186 }
1187 return undef if !$found;
1188
1189 return $res;
1190}
1191
1192PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
1193sub verify_usb_device {
1194 my ($value, $noerr) = @_;
1195
1196 return $value if parse_usb_device($value);
1197
1198 return undef if $noerr;
1199
1200 die "unable to parse usb device\n";
1201}
1202
1203# add JSON properties for create and set function
1204sub json_config_properties {
1205 my $prop = shift;
1206
1207 foreach my $opt (keys %$confdesc) {
1208 $prop->{$opt} = $confdesc->{$opt};
1209 }
1210
1211 return $prop;
1212}
1213
1214sub check_type {
1215 my ($key, $value) = @_;
1216
1217 die "unknown setting '$key'\n" if !$confdesc->{$key};
1218
1219 my $type = $confdesc->{$key}->{type};
1220
1221 if (!defined($value)) {
1222 die "got undefined value\n";
1223 }
1224
1225 if ($value =~ m/[\n\r]/) {
1226 die "property contains a line feed\n";
1227 }
1228
1229 if ($type eq 'boolean') {
1230 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1231 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1232 die "type check ('boolean') failed - got '$value'\n";
1233 } elsif ($type eq 'integer') {
1234 return int($1) if $value =~ m/^(\d+)$/;
1235 die "type check ('integer') failed - got '$value'\n";
1236 } elsif ($type eq 'string') {
1237 if (my $fmt = $confdesc->{$key}->{format}) {
1238 if ($fmt eq 'pve-qm-drive') {
1239 # special case - we need to pass $key to parse_drive()
1240 my $drive = parse_drive($key, $value);
1241 return $value if $drive;
1242 die "unable to parse drive options\n";
1243 }
1244 PVE::JSONSchema::check_format($fmt, $value);
1245 return $value;
1246 }
1247 $value =~ s/^\"(.*)\"$/$1/;
1248 return $value;
1249 } else {
1250 die "internal error"
1251 }
1252}
1253
1254sub lock_config {
1255 my ($vmid, $code, @param) = @_;
1256
1257 my $filename = config_file_lock($vmid);
1258
1259 my $res = lock_file($filename, 10, $code, @param);
1260
1261 die $@ if $@;
1262
1263 return $res;
1264}
1265
1266sub cfs_config_path {
1267 my ($vmid, $node) = @_;
1268
1269 $node = $nodename if !$node;
1270 return "nodes/$node/qemu-server/$vmid.conf";
1271}
1272
1273sub check_iommu_support{
1274 #fixme : need to check IOMMU support
1275 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1276
1277 my $iommu=1;
1278 return $iommu;
1279
1280}
1281
1282sub config_file {
1283 my ($vmid, $node) = @_;
1284
1285 my $cfspath = cfs_config_path($vmid, $node);
1286 return "/etc/pve/$cfspath";
1287}
1288
1289sub config_file_lock {
1290 my ($vmid) = @_;
1291
1292 return "$lock_dir/lock-$vmid.conf";
1293}
1294
1295sub touch_config {
1296 my ($vmid) = @_;
1297
1298 my $conf = config_file($vmid);
1299 utime undef, undef, $conf;
1300}
1301
1302sub create_disks {
1303 my ($storecfg, $vmid, $settings, $conf, $default_storage) = @_;
1304
1305 my $vollist = [];
1306
1307 eval {
1308 foreach_drive($settings, sub {
1309 my ($ds, $disk) = @_;
1310
1311 return if drive_is_cdrom($disk);
1312
1313 my $file = $disk->{file};
1314
1315 if ($file =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
1316 my $storeid = $2 || $default_storage;
1317 my $size = $3;
1318 my $defformat = PVE::Storage::storage_default_format($storecfg, $storeid);
1319 my $fmt = $disk->{format} || $defformat;
1320 syslog('info', "VM $vmid creating new disk - size is $size GB");
1321
1322 my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid,
1323 $fmt, undef, $size*1024*1024);
1324
1325 $disk->{file} = $volid;
1326 delete $disk->{format}; # no longer needed
1327 push @$vollist, $volid;
1328 $settings->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
1329 } else {
1330 my $path;
1331 if ($disk->{file} =~ m|^/dev/.+|) {
1332 $path = $disk->{file};
1333 } else {
1334 $path = PVE::Storage::path($storecfg, $disk->{file});
1335 }
1336 if (!(-f $path || -b $path)) {
1337 die "image '$path' does not exists\n";
1338 }
1339 }
1340 });
1341 };
1342
1343 my $err = $@;
1344
1345 if ($err) {
1346 syslog('err', "VM $vmid creating disks failed");
1347 foreach my $volid (@$vollist) {
1348 eval { PVE::Storage::vdisk_free($storecfg, $volid); };
1349 warn $@ if $@;
1350 }
1351 die $err;
1352 }
1353
1354 return $vollist;
1355}
1356
1357sub destroy_vm {
1358 my ($storecfg, $vmid, $keep_empty_config) = @_;
1359
1360 my $conffile = config_file($vmid);
1361
1362 my $conf = load_config($vmid);
1363
1364 check_lock($conf);
1365
1366 # only remove disks owned by this VM
1367 foreach_drive($conf, sub {
1368 my ($ds, $drive) = @_;
1369
1370 return if drive_is_cdrom($drive);
1371
1372 my $volid = $drive->{file};
1373 return if !$volid || $volid =~ m|^/|;
1374
1375 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
1376 return if !$path || !$owner || ($owner != $vmid);
1377
1378 PVE::Storage::vdisk_free($storecfg, $volid);
1379 });
1380
1381 if ($keep_empty_config) {
1382 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
1383 } else {
1384 unlink $conffile;
1385 }
1386
1387 # also remove unused disk
1388 eval {
1389 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1390
1391 eval {
1392 PVE::Storage::foreach_volid($dl, sub {
1393 my ($volid, $sid, $volname, $d) = @_;
1394 PVE::Storage::vdisk_free($storecfg, $volid);
1395 });
1396 };
1397 warn $@ if $@;
1398
1399 };
1400 warn $@ if $@;
1401}
1402
1403# fixme: remove?
1404sub load_diskinfo_old {
1405 my ($storecfg, $vmid, $conf) = @_;
1406
1407 my $info = {};
1408 my $res = {};
1409 my $vollist;
1410
1411 foreach_drive($conf, sub {
1412 my ($ds, $di) = @_;
1413
1414 $res->{$ds} = $di;
1415
1416 return if drive_is_cdrom($di);
1417
1418 if ($di->{file} =~ m|^/dev/.+|) {
1419 $info->{$di->{file}}->{size} = PVE::Storage::file_size_info($di->{file});
1420 } else {
1421 push @$vollist, $di->{file};
1422 }
1423 });
1424
1425 eval {
1426 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid, $vollist);
1427
1428 PVE::Storage::foreach_volid($dl, sub {
1429 my ($volid, $sid, $volname, $d) = @_;
1430 $info->{$volid} = $d;
1431 });
1432 };
1433 warn $@ if $@;
1434
1435 foreach my $ds (keys %$res) {
1436 my $di = $res->{$ds};
1437
1438 $res->{$ds}->{disksize} = $info->{$di->{file}} ?
1439 $info->{$di->{file}}->{size} / (1024*1024) : 0;
1440 }
1441
1442 return $res;
1443}
1444
1445sub load_config {
1446 my ($vmid) = @_;
1447
1448 my $cfspath = cfs_config_path($vmid);
1449
1450 my $conf = PVE::Cluster::cfs_read_file($cfspath);
1451
1452 die "no such VM ('$vmid')\n" if !defined($conf);
1453
1454 return $conf;
1455}
1456
1457sub parse_vm_config {
1458 my ($filename, $raw) = @_;
1459
1460 return undef if !defined($raw);
1461
1462 my $res = {
1463 digest => Digest::SHA1::sha1_hex($raw),
1464 };
1465
1466 $filename =~ m|/qemu-server/(\d+)\.conf$|
1467 || die "got strange filename '$filename'";
1468
1469 my $vmid = $1;
1470
1471 while ($raw && $raw =~ s/^(.*?)(\n|$)//) {
1472 my $line = $1;
1473
1474 next if $line =~ m/^\#/;
1475
1476 next if $line =~ m/^\s*$/;
1477
1478 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1479 my $key = $1;
1480 my $value = PVE::Tools::decode_text($2);
1481 $res->{$key} = $value;
1482 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1483 my $key = $1;
1484 my $value = $2;
1485 $res->{$key} = $value;
1486 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1487 my $key = $1;
1488 my $value = $2;
1489 eval { $value = check_type($key, $value); };
1490 if ($@) {
1491 warn "vm $vmid - unable to parse value of '$key' - $@";
1492 } else {
1493 my $fmt = $confdesc->{$key}->{format};
1494 if ($fmt && $fmt eq 'pve-qm-drive') {
1495 my $v = parse_drive($key, $value);
1496 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
1497 $v->{file} = $volid;
1498 $value = print_drive($vmid, $v);
1499 } else {
1500 warn "vm $vmid - unable to parse value of '$key'\n";
1501 next;
1502 }
1503 }
1504
1505 if ($key eq 'cdrom') {
1506 $res->{ide2} = $value;
1507 } else {
1508 $res->{$key} = $value;
1509 }
1510 }
1511 }
1512 }
1513
1514 # convert old smp to sockets
1515 if ($res->{smp} && !$res->{sockets}) {
1516 $res->{sockets} = $res->{smp};
1517 }
1518 delete $res->{smp};
1519
1520 return $res;
1521}
1522
1523sub change_config {
1524 my ($vmid, $settings, $unset, $skiplock) = @_;
1525
1526 lock_config($vmid, &change_config_nolock, $settings, $unset, $skiplock);
1527}
1528
1529sub change_config_nolock {
1530 my ($vmid, $settings, $unset, $skiplock) = @_;
1531
1532 my $res = {};
1533
1534 $unset->{ide2} = $unset->{cdrom} if $unset->{cdrom};
1535
1536 check_lock($settings) if !$skiplock;
1537
1538 # we do not use 'smp' any longer
1539 if ($settings->{sockets}) {
1540 $unset->{smp} = 1;
1541 } elsif ($settings->{smp}) {
1542 $settings->{sockets} = $settings->{smp};
1543 $unset->{smp} = 1;
1544 }
1545
1546 my $new_volids = {};
1547
1548 foreach my $key (keys %$settings) {
1549 next if $key eq 'digest';
1550 my $value = $settings->{$key};
1551 if ($key eq 'description') {
1552 $value = PVE::Tools::encode_text($value);
1553 }
1554 eval { $value = check_type($key, $value); };
1555 die "unable to parse value of '$key' - $@" if $@;
1556 if ($key eq 'cdrom') {
1557 $res->{ide2} = $value;
1558 } else {
1559 $res->{$key} = $value;
1560 }
1561 if (valid_drivename($key)) {
1562 my $drive = PVE::QemuServer::parse_drive($key, $value);
1563 $new_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
1564 }
1565 }
1566
1567 my $filename = config_file($vmid);
1568 my $tmpfn = "$filename.$$.tmp";
1569
1570 my $fh = new IO::File($filename, "r") ||
1571 die "unable to read config for VM $vmid\n";
1572
1573 my $werror = "unable to write config for VM $vmid\n";
1574
1575 my $out = new IO::File($tmpfn, "w") || die $werror;
1576
1577 eval {
1578
1579 my $done;
1580
1581 while (my $line = <$fh>) {
1582
1583 if (($line =~ m/^\#/) || ($line =~ m/^\s*$/)) {
1584 die $werror unless print $out $line;
1585 next;
1586 }
1587
1588 if ($line =~ m/^([a-z][a-z_]*\d*):\s*(.*\S)\s*$/) {
1589 my $key = $1;
1590 my $value = $2;
1591
1592 # remove 'unusedX' settings if we re-add a volume
1593 next if $key =~ m/^unused/ && $new_volids->{$value};
1594
1595 # convert 'smp' to 'sockets'
1596 $key = 'sockets' if $key eq 'smp';
1597
1598 next if $done->{$key};
1599 $done->{$key} = 1;
1600
1601 if (defined($res->{$key})) {
1602 $value = $res->{$key};
1603 delete $res->{$key};
1604 }
1605 if (!defined($unset->{$key})) {
1606 die $werror unless print $out "$key: $value\n";
1607 }
1608
1609 next;
1610 }
1611
1612 die "unable to parse config file: $line\n";
1613 }
1614
1615 foreach my $key (keys %$res) {
1616
1617 if (!defined($unset->{$key})) {
1618 die $werror unless print $out "$key: $res->{$key}\n";
1619 }
1620 }
1621 };
1622
1623 my $err = $@;
1624
1625 $fh->close();
1626
1627 if ($err) {
1628 $out->close();
1629 unlink $tmpfn;
1630 die $err;
1631 }
1632
1633 if (!$out->close()) {
1634 $err = "close failed - $!\n";
1635 unlink $tmpfn;
1636 die $err;
1637 }
1638
1639 if (!rename($tmpfn, $filename)) {
1640 $err = "rename failed - $!\n";
1641 unlink $tmpfn;
1642 die $err;
1643 }
1644}
1645
1646sub load_defaults {
1647
1648 my $res = {};
1649
1650 # we use static defaults from our JSON schema configuration
1651 foreach my $key (keys %$confdesc) {
1652 if (defined(my $default = $confdesc->{$key}->{default})) {
1653 $res->{$key} = $default;
1654 }
1655 }
1656
1657 my $conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
1658 $res->{keyboard} = $conf->{keyboard} if $conf->{keyboard};
1659
1660 return $res;
1661}
1662
1663sub config_list {
1664 my $vmlist = PVE::Cluster::get_vmlist();
1665 my $res = {};
1666 return $res if !$vmlist || !$vmlist->{ids};
1667 my $ids = $vmlist->{ids};
1668
1669 foreach my $vmid (keys %$ids) {
1670 my $d = $ids->{$vmid};
1671 next if !$d->{node} || $d->{node} ne $nodename;
1672 next if !$d->{type} || $d->{type} ne 'qemu';
1673 $res->{$vmid}->{exists} = 1;
1674 }
1675 return $res;
1676}
1677
1678# test if VM uses local resources (to prevent migration)
1679sub check_local_resources {
1680 my ($conf, $noerr) = @_;
1681
1682 my $loc_res = 0;
1683
1684 $loc_res = 1 if $conf->{hostusb}; # old syntax
1685 $loc_res = 1 if $conf->{hostpci}; # old syntax
1686
1687 foreach my $k (keys %$conf) {
1688 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1689 }
1690
1691 die "VM uses local resources\n" if $loc_res && !$noerr;
1692
1693 return $loc_res;
1694}
1695
1696sub check_lock {
1697 my ($conf) = @_;
1698
1699 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1700}
1701
1702sub check_cmdline {
1703 my ($pidfile, $pid) = @_;
1704
1705 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
1706 if (defined($fh)) {
1707 my $line = <$fh>;
1708 $fh->close;
1709 return undef if !$line;
1710 my @param = split(/\0/, $line);
1711
1712 my $cmd = $param[0];
1713 return if !$cmd || ($cmd !~ m|kvm$|);
1714
1715 for (my $i = 0; $i < scalar (@param); $i++) {
1716 my $p = $param[$i];
1717 next if !$p;
1718 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1719 my $p = $param[$i+1];
1720 return 1 if $p && ($p eq $pidfile);
1721 return undef;
1722 }
1723 }
1724 }
1725 return undef;
1726}
1727
1728sub check_running {
1729 my ($vmid, $nocheck) = @_;
1730
1731 my $filename = config_file($vmid);
1732
1733 die "unable to find configuration file for VM $vmid - no such machine\n"
1734 if !$nocheck && ! -f $filename;
1735
1736 my $pidfile = pidfile_name($vmid);
1737
1738 if (my $fd = IO::File->new("<$pidfile")) {
1739 my $st = stat($fd);
1740 my $line = <$fd>;
1741 close($fd);
1742
1743 my $mtime = $st->mtime;
1744 if ($mtime > time()) {
1745 warn "file '$filename' modified in future\n";
1746 }
1747
1748 if ($line =~ m/^(\d+)$/) {
1749 my $pid = $1;
1750 if (check_cmdline($pidfile, $pid)) {
1751 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
1752 return $pid;
1753 }
1754 }
1755 }
1756 }
1757
1758 return undef;
1759}
1760
1761sub vzlist {
1762
1763 my $vzlist = config_list();
1764
1765 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1766
1767 while (defined(my $de = $fd->read)) {
1768 next if $de !~ m/^(\d+)\.pid$/;
1769 my $vmid = $1;
1770 next if !defined($vzlist->{$vmid});
1771 if (my $pid = check_running($vmid)) {
1772 $vzlist->{$vmid}->{pid} = $pid;
1773 }
1774 }
1775
1776 return $vzlist;
1777}
1778
1779my $storage_timeout_hash = {};
1780
1781sub disksize {
1782 my ($storecfg, $conf) = @_;
1783
1784 my $bootdisk = $conf->{bootdisk};
1785 return undef if !$bootdisk;
1786 return undef if !valid_drivename($bootdisk);
1787
1788 return undef if !$conf->{$bootdisk};
1789
1790 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
1791 return undef if !defined($drive);
1792
1793 return undef if drive_is_cdrom($drive);
1794
1795 my $volid = $drive->{file};
1796 return undef if !$volid;
1797
1798 my $path;
1799 my $storeid;
1800 my $timeoutid;
1801
1802 if ($volid =~ m|^/|) {
1803 $path = $timeoutid = $volid;
1804 } else {
1805 eval {
1806 $storeid = $timeoutid = PVE::Storage::parse_volume_id($volid);
1807 $path = PVE::Storage::path($storecfg, $volid);
1808 };
1809 if (my $err = $@) {
1810 warn $err;
1811 return undef;
1812 }
1813 }
1814
1815 my $last_timeout = $storage_timeout_hash->{$timeoutid};
1816 if ($last_timeout) {
1817 if ((time() - $last_timeout) < 30) {
1818 # skip storage with errors
1819 return undef ;
1820 }
1821 delete $storage_timeout_hash->{$timeoutid};
1822 }
1823
1824 my ($size, $format, $used);
1825
1826 ($size, $format, $used) = PVE::Storage::file_size_info($path, 1);
1827
1828 if (!defined($format)) {
1829 # got timeout
1830 $storage_timeout_hash->{$timeoutid} = time();
1831 return undef;
1832 }
1833
1834 return wantarray ? ($size, $used) : $size;
1835}
1836
1837my $last_proc_pid_stat;
1838
1839sub vmstatus {
1840 my ($opt_vmid) = @_;
1841
1842 my $res = {};
1843
1844 my $storecfg = PVE::Storage::config();
1845
1846 my $list = vzlist();
1847 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1848
1849 my $cpucount = $cpuinfo->{cpus} || 1;
1850
1851 foreach my $vmid (keys %$list) {
1852 next if $opt_vmid && ($vmid ne $opt_vmid);
1853
1854 my $cfspath = cfs_config_path($vmid);
1855 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
1856
1857 my $d = {};
1858 $d->{pid} = $list->{$vmid}->{pid};
1859
1860 # fixme: better status?
1861 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
1862
1863 my ($size, $used) = disksize($storecfg, $conf);
1864 if (defined($size) && defined($used)) {
1865 $d->{disk} = $used;
1866 $d->{maxdisk} = $size;
1867 } else {
1868 $d->{disk} = 0;
1869 $d->{maxdisk} = 0;
1870 }
1871
1872 $d->{cpus} = ($conf->{sockets} || 1) * ($conf->{cores} || 1);
1873 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
1874
1875 $d->{name} = $conf->{name} || "VM $vmid";
1876 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
1877
1878 $d->{uptime} = 0;
1879 $d->{cpu} = 0;
1880 $d->{mem} = 0;
1881
1882 $d->{netout} = 0;
1883 $d->{netin} = 0;
1884
1885 $d->{diskread} = 0;
1886 $d->{diskwrite} = 0;
1887
1888 $res->{$vmid} = $d;
1889 }
1890
1891 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
1892 foreach my $dev (keys %$netdev) {
1893 next if $dev !~ m/^tap([1-9]\d*)i/;
1894 my $vmid = $1;
1895 my $d = $res->{$vmid};
1896 next if !$d;
1897
1898 $d->{netout} += $netdev->{$dev}->{receive};
1899 $d->{netin} += $netdev->{$dev}->{transmit};
1900 }
1901
1902 my $ctime = gettimeofday;
1903
1904 foreach my $vmid (keys %$list) {
1905
1906 my $d = $res->{$vmid};
1907 my $pid = $d->{pid};
1908 next if !$pid;
1909
1910 if (my $fh = IO::File->new("/proc/$pid/io", "r")) {
1911 my $data = {};
1912 while (defined(my $line = <$fh>)) {
1913 if ($line =~ m/^([rw]char):\s+(\d+)$/) {
1914 $data->{$1} = $2;
1915 }
1916 }
1917 close($fh);
1918 $d->{diskread} = $data->{rchar} || 0;
1919 $d->{diskwrite} = $data->{wchar} || 0;
1920 }
1921
1922 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
1923 next if !$pstat; # not running
1924
1925 my $used = $pstat->{utime} + $pstat->{stime};
1926
1927 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1928
1929 if ($pstat->{vsize}) {
1930 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1931 }
1932
1933 my $old = $last_proc_pid_stat->{$pid};
1934 if (!$old) {
1935 $last_proc_pid_stat->{$pid} = {
1936 time => $ctime,
1937 used => $used,
1938 cpu => 0,
1939 };
1940 next;
1941 }
1942
1943 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1944
1945 if ($dtime > 1000) {
1946 my $dutime = $used - $old->{used};
1947
1948 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1949 $last_proc_pid_stat->{$pid} = {
1950 time => $ctime,
1951 used => $used,
1952 cpu => $d->{cpu},
1953 };
1954 } else {
1955 $d->{cpu} = $old->{cpu};
1956 }
1957 }
1958
1959 return $res;
1960}
1961
1962sub foreach_drive {
1963 my ($conf, $func) = @_;
1964
1965 foreach my $ds (keys %$conf) {
1966 next if !valid_drivename($ds);
1967
1968 my $drive = parse_drive($ds, $conf->{$ds});
1969 next if !$drive;
1970
1971 &$func($ds, $drive);
1972 }
1973}
1974
1975sub config_to_command {
1976 my ($storecfg, $vmid, $conf, $defaults, $migrate_uri) = @_;
1977
1978 my $cmd = [];
1979 my $pciaddr = '';
1980 my $kvmver = kvm_user_version();
1981 my $vernum = 0; # unknown
1982 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
1983 $vernum = $1*1000000+$2*1000;
1984 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1985 $vernum = $1*1000000+$2*1000+$3;
1986 }
1987
1988 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1989
1990 my $have_ovz = -f '/proc/vz/vestat';
1991
1992 push @$cmd, '/usr/bin/kvm';
1993
1994 push @$cmd, '-id', $vmid;
1995
1996 my $use_virtio = 0;
1997
1998 my $socket = monitor_socket($vmid);
1999 push @$cmd, '-chardev', "socket,id=monitor,path=$socket,server,nowait";
2000 push @$cmd, '-mon', "chardev=monitor,mode=readline";
2001
2002 $socket = vnc_socket($vmid);
2003 push @$cmd, '-vnc', "unix:$socket,x509,password";
2004
2005 push @$cmd, '-pidfile' , pidfile_name($vmid);
2006
2007 push @$cmd, '-daemonize';
2008
2009 push @$cmd, '-incoming', $migrate_uri if $migrate_uri;
2010
2011 my $use_usb2 = 0;
2012 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2013 next if !$conf->{"usb$i"};
2014 $use_usb2 = 1;
2015 }
2016 # include usb device config
2017 push @$cmd, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2018
2019 # enable absolute mouse coordinates (needed by vnc)
2020 my $tablet = defined($conf->{tablet}) ? $conf->{tablet} : $defaults->{tablet};
2021 if ($tablet) {
2022 if ($use_usb2) {
2023 push @$cmd, '-device', 'usb-tablet,bus=ehci.0,port=6';
2024 } else {
2025 push @$cmd, '-usbdevice', 'tablet';
2026 }
2027 }
2028
2029 # host pci devices
2030 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2031 my $d = parse_hostpci($conf->{"hostpci$i"});
2032 next if !$d;
2033 $pciaddr = print_pci_addr("hostpci$i");
2034 push @$cmd, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2035 }
2036
2037 # usb devices
2038 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2039 my $d = parse_usb_device($conf->{"usb$i"});
2040 next if !$d;
2041 if ($d->{vendorid} && $d->{productid}) {
2042 push @$cmd, '-device', "usb-host,vendorid=$d->{vendorid},productid=$d->{productid}";
2043 } elsif (defined($d->{hostbus}) && defined($d->{hostport})) {
2044 push @$cmd, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2045 }
2046 }
2047
2048 # serial devices
2049 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2050 if (my $path = $conf->{"serial$i"}) {
2051 die "no such serial device\n" if ! -c $path;
2052 push @$cmd, '-chardev', "tty,id=serial$i,path=$path";
2053 push @$cmd, '-device', "isa-serial,chardev=serial$i";
2054 }
2055 }
2056
2057 # parallel devices
2058 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2059 if (my $path = $conf->{"parallel$i"}) {
2060 die "no such parallel device\n" if ! -c $path;
2061 push @$cmd, '-chardev', "parport,id=parallel$i,path=$path";
2062 push @$cmd, '-device', "isa-parallel,chardev=parallel$i";
2063 }
2064 }
2065
2066 my $vmname = $conf->{name} || "vm$vmid";
2067
2068 push @$cmd, '-name', $vmname;
2069
2070 my $sockets = 1;
2071 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
2072 $sockets = $conf->{sockets} if $conf->{sockets};
2073
2074 my $cores = $conf->{cores} || 1;
2075
2076 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2077
2078 push @$cmd, '-cpu', $conf->{cpu} if $conf->{cpu};
2079
2080 push @$cmd, '-nodefaults';
2081
2082 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
2083
2084 my $bootindex_hash = {};
2085 my $i = 1;
2086 foreach my $o (split(//, $bootorder)) {
2087 $bootindex_hash->{$o} = $i*100;
2088 $i++;
2089 }
2090
2091 push @$cmd, '-boot', "menu=on";
2092
2093 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
2094
2095 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
2096
2097 my $vga = $conf->{vga};
2098 if (!$vga) {
2099 if ($conf->{ostype} && ($conf->{ostype} eq 'win7' || $conf->{ostype} eq 'w2k8')) {
2100 $vga = 'std';
2101 } else {
2102 $vga = 'cirrus';
2103 }
2104 }
2105
2106 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2107
2108 # time drift fix
2109 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
2110 push @$cmd, '-tdf' if $tdf;
2111
2112 my $nokvm = defined($conf->{kvm}) && $conf->{kvm} == 0 ? 1 : 0;
2113
2114 if (my $ost = $conf->{ostype}) {
2115 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2116
2117 if ($ost =~ m/^w/) { # windows
2118 push @$cmd, '-localtime' if !defined($conf->{localtime});
2119
2120 # use rtc-td-hack when acpi is enabled
2121 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
2122 push @$cmd, '-rtc-td-hack';
2123 }
2124 }
2125
2126 # -tdf ?
2127 # -no-acpi
2128 # -no-kvm
2129 # -win2k-hack ?
2130 }
2131
2132 if ($nokvm) {
2133 push @$cmd, '-no-kvm';
2134 } else {
2135 die "No accelerator found!\n" if !$cpuinfo->{hvm};
2136 }
2137
2138 push @$cmd, '-localtime' if $conf->{localtime};
2139
2140 push @$cmd, '-startdate', $conf->{startdate} if $conf->{startdate};
2141
2142 push @$cmd, '-S' if $conf->{freeze};
2143
2144 # set keyboard layout
2145 my $kb = $conf->{keyboard} || $defaults->{keyboard};
2146 push @$cmd, '-k', $kb if $kb;
2147
2148 # enable sound
2149 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2150 #push @$cmd, '-soundhw', 'es1370';
2151 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2152 $pciaddr = print_pci_addr("balloon0");
2153 push @$cmd, '-device', "virtio-balloon-pci,id=balloon0$pciaddr" if $conf->{balloon};
2154
2155 if ($conf->{watchdog}) {
2156 my $wdopts = parse_watchdog($conf->{watchdog});
2157 $pciaddr = print_pci_addr("watchdog");
2158 my $watchdog = $wdopts->{model} || 'i6300esb';
2159 push @$cmd, '-device', "$watchdog$pciaddr";
2160 push @$cmd, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
2161 }
2162
2163 my $vollist = [];
2164 my $scsicontroller = {};
2165
2166 foreach_drive($conf, sub {
2167 my ($ds, $drive) = @_;
2168
2169 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
2170 push @$vollist, $drive->{file};
2171 }
2172
2173 $use_virtio = 1 if $ds =~ m/^virtio/;
2174
2175 if (drive_is_cdrom ($drive)) {
2176 if ($bootindex_hash->{d}) {
2177 $drive->{bootindex} = $bootindex_hash->{d};
2178 $bootindex_hash->{d} += 1;
2179 }
2180 } else {
2181 if ($bootindex_hash->{c}) {
2182 $drive->{bootindex} = $bootindex_hash->{c} if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
2183 $bootindex_hash->{c} += 1;
2184 }
2185 }
2186
2187 if ($drive->{interface} eq 'scsi') {
2188 my $maxdev = 7;
2189 my $controller = int($drive->{index} / $maxdev);
2190 $pciaddr = print_pci_addr("lsi$controller");
2191 push @$cmd, '-device', "lsi,id=lsi$controller$pciaddr" if !$scsicontroller->{$controller};
2192 $scsicontroller->{$controller}=1;
2193 }
2194
2195 push @$cmd, '-drive', print_drive_full($storecfg, $vmid, $drive);
2196 push @$cmd, '-device',print_drivedevice_full($storecfg,$vmid, $drive);
2197 });
2198
2199 push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
2200
2201 for (my $i = 0; $i < $MAX_NETS; $i++) {
2202 next if !$conf->{"net$i"};
2203 my $d = parse_net($conf->{"net$i"});
2204 next if !$d;
2205
2206 $use_virtio = 1 if $d->{model} eq 'virtio';
2207
2208 if ($bootindex_hash->{n}) {
2209 $d->{bootindex} = $bootindex_hash->{n};
2210 $bootindex_hash->{n} += 1;
2211 }
2212
2213 my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i");
2214 push @$cmd, '-netdev', $netdevfull;
2215
2216 my $netdevicefull = print_netdevice_full($vmid,$conf,$d,"net$i");
2217 push @$cmd, '-device', $netdevicefull;
2218 }
2219
2220
2221 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2222 # when the VM uses virtio devices.
2223 if (!$use_virtio && $have_ovz) {
2224
2225 my $cpuunits = defined($conf->{cpuunits}) ?
2226 $conf->{cpuunits} : $defaults->{cpuunits};
2227
2228 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2229
2230 # fixme: cpulimit is currently ignored
2231 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2232 }
2233
2234 # add custom args
2235 if ($conf->{args}) {
2236 my $aa = PVE::Tools::split_args($conf->{args});
2237 push @$cmd, @$aa;
2238 }
2239
2240 return wantarray ? ($cmd, $vollist) : $cmd;
2241}
2242
2243sub vnc_socket {
2244 my ($vmid) = @_;
2245 return "${var_run_tmpdir}/$vmid.vnc";
2246}
2247
2248sub monitor_socket {
2249 my ($vmid) = @_;
2250 return "${var_run_tmpdir}/$vmid.mon";
2251}
2252
2253sub pidfile_name {
2254 my ($vmid) = @_;
2255 return "${var_run_tmpdir}/$vmid.pid";
2256}
2257
2258sub next_migrate_port {
2259
2260 for (my $p = 60000; $p < 60010; $p++) {
2261
2262 my $sock = IO::Socket::INET->new(Listen => 5,
2263 LocalAddr => 'localhost',
2264 LocalPort => $p,
2265 ReuseAddr => 1,
2266 Proto => 0);
2267
2268 if ($sock) {
2269 close($sock);
2270 return $p;
2271 }
2272 }
2273
2274 die "unable to find free migration port";
2275}
2276
2277sub vm_devices_list {
2278 my ($vmid) = @_;
2279
2280 my $res = vm_monitor_command ($vmid, "info pci");
2281
2282 my @lines = split ("\n", $res);
2283 my $devices;
2284 my $bus;
2285 my $addr;
2286 my $id;
2287
2288 foreach my $line (@lines) {
2289 $line =~ s/^\s+//;
2290 if ($line =~ m/^Bus (\d+), device (\d+), function (\d+):$/) {
2291 $bus=$1;
2292 $addr=$2;
2293 }
2294 if ($line =~ m/^id "([a-z][a-z_\-]*\d*)"$/) {
2295 $id=$1;
2296 $devices->{$id}->{bus}=$bus;
2297 $devices->{$id}->{addr}=$addr;
2298 }
2299 }
2300
2301 return $devices;
2302}
2303
2304sub vm_deviceplug {
2305 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2306 return 1 if !check_running($vmid) || !$conf->{hotplug};
2307
2308 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2309 return undef if !qemu_driveadd($storecfg, $vmid, $device);
2310 my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
2311 qemu_deviceadd($vmid, $devicefull);
2312 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2313 qemu_drivedel($vmid, $deviceid);
2314 return undef;
2315 }
2316 }
2317
2318 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2319 my $pciaddr = print_pci_addr($deviceid);
2320 my $devicefull = "lsi,id=$deviceid$pciaddr";
2321 qemu_deviceadd($vmid, $devicefull);
2322 return undef if(!qemu_deviceaddverify($vmid, $deviceid));
2323 }
2324
2325 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2326 return undef if !qemu_findorcreatelsi($storecfg,$conf, $vmid, $device);
2327 return undef if !qemu_driveadd($storecfg, $vmid, $device);
2328 my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
2329 if(!qemu_deviceadd($vmid, $devicefull)) {
2330 qemu_drivedel($vmid, $deviceid);
2331 return undef;
2332 }
2333 }
2334
2335 if ($deviceid =~ m/^(net)(\d+)$/) {
2336 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
2337 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid);
2338 qemu_deviceadd($vmid, $netdevicefull);
2339 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2340 qemu_netdevdel($vmid, $deviceid);
2341 return undef;
2342 }
2343 }
2344
2345 return 1;
2346}
2347
2348sub vm_deviceunplug {
2349 my ($vmid, $conf, $deviceid) = @_;
2350
2351 return 1 if !check_running ($vmid) || !$conf->{hotplug};
2352
2353 die "can't unplug bootdisk" if $conf->{bootdisk} eq $deviceid;
2354
2355 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2356 return undef if !qemu_drivedel($vmid, $deviceid);
2357 qemu_devicedel($vmid, $deviceid);
2358 return undef if !qemu_devicedelverify($vmid, $deviceid);
2359 }
2360
2361 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2362 return undef if !qemu_devicedel($vmid, $deviceid);
2363 }
2364
2365 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2366 return undef if !qemu_devicedel($vmid, $deviceid);
2367 return undef if !qemu_drivedel($vmid, $deviceid);
2368 }
2369
2370 if ($deviceid =~ m/^(net)(\d+)$/) {
2371 return undef if !qemu_netdevdel($vmid, $deviceid);
2372 qemu_devicedel($vmid, $deviceid);
2373 return undef if !qemu_devicedelverify($vmid, $deviceid);
2374 }
2375
2376 return 1;
2377}
2378
2379sub qemu_deviceadd {
2380 my ($vmid, $devicefull) = @_;
2381
2382 my $ret = vm_monitor_command($vmid, "device_add $devicefull");
2383 $ret =~ s/^\s+//;
2384 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2385 return 1 if $ret eq "";
2386 syslog("err", "error on hotplug device : $ret");
2387 return undef;
2388
2389}
2390
2391sub qemu_devicedel {
2392 my($vmid, $deviceid) = @_;
2393
2394 my $ret = vm_monitor_command($vmid, "device_del $deviceid");
2395 $ret =~ s/^\s+//;
2396 return 1 if $ret eq "";
2397 syslog("err", "detaching device $deviceid failed : $ret");
2398 return undef;
2399}
2400
2401sub qemu_driveadd {
2402 my($storecfg, $vmid, $device) = @_;
2403
2404 my $drive = print_drive_full($storecfg, $vmid, $device);
2405 my $ret = vm_monitor_command($vmid, "drive_add auto $drive");
2406 # If the command succeeds qemu prints: "OK"
2407 if ($ret !~ m/OK/s) {
2408 syslog("err", "adding drive failed: $ret");
2409 return undef;
2410 }
2411 return 1;
2412}
2413
2414sub qemu_drivedel {
2415 my($vmid, $deviceid) = @_;
2416
2417 my $ret = vm_monitor_command($vmid, "drive_del drive-$deviceid");
2418 $ret =~ s/^\s+//;
2419 if ($ret =~ m/Device \'.*?\' not found/s) {
2420 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2421 }
2422 elsif ($ret ne "") {
2423 syslog("err", "deleting drive $deviceid failed : $ret");
2424 return undef;
2425 }
2426 return 1;
2427}
2428
2429sub qemu_deviceaddverify {
2430 my ($vmid,$deviceid) = @_;
2431
2432 for (my $i = 0; $i <= 5; $i++) {
2433 my $devices_list = vm_devices_list($vmid);
2434 return 1 if defined($devices_list->{$deviceid});
2435 sleep 1;
2436 }
2437 syslog("err", "error on hotplug device $deviceid");
2438 return undef;
2439}
2440
2441
2442sub qemu_devicedelverify {
2443 my ($vmid,$deviceid) = @_;
2444
2445 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2446 for (my $i = 0; $i <= 5; $i++) {
2447 my $devices_list = vm_devices_list($vmid);
2448 return 1 if !defined($devices_list->{$deviceid});
2449 sleep 1;
2450 }
2451 syslog("err", "error on hot-unplugging device $deviceid");
2452 return undef;
2453}
2454
2455sub qemu_findorcreatelsi {
2456 my ($storecfg, $conf, $vmid, $device) = @_;
2457
2458 my $maxdev = 7;
2459 my $controller = int($device->{index} / $maxdev);
2460 my $lsiid="lsi$controller";
2461 my $devices_list = vm_devices_list($vmid);
2462
2463 if(!defined($devices_list->{$lsiid})) {
2464 return undef if !vm_deviceplug($storecfg, $conf, $vmid, $lsiid);
2465 }
2466 return 1;
2467}
2468
2469sub qemu_netdevadd {
2470 my ($vmid, $conf, $device, $deviceid) = @_;
2471
2472 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
2473 my $ret = vm_monitor_command($vmid, "netdev_add $netdev");
2474 $ret =~ s/^\s+//;
2475
2476 #if the command succeeds, no output is sent. So any non-empty string shows an error
2477 return 1 if $ret eq "";
2478 syslog("err", "adding netdev failed: $ret");
2479 return undef;
2480}
2481
2482sub qemu_netdevdel {
2483 my ($vmid, $deviceid) = @_;
2484
2485 my $ret = vm_monitor_command($vmid, "netdev_del $deviceid");
2486 $ret =~ s/^\s+//;
2487 #if the command succeeds, no output is sent. So any non-empty string shows an error
2488 return 1 if $ret eq "";
2489 syslog("err", "deleting netdev failed: $ret");
2490 return undef;
2491}
2492
2493sub vm_start {
2494 my ($storecfg, $vmid, $statefile, $skiplock) = @_;
2495
2496 lock_config($vmid, sub {
2497 my $conf = load_config($vmid);
2498
2499 check_lock($conf) if !$skiplock;
2500
2501 die "VM $vmid already running\n" if check_running($vmid);
2502
2503 my $migrate_uri;
2504 my $migrate_port = 0;
2505
2506 if ($statefile) {
2507 if ($statefile eq 'tcp') {
2508 $migrate_port = next_migrate_port();
2509 $migrate_uri = "tcp:localhost:${migrate_port}";
2510 } else {
2511 if (-f $statefile) {
2512 $migrate_uri = "exec:cat $statefile";
2513 } else {
2514 warn "state file '$statefile' does not exist - doing normal startup\n";
2515 }
2516 }
2517 }
2518
2519 my $defaults = load_defaults();
2520
2521 my ($cmd, $vollist) = config_to_command($storecfg, $vmid, $conf, $defaults, $migrate_uri);
2522 # host pci devices
2523 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2524 my $d = parse_hostpci($conf->{"hostpci$i"});
2525 next if !$d;
2526 my $info = pci_device_info("0000:$d->{pciid}");
2527 die "IOMMU not present\n" if !check_iommu_support();
2528 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2529 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub($info);
2530 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset($info);
2531 }
2532
2533 PVE::Storage::activate_volumes($storecfg, $vollist);
2534
2535 eval { run_command($cmd, timeout => $migrate_uri ? undef : 30); };
2536 my $err = $@;
2537 die "start failed: $err" if $err;
2538
2539 if ($statefile) {
2540
2541 if ($statefile eq 'tcp') {
2542 print "migration listens on port $migrate_port\n";
2543 } else {
2544 unlink $statefile;
2545 # fixme: send resume - is that necessary ?
2546 eval { vm_monitor_command($vmid, "cont"); };
2547 }
2548 }
2549
2550 # always set migrate speed (overwrite kvm default of 32m)
2551 # we set a very hight default of 8192m which is basically unlimited
2552 my $migrate_speed = $defaults->{migrate_speed} || 8192;
2553 $migrate_speed = $conf->{migrate_speed} || $migrate_speed;
2554 eval {
2555 my $cmd = "migrate_set_speed ${migrate_speed}m";
2556 vm_monitor_command($vmid, $cmd);
2557 };
2558
2559 if (my $migrate_downtime =
2560 $conf->{migrate_downtime} || $defaults->{migrate_downtime}) {
2561 my $cmd = "migrate_set_downtime ${migrate_downtime}";
2562 eval { vm_monitor_command($vmid, $cmd); };
2563 }
2564
2565 vm_balloonset($vmid, $conf->{balloon}) if $conf->{balloon};
2566 });
2567}
2568
2569sub __read_avail {
2570 my ($fh, $timeout) = @_;
2571
2572 my $sel = new IO::Select;
2573 $sel->add($fh);
2574
2575 my $res = '';
2576 my $buf;
2577
2578 my @ready;
2579 while (scalar (@ready = $sel->can_read($timeout))) {
2580 my $count;
2581 if ($count = $fh->sysread($buf, 8192)) {
2582 if ($buf =~ /^(.*)\(qemu\) $/s) {
2583 $res .= $1;
2584 last;
2585 } else {
2586 $res .= $buf;
2587 }
2588 } else {
2589 if (!defined($count)) {
2590 die "$!\n";
2591 }
2592 last;
2593 }
2594 }
2595
2596 die "monitor read timeout\n" if !scalar(@ready);
2597
2598 return $res;
2599}
2600
2601sub vm_monitor_command {
2602 my ($vmid, $cmdstr, $nocheck) = @_;
2603
2604 my $res;
2605
2606 eval {
2607 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
2608
2609 my $sname = monitor_socket($vmid);
2610
2611 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
2612 die "unable to connect to VM $vmid socket - $!\n";
2613
2614 my $timeout = 3;
2615
2616 # hack: migrate sometime blocks the monitor (when migrate_downtime
2617 # is set)
2618 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2619 $timeout = 60*60; # 1 hour
2620 }
2621
2622 # read banner;
2623 my $data = __read_avail($sock, $timeout);
2624
2625 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2626 die "got unexpected qemu monitor banner\n";
2627 }
2628
2629 my $sel = new IO::Select;
2630 $sel->add($sock);
2631
2632 if (!scalar(my @ready = $sel->can_write($timeout))) {
2633 die "monitor write error - timeout";
2634 }
2635
2636 my $fullcmd = "$cmdstr\r";
2637
2638 my $b;
2639 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2640 die "monitor write error - $!";
2641 }
2642
2643 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2644
2645 $timeout = 20;
2646
2647 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2648 $timeout = 60*60; # 1 hour
2649 } elsif ($cmdstr =~ m/^(eject|change)/) {
2650 $timeout = 60; # note: cdrom mount command is slow
2651 }
2652 if ($res = __read_avail($sock, $timeout)) {
2653
2654 my @lines = split("\r?\n", $res);
2655
2656 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2657
2658 $res = join("\n", @lines);
2659 $res .= "\n";
2660 }
2661 };
2662
2663 my $err = $@;
2664
2665 if ($err) {
2666 syslog("err", "VM $vmid monitor command failed - $err");
2667 die $err;
2668 }
2669
2670 return $res;
2671}
2672
2673sub vm_commandline {
2674 my ($storecfg, $vmid) = @_;
2675
2676 my $conf = load_config($vmid);
2677
2678 my $defaults = load_defaults();
2679
2680 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
2681
2682 return join(' ', @$cmd);
2683}
2684
2685sub vm_reset {
2686 my ($vmid, $skiplock) = @_;
2687
2688 lock_config($vmid, sub {
2689
2690 my $conf = load_config($vmid);
2691
2692 check_lock($conf) if !$skiplock;
2693
2694 vm_monitor_command($vmid, "system_reset");
2695 });
2696}
2697
2698sub get_vm_volumes {
2699 my ($conf) = @_;
2700
2701 my $vollist = [];
2702 foreach_drive($conf, sub {
2703 my ($ds, $drive) = @_;
2704
2705 my ($sid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
2706 return if !$sid;
2707
2708 my $volid = $drive->{file};
2709 return if !$volid || $volid =~ m|^/|;
2710
2711 push @$vollist, $volid;
2712 });
2713
2714 return $vollist;
2715}
2716
2717sub vm_stop_cleanup {
2718 my ($storecfg, $vmid, $conf, $keepActive) = @_;
2719
2720 eval {
2721 fairsched_rmnod($vmid); # try to destroy group
2722
2723 if (!$keepActive) {
2724 my $vollist = get_vm_volumes($conf);
2725 PVE::Storage::deactivate_volumes($storecfg, $vollist);
2726 }
2727 };
2728 warn $@ if $@; # avoid errors - just warn
2729}
2730
2731# Note: use $nockeck to skip tests if VM configuration file exists.
2732# We need that when migration VMs to other nodes (files already moved)
2733# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
2734sub vm_stop {
2735 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive) = @_;
2736
2737 $timeout = 60 if !defined($timeout);
2738
2739 $force = 1 if !defined($force) && !$shutdown;
2740
2741 lock_config($vmid, sub {
2742
2743 my $pid = check_running($vmid, $nocheck);
2744 return if !$pid;
2745
2746 my $conf;
2747 if (!$nocheck) {
2748 $conf = load_config($vmid);
2749 check_lock($conf) if !$skiplock;
2750 }
2751
2752 eval {
2753 if ($shutdown) {
2754 vm_monitor_command($vmid, "system_powerdown", $nocheck);
2755 } else {
2756 vm_monitor_command($vmid, "quit", $nocheck);
2757 }
2758 };
2759 my $err = $@;
2760
2761 if (!$err) {
2762 my $count = 0;
2763 while (($count < $timeout) && check_running($vmid, $nocheck)) {
2764 $count++;
2765 sleep 1;
2766 }
2767
2768 if ($count >= $timeout) {
2769 if ($force) {
2770 warn "VM still running - terminating now with SIGTERM\n";
2771 kill 15, $pid;
2772 } else {
2773 die "VM quit/powerdown failed - got timeout\n";
2774 }
2775 } else {
2776 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
2777 return;
2778 }
2779 } else {
2780 if ($force) {
2781 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
2782 kill 15, $pid;
2783 } else {
2784 die "VM quit/powerdown failed\n";
2785 }
2786 }
2787
2788 # wait again
2789 $timeout = 10;
2790
2791 my $count = 0;
2792 while (($count < $timeout) && check_running($vmid, $nocheck)) {
2793 $count++;
2794 sleep 1;
2795 }
2796
2797 if ($count >= $timeout) {
2798 warn "VM still running - terminating now with SIGKILL\n";
2799 kill 9, $pid;
2800 sleep 1;
2801 }
2802
2803 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
2804 });
2805}
2806
2807sub vm_suspend {
2808 my ($vmid, $skiplock) = @_;
2809
2810 lock_config($vmid, sub {
2811
2812 my $conf = load_config($vmid);
2813
2814 check_lock($conf) if !$skiplock;
2815
2816 vm_monitor_command($vmid, "stop");
2817 });
2818}
2819
2820sub vm_resume {
2821 my ($vmid, $skiplock) = @_;
2822
2823 lock_config($vmid, sub {
2824
2825 my $conf = load_config($vmid);
2826
2827 check_lock($conf) if !$skiplock;
2828
2829 vm_monitor_command($vmid, "cont");
2830 });
2831}
2832
2833sub vm_sendkey {
2834 my ($vmid, $skiplock, $key) = @_;
2835
2836 lock_config($vmid, sub {
2837
2838 my $conf = load_config($vmid);
2839
2840 vm_monitor_command($vmid, "sendkey $key");
2841 });
2842}
2843
2844sub vm_destroy {
2845 my ($storecfg, $vmid, $skiplock) = @_;
2846
2847 lock_config($vmid, sub {
2848
2849 my $conf = load_config($vmid);
2850
2851 check_lock($conf) if !$skiplock;
2852
2853 if (!check_running($vmid)) {
2854 fairsched_rmnod($vmid); # try to destroy group
2855 destroy_vm($storecfg, $vmid);
2856 } else {
2857 die "VM $vmid is running - destroy failed\n";
2858 }
2859 });
2860}
2861
2862sub vm_stopall {
2863 my ($storecfg, $timeout) = @_;
2864
2865 $timeout = 3*60 if !$timeout;
2866
2867 my $cleanuphash = {};
2868
2869 my $vzlist = vzlist();
2870 my $count = 0;
2871 foreach my $vmid (keys %$vzlist) {
2872 next if !$vzlist->{$vmid}->{pid};
2873 $count++;
2874 $cleanuphash->{$vmid} = 1;
2875 }
2876
2877 return if !$count;
2878
2879 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs\n";
2880 syslog('info', $msg);
2881 warn $msg;
2882
2883 foreach my $vmid (keys %$vzlist) {
2884 next if !$vzlist->{$vmid}->{pid};
2885 eval { vm_monitor_command($vmid, "system_powerdown"); };
2886 warn $@ if $@;
2887 }
2888
2889 my $wt = 5;
2890 my $maxtries = int(($timeout + $wt -1)/$wt);
2891 my $try = 0;
2892 while (($try < $maxtries) && $count) {
2893 $try++;
2894 sleep $wt;
2895
2896 $vzlist = vzlist();
2897 $count = 0;
2898 foreach my $vmid (keys %$vzlist) {
2899 next if !$vzlist->{$vmid}->{pid};
2900 $count++;
2901 }
2902 last if !$count;
2903 }
2904
2905 if ($count) {
2906
2907 foreach my $vmid (keys %$vzlist) {
2908 next if !$vzlist->{$vmid}->{pid};
2909
2910 warn "VM $vmid still running - sending stop now\n";
2911 eval { vm_monitor_command($vmid, "quit"); };
2912 warn $@ if $@;
2913 }
2914
2915 $timeout = 30;
2916 $maxtries = int(($timeout + $wt -1)/$wt);
2917 $try = 0;
2918 while (($try < $maxtries) && $count) {
2919 $try++;
2920 sleep $wt;
2921
2922 $vzlist = vzlist();
2923 $count = 0;
2924 foreach my $vmid (keys %$vzlist) {
2925 next if !$vzlist->{$vmid}->{pid};
2926 $count++;
2927 }
2928 last if !$count;
2929 }
2930
2931 if ($count) {
2932
2933 foreach my $vmid (keys %$vzlist) {
2934 next if !$vzlist->{$vmid}->{pid};
2935
2936 warn "VM $vmid still running - terminating now with SIGTERM\n";
2937 kill 15, $vzlist->{$vmid}->{pid};
2938 }
2939 sleep 1;
2940 }
2941
2942 # this is called by system shotdown scripts, so remaining
2943 # processes gets killed anyways (no need to send kill -9 here)
2944 }
2945
2946 $vzlist = vzlist();
2947 foreach my $vmid (keys %$cleanuphash) {
2948 next if $vzlist->{$vmid}->{pid};
2949 eval {
2950 my $conf = load_config($vmid);
2951 vm_stop_cleanup($storecfg, $vmid, $conf);
2952 };
2953 warn $@ if $@;
2954 }
2955
2956 $msg = "Qemu Server stopped\n";
2957 syslog('info', $msg);
2958 print $msg;
2959}
2960
2961# pci helpers
2962
2963sub file_write {
2964 my ($filename, $buf) = @_;
2965
2966 my $fh = IO::File->new($filename, "w");
2967 return undef if !$fh;
2968
2969 my $res = print $fh $buf;
2970
2971 $fh->close();
2972
2973 return $res;
2974}
2975
2976sub pci_device_info {
2977 my ($name) = @_;
2978
2979 my $res;
2980
2981 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
2982 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
2983
2984 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
2985 return undef if !defined($irq) || $irq !~ m/^\d+$/;
2986
2987 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
2988 return undef if !defined($vendor) || $vendor !~ s/^0x//;
2989
2990 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
2991 return undef if !defined($product) || $product !~ s/^0x//;
2992
2993 $res = {
2994 name => $name,
2995 vendor => $vendor,
2996 product => $product,
2997 domain => $domain,
2998 bus => $bus,
2999 slot => $slot,
3000 func => $func,
3001 irq => $irq,
3002 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
3003 };
3004
3005 return $res;
3006}
3007
3008sub pci_dev_reset {
3009 my ($dev) = @_;
3010
3011 my $name = $dev->{name};
3012
3013 my $fn = "$pcisysfs/devices/$name/reset";
3014
3015 return file_write($fn, "1");
3016}
3017
3018sub pci_dev_bind_to_stub {
3019 my ($dev) = @_;
3020
3021 my $name = $dev->{name};
3022
3023 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3024 return 1 if -d $testdir;
3025
3026 my $data = "$dev->{vendor} $dev->{product}";
3027 return undef if !file_write("$pcisysfs/drivers/pci-stub/new_id", $data);
3028
3029 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3030 if (!file_write($fn, $name)) {
3031 return undef if -f $fn;
3032 }
3033
3034 $fn = "$pcisysfs/drivers/pci-stub/bind";
3035 if (! -d $testdir) {
3036 return undef if !file_write($fn, $name);
3037 }
3038
3039 return -d $testdir;
3040}
3041
3042sub print_pci_addr {
3043 my ($id) = @_;
3044
3045 my $res = '';
3046 my $devices = {
3047 #addr1 : ide,parallel,serial (motherboard)
3048 #addr2 : first videocard
3049 balloon0 => { bus => 0, addr => 3 },
3050 watchdog => { bus => 0, addr => 4 },
3051 lsi0 => { bus => 0, addr => 5 },
3052 lsi1 => { bus => 0, addr => 6 },
3053 virtio0 => { bus => 0, addr => 10 },
3054 virtio1 => { bus => 0, addr => 11 },
3055 virtio2 => { bus => 0, addr => 12 },
3056 virtio3 => { bus => 0, addr => 13 },
3057 virtio4 => { bus => 0, addr => 14 },
3058 virtio5 => { bus => 0, addr => 15 },
3059 hostpci0 => { bus => 0, addr => 16 },
3060 hostpci1 => { bus => 0, addr => 17 },
3061 net0 => { bus => 0, addr => 18 },
3062 net1 => { bus => 0, addr => 19 },
3063 net2 => { bus => 0, addr => 20 },
3064 net3 => { bus => 0, addr => 21 },
3065 net4 => { bus => 0, addr => 22 },
3066 net5 => { bus => 0, addr => 23 },
3067 #addr29 : usb-host (pve-usb.cfg)
3068 };
3069
3070 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
3071 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
3072 $res = ",bus=pci.$devices->{$id}->{bus},addr=$addr";
3073 }
3074 return $res;
3075
3076}
3077
3078sub vm_balloonset {
3079 my ($vmid, $value) = @_;
3080
3081 vm_monitor_command($vmid, "balloon $value");
3082}
3083
3084# vzdump restore implementaion
3085
3086sub archive_read_firstfile {
3087 my $archive = shift;
3088
3089 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
3090
3091 # try to detect archive type first
3092 my $pid = open (TMP, "tar tf '$archive'|") ||
3093 die "unable to open file '$archive'\n";
3094 my $firstfile = <TMP>;
3095 kill 15, $pid;
3096 close TMP;
3097
3098 die "ERROR: archive contaions no data\n" if !$firstfile;
3099 chomp $firstfile;
3100
3101 return $firstfile;
3102}
3103
3104sub restore_cleanup {
3105 my $statfile = shift;
3106
3107 print STDERR "starting cleanup\n";
3108
3109 if (my $fd = IO::File->new($statfile, "r")) {
3110 while (defined(my $line = <$fd>)) {
3111 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3112 my $volid = $2;
3113 eval {
3114 if ($volid =~ m|^/|) {
3115 unlink $volid || die 'unlink failed\n';
3116 } else {
3117 my $cfg = cfs_read_file('storage.cfg');
3118 PVE::Storage::vdisk_free($cfg, $volid);
3119 }
3120 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3121 };
3122 print STDERR "unable to cleanup '$volid' - $@" if $@;
3123 } else {
3124 print STDERR "unable to parse line in statfile - $line";
3125 }
3126 }
3127 $fd->close();
3128 }
3129}
3130
3131sub restore_archive {
3132 my ($archive, $vmid, $opts) = @_;
3133
3134 if ($archive ne '-') {
3135 my $firstfile = archive_read_firstfile($archive);
3136 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
3137 if $firstfile ne 'qemu-server.conf';
3138 }
3139
3140 my $tocmd = "/usr/lib/qemu-server/qmextract";
3141
3142 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
3143 $tocmd .= ' --prealloc' if $opts->{prealloc};
3144 $tocmd .= ' --info' if $opts->{info};
3145
3146 # tar option "xf" does not autodetect compression when read fron STDIN,
3147 # so we pipe to zcat
3148 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
3149 PVE::Tools::shellquote("--to-command=$tocmd");
3150
3151 my $tmpdir = "/var/tmp/vzdumptmp$$";
3152 mkpath $tmpdir;
3153
3154 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
3155 local $ENV{VZDUMP_VMID} = $vmid;
3156
3157 my $conffile = PVE::QemuServer::config_file($vmid);
3158 my $tmpfn = "$conffile.$$.tmp";
3159
3160 # disable interrupts (always do cleanups)
3161 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
3162 print STDERR "got interrupt - ignored\n";
3163 };
3164
3165 eval {
3166 # enable interrupts
3167 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
3168 die "interrupted by signal\n";
3169 };
3170
3171 if ($archive eq '-') {
3172 print "extracting archive from STDIN\n";
3173 run_command($cmd, input => "<&STDIN");
3174 } else {
3175 print "extracting archive '$archive'\n";
3176 run_command($cmd);
3177 }
3178
3179 return if $opts->{info};
3180
3181 # read new mapping
3182 my $map = {};
3183 my $statfile = "$tmpdir/qmrestore.stat";
3184 if (my $fd = IO::File->new($statfile, "r")) {
3185 while (defined (my $line = <$fd>)) {
3186 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3187 $map->{$1} = $2 if $1;
3188 } else {
3189 print STDERR "unable to parse line in statfile - $line\n";
3190 }
3191 }
3192 $fd->close();
3193 }
3194
3195 my $confsrc = "$tmpdir/qemu-server.conf";
3196
3197 my $srcfd = new IO::File($confsrc, "r") ||
3198 die "unable to open file '$confsrc'\n";
3199
3200 my $outfd = new IO::File ($tmpfn, "w") ||
3201 die "unable to write config for VM $vmid\n";
3202
3203 my $netcount = 0;
3204
3205 while (defined (my $line = <$srcfd>)) {
3206 next if $line =~ m/^\#vzdump\#/;
3207 next if $line =~ m/^lock:/;
3208 next if $line =~ m/^unused\d+:/;
3209
3210 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3211 # try to convert old 1.X settings
3212 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3213 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
3214 my ($model, $macaddr) = split(/\=/, $devconfig);
3215 $macaddr = PVE::Tools::random_ether_addr() if !$macaddr || $opts->{unique};
3216 my $net = {
3217 model => $model,
3218 bridge => "vmbr$ind",
3219 macaddr => $macaddr,
3220 };
3221 my $netstr = print_net($net);
3222 print $outfd "net${netcount}: $netstr\n";
3223 $netcount++;
3224 }
3225 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && ($opts->{unique})) {
3226 my ($id, $netstr) = ($1, $2);
3227 my $net = parse_net($netstr);
3228 $net->{macaddr} = PVE::Tools::random_ether_addr() if $net->{macaddr};
3229 $netstr = print_net($net);
3230 print $outfd "$id: $netstr\n";
3231 } elsif ($line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/) {
3232 my $virtdev = $1;
3233 my $value = $2;
3234 if ($line =~ m/backup=no/) {
3235 print $outfd "#$line";
3236 } elsif ($virtdev && $map->{$virtdev}) {
3237 my $di = PVE::QemuServer::parse_drive($virtdev, $value);
3238 $di->{file} = $map->{$virtdev};
3239 $value = PVE::QemuServer::print_drive($vmid, $di);
3240 print $outfd "$virtdev: $value\n";
3241 } else {
3242 print $outfd $line;
3243 }
3244 } else {
3245 print $outfd $line;
3246 }
3247 }
3248
3249 $srcfd->close();
3250 $outfd->close();
3251 };
3252 my $err = $@;
3253
3254 if ($err) {
3255
3256 unlink $tmpfn;
3257
3258 restore_cleanup("$tmpdir/qmrestore.stat") if !$opts->{info};
3259
3260 die $err;
3261 }
3262
3263 rmtree $tmpdir;
3264
3265 rename $tmpfn, $conffile ||
3266 die "unable to commit configuration file '$conffile'\n";
3267};
3268
32691;