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