]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
add qemu_netdevadd, qemu_netdevdel and add them in hotplug code
[qemu-server.git] / PVE / QemuServer.pm
CommitLineData
1e3baf05
DM
1package PVE::QemuServer;
2
3use strict;
4use POSIX;
5use IO::Handle;
6use IO::Select;
7use IO::File;
8use IO::Dir;
9use IO::Socket::UNIX;
10use File::Basename;
11use File::Path;
12use File::stat;
13use Getopt::Long;
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;
6b64503e 27use Time::HiRes qw(gettimeofday);
1e3baf05 28
7f0b5beb 29my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
1e3baf05 30
19672434 31# Note about locking: we use flock on the config file protect
1e3baf05
DM
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
19672434 38cfs_register_file('/qemu-server/', \&parse_vm_config);
1e3baf05 39
3ea94c60
DM
40PVE::JSONSchema::register_standard_option('skiplock', {
41 description => "Ignore locks - only root is allowed to use this option.",
afdb31d5 42 type => 'boolean',
3ea94c60
DM
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
1e3baf05
DM
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
6b64503e 87 return syscall(&__NR_fairsched_mknod, int($parent), int($weight), int($desired));
1e3baf05
DM
88}
89
90sub fairsched_rmnod {
91 my ($id) = @_;
92
6b64503e 93 return syscall(&__NR_fairsched_rmnod, int($id));
1e3baf05
DM
94}
95
96sub fairsched_mvpr {
97 my ($pid, $newid) = @_;
98
6b64503e 99 return syscall(&__NR_fairsched_mvpr, int($pid), int($newid));
1e3baf05
DM
100}
101
102sub fairsched_vcpus {
103 my ($id, $vcpus) = @_;
104
6b64503e 105 return syscall(&__NR_fairsched_vcpus, int($id), int($vcpus));
1e3baf05
DM
106}
107
108sub fairsched_rate {
109 my ($id, $op, $rate) = @_;
110
6b64503e 111 return syscall(&__NR_fairsched_rate, int($id), int($op), int($rate));
1e3baf05
DM
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
6b64503e 121 my $cpulim1024 = int($limit * 1024 / 100);
1e3baf05
DM
122 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE : FAIRSCHED_DROP_RATE;
123
6b64503e 124 return fairsched_rate($id, $op, $cpulim1024);
1e3baf05
DM
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
1e3baf05
DM
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 },
2ff09f52
DA
154 hotplug => {
155 optional => 1,
e8b9c17c 156 type => 'boolean',
2ff09f52
DA
157 description => "Activate hotplug for disk and network device",
158 default => 0,
159 },
1e3baf05
DM
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',
7878afeb 190 description => "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
1e3baf05
DM
191 minimum => 16,
192 default => 512,
193 },
13a48620
DA
194 balloon => {
195 optional => 1,
196 type => 'integer',
197 description => "Amount of target RAM for the VM in MB.",
7878afeb 198 minimum => 16,
13a48620 199 },
1e3baf05
DM
200 keyboard => {
201 optional => 1,
202 type => 'string',
203 description => "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
e95fe75f 204 enum => PVE::Tools::kvmkeymaplist(),
1e3baf05
DM
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}',
32baffb4 244 default => 'cdn',
1e3baf05
DM
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 },
19672434 291 localtime => {
1e3baf05
DM
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 },
0ea9541d
DM
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 },
1e3baf05
DM
313 startdate => {
314 optional => 1,
19672434 315 type => 'string',
1e3baf05
DM
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;
f62db2a4
DA
387my $MAX_SCSI_DISKS = 14;
388my $MAX_VIRTIO_DISKS = 6;
1e3baf05 389my $MAX_USB_DEVICES = 5;
f62db2a4 390my $MAX_NETS = 6;
1e3baf05 391my $MAX_UNUSED_DISKS = 8;
040b06b7 392my $MAX_HOSTPCI_DEVICES = 2;
bae179aa 393my $MAX_SERIAL_PORTS = 4;
1989a89c 394my $MAX_PARALLEL_PORTS = 3;
1e3baf05
DM
395
396my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
397 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
6b64503e 398my $nic_model_list_txt = join(' ', sort @$nic_model_list);
1e3baf05
DM
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,
19672434 406Specify network devices.
1e3baf05
DM
407
408MODEL is one of: $nic_model_list_txt
409
19672434 410XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
1e3baf05
DM
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;
19672434 434
1e3baf05
DM
435my $idedesc = {
436 optional => 1,
437 type => 'string', format => 'pve-qm-drive',
5534dd1a 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]',
1e3baf05
DM
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',
231f2e13 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]',
2fe1a152 447 description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13).",
1e3baf05
DM
448};
449PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
450
451my $virtiodesc = {
452 optional => 1,
453 type => 'string', format => 'pve-qm-drive',
5534dd1a 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]',
2fe1a152 455 description => "Use volume as VIRTIO hard disk (n is 0 to 5).",
1e3baf05
DM
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,
2fe1a152 464Configure an USB device (n is 0 to 4). This can be used to
1e3baf05
DM
465pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
466
19672434 467'bus-port(.port)*' (decimal numbers) or
1e3baf05
DM
468'vendor_id:product_id' (hexadeciaml numbers)
469
19672434 470You can use the 'lsusb -t' command to list existing usb devices.
1e3baf05
DM
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
040b06b7
DA
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
bae179aa
DA
496my $serialdesc = {
497 optional => 1,
ca0cef26 498 type => 'string',
2fe1a152 499 pattern => '/dev/ttyS\d+',
bae179aa 500 description => <<EODESCR,
19672434 501Map host serial devices (n is 0 to 3).
bae179aa
DA
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};
bae179aa 508
1989a89c
DA
509my $paralleldesc= {
510 optional => 1,
ca0cef26 511 type => 'string',
2fe1a152 512 pattern => '/dev/parport\d+',
1989a89c 513 description => <<EODESCR,
19672434 514Map host parallel devices (n is 0 to 2).
1989a89c
DA
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};
1989a89c
DA
521
522for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
523 $confdesc->{"parallel$i"} = $paralleldesc;
524}
525
bae179aa
DA
526for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
527 $confdesc->{"serial$i"} = $serialdesc;
528}
529
040b06b7
DA
530for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
531 $confdesc->{"hostpci$i"} = $hostpcidesc;
532}
1e3baf05
DM
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
6b64503e 569 my $fh = IO::File->new("</dev/kvm") ||
1e3baf05
DM
570 return 0;
571
6b64503e 572 if (my $v = $fh->ioctl(KVM_GET_API_VERSION(), 0)) {
1e3baf05
DM
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`;
19672434 590
a3c52213 591 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?) /) {
1e3baf05
DM
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
19672434 603 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1e3baf05
DM
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
6b64503e 611 return defined($drivename_hash->{$dev});
1e3baf05
DM
612}
613
614sub option_exists {
615 my $key = shift;
616 return defined($confdesc->{$key});
19672434 617}
1e3baf05
DM
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',
19672434 635 };
1e3baf05
DM
636}
637
1e3baf05
DM
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') {
f62db2a4 650 $maxdev = 7;
1e3baf05
DM
651 }
652
6b64503e 653 my $controller = int($index / $maxdev);
1e3baf05
DM
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 {
19672434 663 my ($dev, $media) = @_;
1e3baf05 664
6b64503e 665 my $info = disk_devive_info($dev);
1e3baf05
DM
666 my $mediastr = '';
667
668 if (($info->{bus} eq 'ide') || ($info->{bus} eq 'scsi')) {
669 $mediastr = ($media eq 'cdrom') ? "-cd" : "-hd";
19672434 670 return sprintf("%s%i%s%i", $info->{bus}, $info->{controller},
1e3baf05
DM
671 $mediastr, $info->{unit});
672 } else {
19672434 673 return sprintf("%s%i", $info->{bus}, $info->{index});
1e3baf05
DM
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 {
6b64503e 698 return PVE::Storage::path($storecfg, $cdrom);
1e3baf05
DM
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/^([^:]+):(.+)$/)) {
19672434 708
1e3baf05 709 return undef if $file =~ m|/|;
19672434 710
1e3baf05
DM
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);
19672434 736
1e3baf05
DM
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/^([^:]+):(.+)$/) &&
19672434 748 ($drive->{file} !~ m/^\d+$/)) {
1e3baf05
DM
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
6b64503e 762 my $filename = config_file($vmid);
1e3baf05
DM
763
764 die "configuration file '$filename' already exists\n" if -f $filename;
19672434 765
1e3baf05
DM
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 = {};
19672434 792
1e3baf05
DM
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};
19672434 813
1e3baf05
DM
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
19672434 826 return undef if $res->{cache} &&
5534dd1a 827 $res->{cache} !~ m/^(off|none|writethrough|writeback|unsafe)$/;
1e3baf05
DM
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};
19672434 842 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
1e3baf05
DM
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
ca916ecc
DA
867sub print_drivedevice_full {
868 my ($storecfg, $vmid, $drive) = @_;
869
870 my $device = '';
871 my $maxdev = 0;
19672434 872
ca916ecc 873 if ($drive->{interface} eq 'virtio') {
2ed36a41
DM
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';
231f2e13
DA
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 }
ca916ecc 894
7ebe888a 895 $device = "scsi-$devicetype,bus=lsi$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
2ed36a41
DM
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
7ebe888a 902 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
2ed36a41
DM
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";
ca916ecc
DA
908 }
909
3b408e82
DM
910 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
911
ca916ecc
DA
912 return $device;
913}
914
1e3baf05
DM
915sub print_drive_full {
916 my ($storecfg, $vmid, $drive) = @_;
917
918 my $opts = '';
919 foreach my $o (@qemu_drive_options) {
3b408e82 920 next if $o eq 'bootindex';
1e3baf05 921 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
19672434 922 }
1e3baf05
DM
923
924 # use linux-aio by default (qemu default is threads)
19672434 925 $opts .= ",aio=native" if !$drive->{aio};
1e3baf05
DM
926
927 my $path;
928 my $volid = $drive->{file};
6b64503e
DM
929 if (drive_is_cdrom($drive)) {
930 $path = get_iso_path($storecfg, $vmid, $volid);
1e3baf05
DM
931 } else {
932 if ($volid =~ m|^/|) {
933 $path = $volid;
934 } else {
6b64503e 935 $path = PVE::Storage::path($storecfg, $volid);
1e3baf05 936 }
2b556977
DM
937 if (!$drive->{cache} && ($path =~ m|^/dev/| || $path =~ m|\.raw$|)) {
938 $opts .= ",cache=none";
939 }
1e3baf05
DM
940 }
941
942 my $pathinfo = $path ? "file=$path," : '';
943
3ebfcc86 944 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1e3baf05
DM
945}
946
cc4d6182
DA
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}
1e3baf05
DM
993
994sub drive_is_cdrom {
995 my ($drive) = @_;
996
997 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
998
999}
1000
040b06b7
DA
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
1e3baf05
DM
1017# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1018sub parse_net {
1019 my ($data) = @_;
1020
1021 my $res = {};
1022
6b64503e 1023 foreach my $kvp (split(/,/, $data)) {
1e3baf05
DM
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) {
6b64503e 1026 my $model = lc($1);
9f91ff02 1027 my $mac = uc($3) || PVE::Tools::random_ether_addr();
1e3baf05
DM
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 }
19672434 1037
1e3baf05
DM
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 {
c2a64aa7 1068 my ($config, $volid, $vmid) = @_;
1e3baf05
DM
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;
19672434 1077 }
1e3baf05
DM
1078 }
1079
1080 die "To many unused volume - please delete them first.\n" if !$key;
1081
c2a64aa7
DA
1082 PVE::QemuServer::change_config_nolock($vmid, { $key => $volid }, {}, 1);
1083 $config->{$key} = $volid;
1e3baf05
DM
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
19672434 1092 return $value if valid_drivename($value);
1e3baf05
DM
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;
19672434 1106
1e3baf05
DM
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
6b64503e 1114 return $value if parse_drive(undef, $value);
1e3baf05
DM
1115
1116 return undef if $noerr;
19672434 1117
1e3baf05
DM
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
040b06b7
DA
1125 return $value if parse_hostpci($value);
1126
1127 return undef if $noerr;
1128
1129 die "unable to parse pci id\n";
1e3baf05
DM
1130}
1131
0ea9541d
DM
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;
19672434 1139
0ea9541d
DM
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
6b64503e 1150 foreach my $p (split(/,/, $value)) {
0ea9541d
DM
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
1e3baf05
DM
1165sub parse_usb_device {
1166 my ($value) = @_;
1167
1168 return undef if !$value;
1169
6b64503e 1170 my @dl = split(/,/, $value);
1e3baf05
DM
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}
19672434 1191
1e3baf05
DM
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;
19672434 1199
1e3baf05
DM
1200 die "unable to parse usb device\n";
1201}
1202
1e3baf05
DM
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
6b64503e 1221 if (!defined($value)) {
1e3baf05
DM
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') {
19672434
DM
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";
1e3baf05
DM
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()
6b64503e 1240 my $drive = parse_drive($key, $value);
1e3baf05
DM
1241 return $value if $drive;
1242 die "unable to parse drive options\n";
1243 }
1244 PVE::JSONSchema::check_format($fmt, $value);
19672434
DM
1245 return $value;
1246 }
1e3baf05 1247 $value =~ s/^\"(.*)\"$/$1/;
19672434 1248 return $value;
1e3baf05
DM
1249 } else {
1250 die "internal error"
1251 }
1252}
1253
1254sub lock_config {
1255 my ($vmid, $code, @param) = @_;
1256
6b64503e 1257 my $filename = config_file_lock($vmid);
1e3baf05 1258
5fdbe4f0 1259 my $res = lock_file($filename, 10, $code, @param);
1e3baf05
DM
1260
1261 die $@ if $@;
5fdbe4f0
DM
1262
1263 return $res;
1e3baf05
DM
1264}
1265
1266sub cfs_config_path {
a78ccf26 1267 my ($vmid, $node) = @_;
1e3baf05 1268
a78ccf26
DM
1269 $node = $nodename if !$node;
1270 return "nodes/$node/qemu-server/$vmid.conf";
1e3baf05
DM
1271}
1272
040b06b7
DA
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
1e3baf05 1282sub config_file {
a78ccf26 1283 my ($vmid, $node) = @_;
1e3baf05 1284
a78ccf26 1285 my $cfspath = cfs_config_path($vmid, $node);
1e3baf05
DM
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
6b64503e 1298 my $conf = config_file($vmid);
1e3baf05
DM
1299 utime undef, undef, $conf;
1300}
1301
1302sub create_disks {
3e16d5fc 1303 my ($storecfg, $vmid, $settings, $conf, $default_storage) = @_;
1e3baf05
DM
1304
1305 my $vollist = [];
1306
1307 eval {
1308 foreach_drive($settings, sub {
1309 my ($ds, $disk) = @_;
1310
6b64503e 1311 return if drive_is_cdrom($disk);
1e3baf05
DM
1312
1313 my $file = $disk->{file};
1314
1315 if ($file =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
3e16d5fc 1316 my $storeid = $2 || $default_storage;
1e3baf05 1317 my $size = $3;
6b64503e 1318 my $defformat = PVE::Storage::storage_default_format($storecfg, $storeid);
1e3baf05 1319 my $fmt = $disk->{format} || $defformat;
6b64503e 1320 syslog('info', "VM $vmid creating new disk - size is $size GB");
1e3baf05 1321
6b64503e 1322 my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid,
1e3baf05
DM
1323 $fmt, undef, $size*1024*1024);
1324
1325 $disk->{file} = $volid;
6b64503e 1326 delete $disk->{format}; # no longer needed
1e3baf05 1327 push @$vollist, $volid;
6b64503e 1328 $settings->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
1e3baf05
DM
1329 } else {
1330 my $path;
1331 if ($disk->{file} =~ m|^/dev/.+|) {
1332 $path = $disk->{file};
1333 } else {
6b64503e 1334 $path = PVE::Storage::path($storecfg, $disk->{file});
1e3baf05
DM
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) {
6b64503e 1346 syslog('err', "VM $vmid creating disks failed");
1e3baf05 1347 foreach my $volid (@$vollist) {
6b64503e 1348 eval { PVE::Storage::vdisk_free($storecfg, $volid); };
1e3baf05
DM
1349 warn $@ if $@;
1350 }
1351 die $err;
1352 }
1353
1354 return $vollist;
1355}
1356
1e3baf05 1357sub destroy_vm {
a6af7b3e 1358 my ($storecfg, $vmid, $keep_empty_config) = @_;
1e3baf05 1359
6b64503e 1360 my $conffile = config_file($vmid);
1e3baf05 1361
6b64503e 1362 my $conf = load_config($vmid);
1e3baf05 1363
6b64503e 1364 check_lock($conf);
1e3baf05 1365
19672434 1366 # only remove disks owned by this VM
1e3baf05
DM
1367 foreach_drive($conf, sub {
1368 my ($ds, $drive) = @_;
1369
6b64503e 1370 return if drive_is_cdrom($drive);
1e3baf05
DM
1371
1372 my $volid = $drive->{file};
ff1a2432 1373 return if !$volid || $volid =~ m|^/|;
1e3baf05 1374
6b64503e 1375 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
ff1a2432 1376 return if !$path || !$owner || ($owner != $vmid);
1e3baf05 1377
6b64503e 1378 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05 1379 });
19672434 1380
a6af7b3e 1381 if ($keep_empty_config) {
9c502e26 1382 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
a6af7b3e
DM
1383 } else {
1384 unlink $conffile;
1385 }
1e3baf05
DM
1386
1387 # also remove unused disk
1388 eval {
6b64503e 1389 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1e3baf05
DM
1390
1391 eval {
6b64503e 1392 PVE::Storage::foreach_volid($dl, sub {
1e3baf05 1393 my ($volid, $sid, $volname, $d) = @_;
6b64503e 1394 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05
DM
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
6b64503e 1416 return if drive_is_cdrom($di);
1e3baf05
DM
1417
1418 if ($di->{file} =~ m|^/dev/.+|) {
6b64503e 1419 $info->{$di->{file}}->{size} = PVE::Storage::file_size_info($di->{file});
1e3baf05
DM
1420 } else {
1421 push @$vollist, $di->{file};
1422 }
1423 });
1424
1425 eval {
6b64503e 1426 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid, $vollist);
1e3baf05 1427
6b64503e 1428 PVE::Storage::foreach_volid($dl, sub {
1e3baf05
DM
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
19672434 1438 $res->{$ds}->{disksize} = $info->{$di->{file}} ?
1e3baf05
DM
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;
19672434 1455}
1e3baf05
DM
1456
1457sub parse_vm_config {
1458 my ($filename, $raw) = @_;
1459
1460 return undef if !defined($raw);
1461
554ac7e7
DM
1462 my $res = {
1463 digest => Digest::SHA1::sha1_hex($raw),
1464 };
1e3baf05 1465
19672434 1466 $filename =~ m|/qemu-server/(\d+)\.conf$|
1e3baf05
DM
1467 || die "got strange filename '$filename'";
1468
1469 my $vmid = $1;
1470
1471 while ($raw && $raw =~ s/^(.*?)(\n|$)//) {
1472 my $line = $1;
19672434 1473
1e3baf05
DM
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;
6b64503e 1498 $value = print_drive($vmid, $v);
1e3baf05
DM
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};
19672434 1517 }
1e3baf05
DM
1518 delete $res->{smp};
1519
1520 return $res;
1521}
1522
1523sub change_config {
1524 my ($vmid, $settings, $unset, $skiplock) = @_;
1525
6b64503e 1526 lock_config($vmid, &change_config_nolock, $settings, $unset, $skiplock);
1e3baf05
DM
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}) {
19672434 1540 $unset->{smp} = 1;
1e3baf05
DM
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) {
554ac7e7 1549 next if $key eq 'digest';
1e3baf05
DM
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
6b64503e 1570 my $fh = new IO::File($filename, "r") ||
1e3baf05
DM
1571 die "unable to read config for VM $vmid\n";
1572
1573 my $werror = "unable to write config for VM $vmid\n";
1574
6b64503e 1575 my $out = new IO::File($tmpfn, "w") || die $werror;
1e3baf05
DM
1576
1577 eval {
1578
1579 my $done;
1580
1581 while (my $line = <$fh>) {
19672434 1582
1e3baf05
DM
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
6b64503e 1601 if (defined($res->{$key})) {
1e3baf05
DM
1602 $value = $res->{$key};
1603 delete $res->{$key};
1604 }
6b64503e 1605 if (!defined($unset->{$key})) {
1e3baf05 1606 die $werror unless print $out "$key: $value\n";
19672434 1607 }
1e3baf05
DM
1608
1609 next;
1610 }
1611
1612 die "unable to parse config file: $line\n";
1613 }
1614
1615 foreach my $key (keys %$res) {
1616
6b64503e 1617 if (!defined($unset->{$key})) {
1e3baf05
DM
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;
19672434 1636 die $err;
1e3baf05
DM
1637 }
1638
1639 if (!rename($tmpfn, $filename)) {
1640 $err = "rename failed - $!\n";
1641 unlink $tmpfn;
1642 die $err;
1643 }
1644}
1645
19672434 1646sub load_defaults {
1e3baf05
DM
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 }
19672434 1656
1e3baf05
DM
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
1e3baf05
DM
1669 foreach my $vmid (keys %$ids) {
1670 my $d = $ids->{$vmid};
1671 next if !$d->{node} || $d->{node} ne $nodename;
5ee957cc 1672 next if !$d->{type} || $d->{type} ne 'qemu';
1e3baf05
DM
1673 $res->{$vmid}->{exists} = 1;
1674 }
1675 return $res;
1676}
1677
64e13401
DM
1678# test if VM uses local resources (to prevent migration)
1679sub check_local_resources {
1680 my ($conf, $noerr) = @_;
1681
1682 my $loc_res = 0;
19672434 1683
e0ab7331
DM
1684 $loc_res = 1 if $conf->{hostusb}; # old syntax
1685 $loc_res = 1 if $conf->{hostpci}; # old syntax
64e13401 1686
0d29ab3b 1687 foreach my $k (keys %$conf) {
2fe1a152 1688 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
64e13401
DM
1689 }
1690
1691 die "VM uses local resources\n" if $loc_res && !$noerr;
1692
1693 return $loc_res;
1694}
1695
1e3baf05
DM
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
6b64503e
DM
1705 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
1706 if (defined($fh)) {
1e3baf05
DM
1707 my $line = <$fh>;
1708 $fh->close;
1709 return undef if !$line;
6b64503e 1710 my @param = split(/\0/, $line);
1e3baf05
DM
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 {
e6c3b671 1729 my ($vmid, $nocheck) = @_;
1e3baf05 1730
e6c3b671 1731 my $filename = config_file($vmid);
1e3baf05
DM
1732
1733 die "unable to find configuration file for VM $vmid - no such machine\n"
e6c3b671 1734 if !$nocheck && ! -f $filename;
1e3baf05 1735
e6c3b671 1736 my $pidfile = pidfile_name($vmid);
1e3baf05 1737
e6c3b671
DM
1738 if (my $fd = IO::File->new("<$pidfile")) {
1739 my $st = stat($fd);
1e3baf05 1740 my $line = <$fd>;
6b64503e 1741 close($fd);
1e3baf05
DM
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;
e6c3b671
DM
1750 if (check_cmdline($pidfile, $pid)) {
1751 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
1752 return $pid;
1753 }
1754 }
1e3baf05
DM
1755 }
1756 }
1757
1758 return undef;
1759}
1760
1761sub vzlist {
19672434 1762
1e3baf05
DM
1763 my $vzlist = config_list();
1764
6b64503e 1765 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1e3baf05 1766
19672434 1767 while (defined(my $de = $fd->read)) {
1e3baf05
DM
1768 next if $de !~ m/^(\d+)\.pid$/;
1769 my $vmid = $1;
6b64503e
DM
1770 next if !defined($vzlist->{$vmid});
1771 if (my $pid = check_running($vmid)) {
1e3baf05
DM
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 {
f0cab979
DM
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 }
1e3baf05
DM
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
19672434 1844 my $storecfg = PVE::Storage::config();
1e3baf05
DM
1845
1846 my $list = vzlist();
694fcad4 1847 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1e3baf05 1848
ae4915a2
DM
1849 my $cpucount = $cpuinfo->{cpus} || 1;
1850
1e3baf05
DM
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);
ae4915a2
DM
1873 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
1874
1e3baf05 1875 $d->{name} = $conf->{name} || "VM $vmid";
19672434 1876 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
1e3baf05 1877
1e3baf05
DM
1878 $d->{uptime} = 0;
1879 $d->{cpu} = 0;
1e3baf05
DM
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;
19672434 1897
1e3baf05
DM
1898 $d->{netout} += $netdev->{$dev}->{receive};
1899 $d->{netin} += $netdev->{$dev}->{transmit};
1900 }
1901
1e3baf05
DM
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 = {};
6b64503e 1912 while (defined(my $line = <$fh>)) {
1e3baf05
DM
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
694fcad4
DM
1922 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
1923 next if !$pstat; # not running
19672434 1924
694fcad4 1925 my $used = $pstat->{utime} + $pstat->{stime};
1e3baf05 1926
694fcad4 1927 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1e3baf05 1928
694fcad4 1929 if ($pstat->{vsize}) {
6b64503e 1930 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1e3baf05
DM
1931 }
1932
1933 my $old = $last_proc_pid_stat->{$pid};
1934 if (!$old) {
19672434
DM
1935 $last_proc_pid_stat->{$pid} = {
1936 time => $ctime,
1e3baf05
DM
1937 used => $used,
1938 cpu => 0,
1e3baf05
DM
1939 };
1940 next;
1941 }
1942
7f0b5beb 1943 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1e3baf05
DM
1944
1945 if ($dtime > 1000) {
1946 my $dutime = $used - $old->{used};
1947
ae4915a2 1948 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1e3baf05 1949 $last_proc_pid_stat->{$pid} = {
19672434 1950 time => $ctime,
1e3baf05
DM
1951 used => $used,
1952 cpu => $d->{cpu},
1e3baf05
DM
1953 };
1954 } else {
1955 $d->{cpu} = $old->{cpu};
1e3baf05
DM
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
6b64503e 1968 my $drive = parse_drive($ds, $conf->{$ds});
1e3baf05
DM
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 = [];
b78ebef7 1979 my $pciaddr = '';
1e3baf05
DM
1980 my $kvmver = kvm_user_version();
1981 my $vernum = 0; # unknown
a3c52213
DM
1982 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
1983 $vernum = $1*1000000+$2*1000;
1984 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1e3baf05
DM
1985 $vernum = $1*1000000+$2*1000+$3;
1986 }
1987
a3c52213 1988 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1e3baf05
DM
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
6b64503e 1998 my $socket = monitor_socket($vmid);
abb39b66
DA
1999 push @$cmd, '-chardev', "socket,id=monitor,path=$socket,server,nowait";
2000 push @$cmd, '-mon', "chardev=monitor,mode=readline";
1e3baf05 2001
6b64503e 2002 $socket = vnc_socket($vmid);
1e3baf05
DM
2003 push @$cmd, '-vnc', "unix:$socket,x509,password";
2004
6b64503e 2005 push @$cmd, '-pidfile' , pidfile_name($vmid);
19672434 2006
1e3baf05
DM
2007 push @$cmd, '-daemonize';
2008
2009 push @$cmd, '-incoming', $migrate_uri if $migrate_uri;
2010
1c060867
DM
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 }
1e3baf05 2016 # include usb device config
1c060867 2017 push @$cmd, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
19672434 2018
1e3baf05 2019 # enable absolute mouse coordinates (needed by vnc)
6b64503e 2020 my $tablet = defined($conf->{tablet}) ? $conf->{tablet} : $defaults->{tablet};
1c060867
DM
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 }
1e3baf05
DM
2028
2029 # host pci devices
040b06b7
DA
2030 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2031 my $d = parse_hostpci($conf->{"hostpci$i"});
2032 next if !$d;
b78ebef7
DA
2033 $pciaddr = print_pci_addr("hostpci$i");
2034 push @$cmd, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
1e3baf05
DM
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
1e3baf05 2048 # serial devices
bae179aa 2049 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
34978be3 2050 if (my $path = $conf->{"serial$i"}) {
19672434 2051 die "no such serial device\n" if ! -c $path;
34978be3
DM
2052 push @$cmd, '-chardev', "tty,id=serial$i,path=$path";
2053 push @$cmd, '-device', "isa-serial,chardev=serial$i";
2054 }
1e3baf05
DM
2055 }
2056
2057 # parallel devices
1989a89c 2058 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
34978be3 2059 if (my $path = $conf->{"parallel$i"}) {
19672434 2060 die "no such parallel device\n" if ! -c $path;
34978be3
DM
2061 push @$cmd, '-chardev', "parport,id=parallel$i,path=$path";
2062 push @$cmd, '-device', "isa-parallel,chardev=parallel$i";
2063 }
1e3baf05
DM
2064 }
2065
2066 my $vmname = $conf->{name} || "vm$vmid";
2067
2068 push @$cmd, '-name', $vmname;
19672434 2069
1e3baf05
DM
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
1e3baf05
DM
2076 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2077
2078 push @$cmd, '-cpu', $conf->{cpu} if $conf->{cpu};
2079
1e3baf05
DM
2080 push @$cmd, '-nodefaults';
2081
32baffb4 2082 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
3b408e82 2083
0888fdce
DM
2084 my $bootindex_hash = {};
2085 my $i = 1;
2086 foreach my $o (split(//, $bootorder)) {
2087 $bootindex_hash->{$o} = $i*100;
2088 $i++;
afdb31d5 2089 }
3b408e82
DM
2090
2091 push @$cmd, '-boot', "menu=on";
1e3baf05 2092
6b64503e 2093 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
1e3baf05 2094
6b64503e 2095 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
1e3baf05
DM
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 }
19672434 2105
1e3baf05
DM
2106 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2107
2108 # time drift fix
6b64503e 2109 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
1e3baf05
DM
2110 push @$cmd, '-tdf' if $tdf;
2111
6b64503e 2112 my $nokvm = defined($conf->{kvm}) && $conf->{kvm} == 0 ? 1 : 0;
1e3baf05
DM
2113
2114 if (my $ost = $conf->{ostype}) {
2115 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2116
2117 if ($ost =~ m/^w/) { # windows
6b64503e 2118 push @$cmd, '-localtime' if !defined($conf->{localtime});
1e3baf05
DM
2119
2120 # use rtc-td-hack when acpi is enabled
6b64503e 2121 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
1e3baf05
DM
2122 push @$cmd, '-rtc-td-hack';
2123 }
2124 }
2125
2126 # -tdf ?
19672434
DM
2127 # -no-acpi
2128 # -no-kvm
1e3baf05
DM
2129 # -win2k-hack ?
2130 }
2131
7f0b5beb
DM
2132 if ($nokvm) {
2133 push @$cmd, '-no-kvm';
2134 } else {
2135 die "No accelerator found!\n" if !$cpuinfo->{hvm};
2136 }
1e3baf05
DM
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;
b78ebef7 2152 $pciaddr = print_pci_addr("balloon0");
13b5a753 2153 push @$cmd, '-device', "virtio-balloon-pci,id=balloon0$pciaddr" if $conf->{balloon};
1e3baf05 2154
0ea9541d
DM
2155 if ($conf->{watchdog}) {
2156 my $wdopts = parse_watchdog($conf->{watchdog});
0a40e8ea
DA
2157 $pciaddr = print_pci_addr("watchdog");
2158 my $watchdog = $wdopts->{model} || 'i6300esb';
2159 push @$cmd, '-device', "$watchdog$pciaddr";
0ea9541d
DM
2160 push @$cmd, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
2161 }
2162
1e3baf05 2163 my $vollist = [];
941e0c42 2164 my $scsicontroller = {};
1e3baf05
DM
2165
2166 foreach_drive($conf, sub {
2167 my ($ds, $drive) = @_;
2168
ff1a2432 2169 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
1e3baf05 2170 push @$vollist, $drive->{file};
ff1a2432 2171 }
afdb31d5 2172
1e3baf05 2173 $use_virtio = 1 if $ds =~ m/^virtio/;
3b408e82
DM
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
941e0c42
DA
2187 if ($drive->{interface} eq 'scsi') {
2188 my $maxdev = 7;
6b64503e 2189 my $controller = int($drive->{index} / $maxdev);
69b6ae0c
DA
2190 $pciaddr = print_pci_addr("lsi$controller");
2191 push @$cmd, '-device', "lsi,id=lsi$controller$pciaddr" if !$scsicontroller->{$controller};
58dc808d 2192 $scsicontroller->{$controller}=1;
941e0c42 2193 }
3b408e82
DM
2194
2195 push @$cmd, '-drive', print_drive_full($storecfg, $vmid, $drive);
6b64503e 2196 push @$cmd, '-device',print_drivedevice_full($storecfg,$vmid, $drive);
1e3baf05
DM
2197 });
2198
2199 push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
19672434 2200
cc4d6182
DA
2201 for (my $i = 0; $i < $MAX_NETS; $i++) {
2202 my $d = parse_net($conf->{"net$i"});
2203 next if !$d;
1e3baf05 2204
cc4d6182 2205 $use_virtio = 1 if $d->{model} eq 'virtio';
1e3baf05 2206
cc4d6182
DA
2207 if ($bootindex_hash->{n}) {
2208 $d->{bootindex} = $bootindex_hash->{n};
2209 $bootindex_hash->{n} += 1;
2210 }
1e3baf05 2211
cc4d6182
DA
2212 my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i");
2213 push @$cmd, '-netdev', $netdevfull;
1e3baf05 2214
cc4d6182
DA
2215 my $netdevicefull = print_netdevice_full($vmid,$conf,$d,"net$i");
2216 push @$cmd, '-device', $netdevicefull;
19672434
DM
2217 }
2218
1e3baf05
DM
2219
2220 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2221 # when the VM uses virtio devices.
19672434
DM
2222 if (!$use_virtio && $have_ovz) {
2223
6b64503e 2224 my $cpuunits = defined($conf->{cpuunits}) ?
1e3baf05
DM
2225 $conf->{cpuunits} : $defaults->{cpuunits};
2226
2227 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2228
2229 # fixme: cpulimit is currently ignored
2230 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2231 }
2232
2233 # add custom args
2234 if ($conf->{args}) {
3ada46c9 2235 my $aa = PVE::Tools::split_args($conf->{args});
1e3baf05
DM
2236 push @$cmd, @$aa;
2237 }
2238
2239 return wantarray ? ($cmd, $vollist) : $cmd;
2240}
19672434 2241
1e3baf05
DM
2242sub vnc_socket {
2243 my ($vmid) = @_;
2244 return "${var_run_tmpdir}/$vmid.vnc";
2245}
2246
2247sub monitor_socket {
2248 my ($vmid) = @_;
2249 return "${var_run_tmpdir}/$vmid.mon";
2250}
2251
2252sub pidfile_name {
2253 my ($vmid) = @_;
2254 return "${var_run_tmpdir}/$vmid.pid";
2255}
2256
1e3baf05
DM
2257sub next_migrate_port {
2258
2259 for (my $p = 60000; $p < 60010; $p++) {
2260
6b64503e
DM
2261 my $sock = IO::Socket::INET->new(Listen => 5,
2262 LocalAddr => 'localhost',
2263 LocalPort => $p,
2264 ReuseAddr => 1,
2265 Proto => 0);
1e3baf05
DM
2266
2267 if ($sock) {
6b64503e 2268 close($sock);
1e3baf05
DM
2269 return $p;
2270 }
2271 }
2272
2273 die "unable to find free migration port";
2274}
2275
86fdcfb2
DA
2276sub vm_devices_list {
2277 my ($vmid) = @_;
2278
ff1a2432 2279 my $res = vm_monitor_command ($vmid, "info pci");
1dc4f496
DM
2280
2281 my @lines = split ("\n", $res);
2282 my $devices;
2283 my $bus;
2284 my $addr;
2285 my $id;
afdb31d5 2286
1dc4f496
DM
2287 foreach my $line (@lines) {
2288 $line =~ s/^\s+//;
2289 if ($line =~ m/^Bus (\d+), device (\d+), function (\d+):$/) {
2290 $bus=$1;
2291 $addr=$2;
2292 }
2293 if ($line =~ m/^id "([a-z][a-z_\-]*\d*)"$/) {
86fdcfb2
DA
2294 $id=$1;
2295 $devices->{$id}->{bus}=$bus;
2296 $devices->{$id}->{addr}=$addr;
1dc4f496
DM
2297 }
2298 }
86fdcfb2 2299
1dc4f496 2300 return $devices;
86fdcfb2
DA
2301}
2302
ec21aa11 2303sub vm_deviceplug {
f19d1c47 2304 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2630d2a9 2305 return 1 if !check_running($vmid) || !$conf->{hotplug};
afdb31d5 2306
5e5dcb73
DA
2307 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2308 return undef if !qemu_driveadd($storecfg, $vmid, $device);
1dc4f496 2309 my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
5e5dcb73
DA
2310 qemu_deviceadd($vmid, $devicefull);
2311 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2312 qemu_drivedel($vmid, $deviceid);
2313 return undef;
2314 }
f19d1c47 2315 }
cfc817c7
DA
2316
2317 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2318 my $pciaddr = print_pci_addr($deviceid);
2319 my $devicefull = "lsi,id=$deviceid$pciaddr";
2320 qemu_deviceadd($vmid, $devicefull);
2321 return undef if(!qemu_deviceaddverify($vmid, $deviceid));
2322 }
2323
a4f091a0
DA
2324 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2325 return undef if !qemu_findorcreatelsi($storecfg,$conf, $vmid, $device);
2326 return undef if !qemu_driveadd($storecfg, $vmid, $device);
2327 my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
2328 if(!qemu_deviceadd($vmid, $devicefull)) {
2329 qemu_drivedel($vmid, $deviceid);
2330 return undef;
2331 }
2332 }
2333
2630d2a9
DA
2334 if ($deviceid =~ m/^(net)(\d+)$/) {
2335 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
2336 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid);
2337 qemu_deviceadd($vmid, $netdevicefull);
2338 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2339 qemu_netdevdel($vmid, $deviceid);
2340 return undef;
2341 }
2342 }
2343
5e5dcb73 2344 return 1;
a4dea331
DA
2345}
2346
ec21aa11 2347sub vm_deviceunplug {
f19d1c47 2348 my ($vmid, $conf, $deviceid) = @_;
873c2d69 2349
5e5dcb73 2350 return 1 if !check_running ($vmid) || !$conf->{hotplug};
873c2d69 2351
f19d1c47
DA
2352 die "can't unplug bootdisk" if $conf->{bootdisk} eq $deviceid;
2353
5e5dcb73
DA
2354 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2355 return undef if !qemu_drivedel($vmid, $deviceid);
2356 qemu_devicedel($vmid, $deviceid);
2357 return undef if !qemu_devicedelverify($vmid, $deviceid);
2358 }
cfc817c7
DA
2359
2360 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2361 return undef if !qemu_devicedel($vmid, $deviceid);
2362 }
2363
a4f091a0
DA
2364 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2365 return undef if !qemu_devicedel($vmid, $deviceid);
2366 return undef if !qemu_drivedel($vmid, $deviceid);
2367 }
2368
2630d2a9
DA
2369 if ($deviceid =~ m/^(net)(\d+)$/) {
2370 return undef if !qemu_netdevdel($vmid, $deviceid);
2371 qemu_devicedel($vmid, $deviceid);
2372 return undef if !qemu_devicedelverify($vmid, $deviceid);
2373 }
2374
5e5dcb73
DA
2375 return 1;
2376}
2377
2378sub qemu_deviceadd {
2379 my ($vmid, $devicefull) = @_;
873c2d69 2380
5e5dcb73
DA
2381 my $ret = vm_monitor_command($vmid, "device_add $devicefull");
2382 $ret =~ s/^\s+//;
afdb31d5 2383 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
5e5dcb73
DA
2384 return 1 if $ret eq "";
2385 syslog("err", "error on hotplug device : $ret");
2386 return undef;
f19d1c47 2387
5e5dcb73 2388}
afdb31d5 2389
5e5dcb73
DA
2390sub qemu_devicedel {
2391 my($vmid, $deviceid) = @_;
f19d1c47 2392
5e5dcb73
DA
2393 my $ret = vm_monitor_command($vmid, "device_del $deviceid");
2394 $ret =~ s/^\s+//;
2395 return 1 if $ret eq "";
2396 syslog("err", "detaching device $deviceid failed : $ret");
2397 return undef;
2398}
2399
2400sub qemu_driveadd {
2401 my($storecfg, $vmid, $device) = @_;
2402
2403 my $drive = print_drive_full($storecfg, $vmid, $device);
2404 my $ret = vm_monitor_command($vmid, "drive_add auto $drive");
2405 # If the command succeeds qemu prints: "OK"
2406 if ($ret !~ m/OK/s) {
2407 syslog("err", "adding drive failed: $ret");
2408 return undef;
f19d1c47 2409 }
5e5dcb73
DA
2410 return 1;
2411}
afdb31d5 2412
5e5dcb73
DA
2413sub qemu_drivedel {
2414 my($vmid, $deviceid) = @_;
873c2d69 2415
5e5dcb73
DA
2416 my $ret = vm_monitor_command($vmid, "drive_del drive-$deviceid");
2417 $ret =~ s/^\s+//;
2418 if ($ret =~ m/Device \'.*?\' not found/s) {
afdb31d5 2419 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
5e5dcb73
DA
2420 }
2421 elsif ($ret ne "") {
2422 syslog("err", "deleting drive $deviceid failed : $ret");
2423 return undef;
873c2d69 2424 }
5e5dcb73
DA
2425 return 1;
2426}
f19d1c47 2427
5e5dcb73
DA
2428sub qemu_deviceaddverify {
2429 my ($vmid,$deviceid) = @_;
873c2d69 2430
5e5dcb73
DA
2431 for (my $i = 0; $i <= 5; $i++) {
2432 my $devices_list = vm_devices_list($vmid);
2433 return 1 if defined($devices_list->{$deviceid});
2434 sleep 1;
afdb31d5 2435 }
5e5dcb73
DA
2436 syslog("err", "error on hotplug device $deviceid");
2437 return undef;
2438}
afdb31d5 2439
5e5dcb73
DA
2440
2441sub qemu_devicedelverify {
2442 my ($vmid,$deviceid) = @_;
2443
2444 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2445 for (my $i = 0; $i <= 5; $i++) {
2446 my $devices_list = vm_devices_list($vmid);
2447 return 1 if !defined($devices_list->{$deviceid});
2448 sleep 1;
afdb31d5 2449 }
5e5dcb73
DA
2450 syslog("err", "error on hot-unplugging device $deviceid");
2451 return undef;
873c2d69
DA
2452}
2453
cfc817c7
DA
2454sub qemu_findorcreatelsi {
2455 my ($storecfg, $conf, $vmid, $device) = @_;
2456
2457 my $maxdev = 7;
2458 my $controller = int($device->{index} / $maxdev);
2459 my $lsiid="lsi$controller";
2460 my $devices_list = vm_devices_list($vmid);
2461
2462 if(!defined($devices_list->{$lsiid})) {
2463 return undef if !vm_deviceplug($storecfg, $conf, $vmid, $lsiid);
2464 }
2465 return 1;
2466}
2467
2630d2a9
DA
2468sub qemu_netdevadd {
2469 my ($vmid, $conf, $device, $deviceid) = @_;
2470
2471 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
2472 my $ret = vm_monitor_command($vmid, "netdev_add $netdev");
2473 $ret =~ s/^\s+//;
2474
2475 #if the command succeeds, no output is sent. So any non-empty string shows an error
2476 return 1 if $ret eq "";
2477 syslog("err", "adding netdev failed: $ret");
2478 return undef;
2479}
2480
2481sub qemu_netdevdel {
2482 my ($vmid, $deviceid) = @_;
2483
2484 my $ret = vm_monitor_command($vmid, "netdev_del $deviceid");
2485 $ret =~ s/^\s+//;
2486 #if the command succeeds, no output is sent. So any non-empty string shows an error
2487 return 1 if $ret eq "";
2488 syslog("err", "deleting netdev failed: $ret");
2489 return undef;
2490}
2491
1e3baf05
DM
2492sub vm_start {
2493 my ($storecfg, $vmid, $statefile, $skiplock) = @_;
2494
6b64503e
DM
2495 lock_config($vmid, sub {
2496 my $conf = load_config($vmid);
1e3baf05 2497
6b64503e 2498 check_lock($conf) if !$skiplock;
1e3baf05 2499
ff1a2432 2500 die "VM $vmid already running\n" if check_running($vmid);
1e3baf05
DM
2501
2502 my $migrate_uri;
2503 my $migrate_port = 0;
2504
2505 if ($statefile) {
2506 if ($statefile eq 'tcp') {
2507 $migrate_port = next_migrate_port();
2508 $migrate_uri = "tcp:localhost:${migrate_port}";
2509 } else {
2510 if (-f $statefile) {
2511 $migrate_uri = "exec:cat $statefile";
2512 } else {
2513 warn "state file '$statefile' does not exist - doing normal startup\n";
2514 }
2515 }
2516 }
2517
2518 my $defaults = load_defaults();
2519
e6c3b671 2520 my ($cmd, $vollist) = config_to_command($storecfg, $vmid, $conf, $defaults, $migrate_uri);
1e3baf05 2521 # host pci devices
040b06b7
DA
2522 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2523 my $d = parse_hostpci($conf->{"hostpci$i"});
2524 next if !$d;
2525 my $info = pci_device_info("0000:$d->{pciid}");
2526 die "IOMMU not present\n" if !check_iommu_support();
2527 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2528 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub($info);
2529 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset($info);
2530 }
1e3baf05
DM
2531
2532 PVE::Storage::activate_volumes($storecfg, $vollist);
2533
6b64503e 2534 eval { run_command($cmd, timeout => $migrate_uri ? undef : 30); };
1e3baf05 2535 my $err = $@;
ff1a2432 2536 die "start failed: $err" if $err;
1e3baf05
DM
2537
2538 if ($statefile) {
2539
2540 if ($statefile eq 'tcp') {
2541 print "migration listens on port $migrate_port\n";
2542 } else {
2543 unlink $statefile;
2544 # fixme: send resume - is that necessary ?
ff1a2432 2545 eval { vm_monitor_command($vmid, "cont"); };
1e3baf05
DM
2546 }
2547 }
afdb31d5 2548
48e1a963
DM
2549 # always set migrate speed (overwrite kvm default of 32m)
2550 # we set a very hight default of 8192m which is basically unlimited
2551 my $migrate_speed = $defaults->{migrate_speed} || 8192;
2552 $migrate_speed = $conf->{migrate_speed} || $migrate_speed;
afdb31d5 2553 eval {
1e3baf05 2554 my $cmd = "migrate_set_speed ${migrate_speed}m";
afdb31d5 2555 vm_monitor_command($vmid, $cmd);
48e1a963 2556 };
1e3baf05 2557
19672434 2558 if (my $migrate_downtime =
1e3baf05
DM
2559 $conf->{migrate_downtime} || $defaults->{migrate_downtime}) {
2560 my $cmd = "migrate_set_downtime ${migrate_downtime}";
ff1a2432 2561 eval { vm_monitor_command($vmid, $cmd); };
1e3baf05 2562 }
e6c3b671 2563
7878afeb 2564 vm_balloonset($vmid, $conf->{balloon}) if $conf->{balloon};
1e3baf05
DM
2565 });
2566}
2567
2568sub __read_avail {
2569 my ($fh, $timeout) = @_;
2570
2571 my $sel = new IO::Select;
6b64503e 2572 $sel->add($fh);
1e3baf05
DM
2573
2574 my $res = '';
2575 my $buf;
2576
2577 my @ready;
6b64503e 2578 while (scalar (@ready = $sel->can_read($timeout))) {
1e3baf05 2579 my $count;
6b64503e 2580 if ($count = $fh->sysread($buf, 8192)) {
1e3baf05
DM
2581 if ($buf =~ /^(.*)\(qemu\) $/s) {
2582 $res .= $1;
2583 last;
2584 } else {
2585 $res .= $buf;
2586 }
2587 } else {
6b64503e 2588 if (!defined($count)) {
1e3baf05
DM
2589 die "$!\n";
2590 }
2591 last;
2592 }
2593 }
2594
6b64503e 2595 die "monitor read timeout\n" if !scalar(@ready);
1e3baf05
DM
2596
2597 return $res;
2598}
2599
2600sub vm_monitor_command {
ff1a2432 2601 my ($vmid, $cmdstr, $nocheck) = @_;
1e3baf05
DM
2602
2603 my $res;
2604
1e3baf05 2605 eval {
ff1a2432 2606 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
1e3baf05 2607
e6c3b671 2608 my $sname = monitor_socket($vmid);
1e3baf05 2609
6b64503e 2610 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
1e3baf05
DM
2611 die "unable to connect to VM $vmid socket - $!\n";
2612
2613 my $timeout = 3;
2614
19672434 2615 # hack: migrate sometime blocks the monitor (when migrate_downtime
1e3baf05
DM
2616 # is set)
2617 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2618 $timeout = 60*60; # 1 hour
2619 }
2620
2621 # read banner;
6b64503e 2622 my $data = __read_avail($sock, $timeout);
19672434 2623
1e3baf05
DM
2624 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2625 die "got unexpected qemu monitor banner\n";
2626 }
2627
2628 my $sel = new IO::Select;
6b64503e 2629 $sel->add($sock);
1e3baf05 2630
6b64503e 2631 if (!scalar(my @ready = $sel->can_write($timeout))) {
1e3baf05
DM
2632 die "monitor write error - timeout";
2633 }
2634
2635 my $fullcmd = "$cmdstr\r";
2636
2637 my $b;
6b64503e 2638 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
1e3baf05
DM
2639 die "monitor write error - $!";
2640 }
2641
2642 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2643
19672434 2644 $timeout = 20;
1e3baf05
DM
2645
2646 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2647 $timeout = 60*60; # 1 hour
2648 } elsif ($cmdstr =~ m/^(eject|change)/) {
2649 $timeout = 60; # note: cdrom mount command is slow
2650 }
6b64503e 2651 if ($res = __read_avail($sock, $timeout)) {
19672434 2652
6b64503e 2653 my @lines = split("\r?\n", $res);
1e3baf05
DM
2654
2655 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
19672434 2656
6b64503e 2657 $res = join("\n", @lines);
1e3baf05
DM
2658 $res .= "\n";
2659 }
2660 };
2661
2662 my $err = $@;
2663
2664 if ($err) {
6b64503e 2665 syslog("err", "VM $vmid monitor command failed - $err");
1e3baf05
DM
2666 die $err;
2667 }
2668
2669 return $res;
2670}
2671
2672sub vm_commandline {
2673 my ($storecfg, $vmid) = @_;
2674
6b64503e 2675 my $conf = load_config($vmid);
1e3baf05
DM
2676
2677 my $defaults = load_defaults();
2678
6b64503e 2679 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 2680
6b64503e 2681 return join(' ', @$cmd);
1e3baf05
DM
2682}
2683
2684sub vm_reset {
2685 my ($vmid, $skiplock) = @_;
2686
6b64503e 2687 lock_config($vmid, sub {
1e3baf05 2688
6b64503e 2689 my $conf = load_config($vmid);
1e3baf05 2690
6b64503e 2691 check_lock($conf) if !$skiplock;
1e3baf05 2692
ff1a2432
DM
2693 vm_monitor_command($vmid, "system_reset");
2694 });
2695}
2696
2697sub get_vm_volumes {
2698 my ($conf) = @_;
1e3baf05 2699
ff1a2432
DM
2700 my $vollist = [];
2701 foreach_drive($conf, sub {
2702 my ($ds, $drive) = @_;
2703
2704 my ($sid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
2705 return if !$sid;
2706
2707 my $volid = $drive->{file};
2708 return if !$volid || $volid =~ m|^/|;
2709
2710 push @$vollist, $volid;
1e3baf05 2711 });
ff1a2432
DM
2712
2713 return $vollist;
2714}
2715
2716sub vm_stop_cleanup {
254575e9 2717 my ($storecfg, $vmid, $conf, $keepActive) = @_;
ff1a2432 2718
745fed70
DM
2719 eval {
2720 fairsched_rmnod($vmid); # try to destroy group
ff1a2432 2721
254575e9
DM
2722 if (!$keepActive) {
2723 my $vollist = get_vm_volumes($conf);
2724 PVE::Storage::deactivate_volumes($storecfg, $vollist);
2725 }
745fed70
DM
2726 };
2727 warn $@ if $@; # avoid errors - just warn
1e3baf05
DM
2728}
2729
e6c3b671 2730# Note: use $nockeck to skip tests if VM configuration file exists.
254575e9
DM
2731# We need that when migration VMs to other nodes (files already moved)
2732# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
1e3baf05 2733sub vm_stop {
254575e9 2734 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive) = @_;
9269013a
DM
2735
2736 $timeout = 60 if !defined($timeout);
ff1a2432 2737
9269013a 2738 $force = 1 if !defined($force) && !$shutdown;
1e3baf05 2739
e6c3b671 2740 lock_config($vmid, sub {
1e3baf05 2741
e6c3b671 2742 my $pid = check_running($vmid, $nocheck);
ff1a2432 2743 return if !$pid;
1e3baf05 2744
ff1a2432 2745 my $conf;
e6c3b671 2746 if (!$nocheck) {
ff1a2432 2747 $conf = load_config($vmid);
e6c3b671
DM
2748 check_lock($conf) if !$skiplock;
2749 }
19672434 2750
9269013a
DM
2751 eval {
2752 if ($shutdown) {
2753 vm_monitor_command($vmid, "system_powerdown", $nocheck);
2754 } else {
2755 vm_monitor_command($vmid, "quit", $nocheck);
afdb31d5 2756 }
9269013a 2757 };
1e3baf05
DM
2758 my $err = $@;
2759
2760 if (!$err) {
1e3baf05 2761 my $count = 0;
e6c3b671 2762 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
2763 $count++;
2764 sleep 1;
2765 }
2766
2767 if ($count >= $timeout) {
9269013a
DM
2768 if ($force) {
2769 warn "VM still running - terminating now with SIGTERM\n";
2770 kill 15, $pid;
2771 } else {
2772 die "VM quit/powerdown failed - got timeout\n";
2773 }
2774 } else {
254575e9 2775 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
9269013a 2776 return;
1e3baf05
DM
2777 }
2778 } else {
9269013a
DM
2779 if ($force) {
2780 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
2781 kill 15, $pid;
2782 } else {
afdb31d5 2783 die "VM quit/powerdown failed\n";
9269013a 2784 }
1e3baf05
DM
2785 }
2786
2787 # wait again
ff1a2432 2788 $timeout = 10;
1e3baf05
DM
2789
2790 my $count = 0;
e6c3b671 2791 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
2792 $count++;
2793 sleep 1;
2794 }
2795
2796 if ($count >= $timeout) {
ff1a2432 2797 warn "VM still running - terminating now with SIGKILL\n";
1e3baf05 2798 kill 9, $pid;
ff1a2432 2799 sleep 1;
1e3baf05
DM
2800 }
2801
254575e9 2802 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
ff1a2432 2803 });
1e3baf05
DM
2804}
2805
2806sub vm_suspend {
2807 my ($vmid, $skiplock) = @_;
2808
6b64503e 2809 lock_config($vmid, sub {
1e3baf05 2810
6b64503e 2811 my $conf = load_config($vmid);
1e3baf05 2812
6b64503e 2813 check_lock($conf) if !$skiplock;
1e3baf05 2814
ff1a2432 2815 vm_monitor_command($vmid, "stop");
1e3baf05
DM
2816 });
2817}
2818
2819sub vm_resume {
2820 my ($vmid, $skiplock) = @_;
2821
6b64503e 2822 lock_config($vmid, sub {
1e3baf05 2823
6b64503e 2824 my $conf = load_config($vmid);
1e3baf05 2825
6b64503e 2826 check_lock($conf) if !$skiplock;
1e3baf05 2827
ff1a2432 2828 vm_monitor_command($vmid, "cont");
1e3baf05
DM
2829 });
2830}
2831
5fdbe4f0
DM
2832sub vm_sendkey {
2833 my ($vmid, $skiplock, $key) = @_;
1e3baf05 2834
6b64503e 2835 lock_config($vmid, sub {
1e3baf05 2836
6b64503e 2837 my $conf = load_config($vmid);
1e3baf05 2838
ff1a2432 2839 vm_monitor_command($vmid, "sendkey $key");
1e3baf05
DM
2840 });
2841}
2842
2843sub vm_destroy {
2844 my ($storecfg, $vmid, $skiplock) = @_;
2845
6b64503e 2846 lock_config($vmid, sub {
1e3baf05 2847
6b64503e 2848 my $conf = load_config($vmid);
1e3baf05 2849
6b64503e 2850 check_lock($conf) if !$skiplock;
1e3baf05 2851
ff1a2432
DM
2852 if (!check_running($vmid)) {
2853 fairsched_rmnod($vmid); # try to destroy group
2854 destroy_vm($storecfg, $vmid);
2855 } else {
2856 die "VM $vmid is running - destroy failed\n";
1e3baf05
DM
2857 }
2858 });
2859}
2860
2861sub vm_stopall {
ff1a2432 2862 my ($storecfg, $timeout) = @_;
1e3baf05
DM
2863
2864 $timeout = 3*60 if !$timeout;
2865
ff1a2432
DM
2866 my $cleanuphash = {};
2867
1e3baf05
DM
2868 my $vzlist = vzlist();
2869 my $count = 0;
2870 foreach my $vmid (keys %$vzlist) {
2871 next if !$vzlist->{$vmid}->{pid};
2872 $count++;
ff1a2432 2873 $cleanuphash->{$vmid} = 1;
1e3baf05
DM
2874 }
2875
ff1a2432 2876 return if !$count;
1e3baf05 2877
ff1a2432
DM
2878 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs\n";
2879 syslog('info', $msg);
2880 warn $msg;
1e3baf05 2881
ff1a2432
DM
2882 foreach my $vmid (keys %$vzlist) {
2883 next if !$vzlist->{$vmid}->{pid};
bbbe5146
DM
2884 eval { vm_monitor_command($vmid, "system_powerdown"); };
2885 warn $@ if $@;
ff1a2432 2886 }
1e3baf05 2887
ff1a2432
DM
2888 my $wt = 5;
2889 my $maxtries = int(($timeout + $wt -1)/$wt);
2890 my $try = 0;
2891 while (($try < $maxtries) && $count) {
2892 $try++;
2893 sleep $wt;
afdb31d5 2894
ff1a2432
DM
2895 $vzlist = vzlist();
2896 $count = 0;
2897 foreach my $vmid (keys %$vzlist) {
2898 next if !$vzlist->{$vmid}->{pid};
2899 $count++;
1e3baf05 2900 }
ff1a2432
DM
2901 last if !$count;
2902 }
1e3baf05 2903
ff1a2432 2904 if ($count) {
1e3baf05
DM
2905
2906 foreach my $vmid (keys %$vzlist) {
2907 next if !$vzlist->{$vmid}->{pid};
19672434 2908
ff1a2432
DM
2909 warn "VM $vmid still running - sending stop now\n";
2910 eval { vm_monitor_command($vmid, "quit"); };
2911 warn $@ if $@;
1e3baf05
DM
2912 }
2913
2914 $timeout = 30;
6b64503e 2915 $maxtries = int(($timeout + $wt -1)/$wt);
1e3baf05
DM
2916 $try = 0;
2917 while (($try < $maxtries) && $count) {
2918 $try++;
2919 sleep $wt;
afdb31d5 2920
1e3baf05
DM
2921 $vzlist = vzlist();
2922 $count = 0;
2923 foreach my $vmid (keys %$vzlist) {
2924 next if !$vzlist->{$vmid}->{pid};
2925 $count++;
2926 }
2927 last if !$count;
2928 }
2929
ff1a2432 2930 if ($count) {
1e3baf05 2931
ff1a2432
DM
2932 foreach my $vmid (keys %$vzlist) {
2933 next if !$vzlist->{$vmid}->{pid};
19672434 2934
ff1a2432
DM
2935 warn "VM $vmid still running - terminating now with SIGTERM\n";
2936 kill 15, $vzlist->{$vmid}->{pid};
2937 }
2938 sleep 1;
1e3baf05
DM
2939 }
2940
2941 # this is called by system shotdown scripts, so remaining
2942 # processes gets killed anyways (no need to send kill -9 here)
ff1a2432 2943 }
1e3baf05 2944
ff1a2432
DM
2945 $vzlist = vzlist();
2946 foreach my $vmid (keys %$cleanuphash) {
2947 next if $vzlist->{$vmid}->{pid};
afdb31d5 2948 eval {
ff1a2432 2949 my $conf = load_config($vmid);
afdb31d5 2950 vm_stop_cleanup($storecfg, $vmid, $conf);
ff1a2432
DM
2951 };
2952 warn $@ if $@;
1e3baf05 2953 }
ff1a2432
DM
2954
2955 $msg = "Qemu Server stopped\n";
2956 syslog('info', $msg);
2957 print $msg;
1e3baf05
DM
2958}
2959
2960# pci helpers
2961
2962sub file_write {
2963 my ($filename, $buf) = @_;
2964
6b64503e 2965 my $fh = IO::File->new($filename, "w");
1e3baf05
DM
2966 return undef if !$fh;
2967
2968 my $res = print $fh $buf;
2969
2970 $fh->close();
2971
2972 return $res;
2973}
2974
2975sub pci_device_info {
2976 my ($name) = @_;
2977
2978 my $res;
2979
2980 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
2981 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
2982
2983 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
2984 return undef if !defined($irq) || $irq !~ m/^\d+$/;
2985
2986 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
2987 return undef if !defined($vendor) || $vendor !~ s/^0x//;
2988
2989 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
2990 return undef if !defined($product) || $product !~ s/^0x//;
2991
2992 $res = {
2993 name => $name,
2994 vendor => $vendor,
2995 product => $product,
2996 domain => $domain,
2997 bus => $bus,
2998 slot => $slot,
2999 func => $func,
3000 irq => $irq,
3001 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
3002 };
3003
3004 return $res;
3005}
3006
3007sub pci_dev_reset {
3008 my ($dev) = @_;
3009
3010 my $name = $dev->{name};
3011
3012 my $fn = "$pcisysfs/devices/$name/reset";
3013
6b64503e 3014 return file_write($fn, "1");
1e3baf05
DM
3015}
3016
3017sub pci_dev_bind_to_stub {
3018 my ($dev) = @_;
3019
3020 my $name = $dev->{name};
3021
3022 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3023 return 1 if -d $testdir;
3024
3025 my $data = "$dev->{vendor} $dev->{product}";
6b64503e 3026 return undef if !file_write("$pcisysfs/drivers/pci-stub/new_id", $data);
1e3baf05
DM
3027
3028 my $fn = "$pcisysfs/devices/$name/driver/unbind";
6b64503e 3029 if (!file_write($fn, $name)) {
1e3baf05
DM
3030 return undef if -f $fn;
3031 }
3032
3033 $fn = "$pcisysfs/drivers/pci-stub/bind";
3034 if (! -d $testdir) {
6b64503e 3035 return undef if !file_write($fn, $name);
1e3baf05
DM
3036 }
3037
3038 return -d $testdir;
3039}
3040
afdb31d5 3041sub print_pci_addr {
72a063e4 3042 my ($id) = @_;
6b64503e 3043
72a063e4 3044 my $res = '';
6b64503e 3045 my $devices = {
e5f7f8ed
DA
3046 #addr1 : ide,parallel,serial (motherboard)
3047 #addr2 : first videocard
13b5a753 3048 balloon0 => { bus => 0, addr => 3 },
0a40e8ea 3049 watchdog => { bus => 0, addr => 4 },
69b6ae0c
DA
3050 lsi0 => { bus => 0, addr => 5 },
3051 lsi1 => { bus => 0, addr => 6 },
6b64503e
DM
3052 virtio0 => { bus => 0, addr => 10 },
3053 virtio1 => { bus => 0, addr => 11 },
3054 virtio2 => { bus => 0, addr => 12 },
3055 virtio3 => { bus => 0, addr => 13 },
3056 virtio4 => { bus => 0, addr => 14 },
3057 virtio5 => { bus => 0, addr => 15 },
b78ebef7
DA
3058 hostpci0 => { bus => 0, addr => 16 },
3059 hostpci1 => { bus => 0, addr => 17 },
f290f8d9
DA
3060 net0 => { bus => 0, addr => 18 },
3061 net1 => { bus => 0, addr => 19 },
3062 net2 => { bus => 0, addr => 20 },
3063 net3 => { bus => 0, addr => 21 },
3064 net4 => { bus => 0, addr => 22 },
3065 net5 => { bus => 0, addr => 23 },
e5f7f8ed 3066 #addr29 : usb-host (pve-usb.cfg)
6b64503e
DM
3067 };
3068
3069 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
72a063e4
DA
3070 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
3071 $res = ",bus=pci.$devices->{$id}->{bus},addr=$addr";
3072 }
3073 return $res;
3074
3075}
3076
13a48620 3077sub vm_balloonset {
7878afeb 3078 my ($vmid, $value) = @_;
13a48620 3079
ff1a2432 3080 vm_monitor_command($vmid, "balloon $value");
13a48620
DA
3081}
3082
3e16d5fc
DM
3083# vzdump restore implementaion
3084
3085sub archive_read_firstfile {
3086 my $archive = shift;
afdb31d5 3087
3e16d5fc
DM
3088 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
3089
3090 # try to detect archive type first
3091 my $pid = open (TMP, "tar tf '$archive'|") ||
3092 die "unable to open file '$archive'\n";
3093 my $firstfile = <TMP>;
3094 kill 15, $pid;
3095 close TMP;
3096
3097 die "ERROR: archive contaions no data\n" if !$firstfile;
3098 chomp $firstfile;
3099
3100 return $firstfile;
3101}
3102
3103sub restore_cleanup {
3104 my $statfile = shift;
3105
3106 print STDERR "starting cleanup\n";
3107
3108 if (my $fd = IO::File->new($statfile, "r")) {
3109 while (defined(my $line = <$fd>)) {
3110 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3111 my $volid = $2;
3112 eval {
3113 if ($volid =~ m|^/|) {
3114 unlink $volid || die 'unlink failed\n';
3115 } else {
3116 my $cfg = cfs_read_file('storage.cfg');
3117 PVE::Storage::vdisk_free($cfg, $volid);
3118 }
afdb31d5 3119 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3e16d5fc
DM
3120 };
3121 print STDERR "unable to cleanup '$volid' - $@" if $@;
3122 } else {
3123 print STDERR "unable to parse line in statfile - $line";
afdb31d5 3124 }
3e16d5fc
DM
3125 }
3126 $fd->close();
3127 }
3128}
3129
3130sub restore_archive {
3131 my ($archive, $vmid, $opts) = @_;
3132
9c502e26
DM
3133 if ($archive ne '-') {
3134 my $firstfile = archive_read_firstfile($archive);
3135 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
3136 if $firstfile ne 'qemu-server.conf';
3137 }
3e16d5fc
DM
3138
3139 my $tocmd = "/usr/lib/qemu-server/qmextract";
3140
2415a446 3141 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
3e16d5fc
DM
3142 $tocmd .= ' --prealloc' if $opts->{prealloc};
3143 $tocmd .= ' --info' if $opts->{info};
3144
9c502e26
DM
3145 # tar option "xf" does not autodetect compression when read fron STDIN,
3146 # so we pipe to zcat
2415a446
DM
3147 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
3148 PVE::Tools::shellquote("--to-command=$tocmd");
3e16d5fc
DM
3149
3150 my $tmpdir = "/var/tmp/vzdumptmp$$";
3151 mkpath $tmpdir;
3152
3153 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
3154 local $ENV{VZDUMP_VMID} = $vmid;
3155
3156 my $conffile = PVE::QemuServer::config_file($vmid);
3157 my $tmpfn = "$conffile.$$.tmp";
3158
3159 # disable interrupts (always do cleanups)
3160 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
3161 print STDERR "got interrupt - ignored\n";
3162 };
3163
afdb31d5 3164 eval {
3e16d5fc
DM
3165 # enable interrupts
3166 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
3167 die "interrupted by signal\n";
3168 };
3169
9c502e26
DM
3170 if ($archive eq '-') {
3171 print "extracting archive from STDIN\n";
3172 run_command($cmd, input => "<&STDIN");
3173 } else {
3174 print "extracting archive '$archive'\n";
3175 run_command($cmd);
3176 }
3e16d5fc
DM
3177
3178 return if $opts->{info};
3179
3180 # read new mapping
3181 my $map = {};
3182 my $statfile = "$tmpdir/qmrestore.stat";
3183 if (my $fd = IO::File->new($statfile, "r")) {
3184 while (defined (my $line = <$fd>)) {
3185 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3186 $map->{$1} = $2 if $1;
3187 } else {
3188 print STDERR "unable to parse line in statfile - $line\n";
3189 }
3190 }
3191 $fd->close();
3192 }
3193
3194 my $confsrc = "$tmpdir/qemu-server.conf";
3195
3196 my $srcfd = new IO::File($confsrc, "r") ||
3197 die "unable to open file '$confsrc'\n";
3198
3199 my $outfd = new IO::File ($tmpfn, "w") ||
3200 die "unable to write config for VM $vmid\n";
3201
51586c3a
DM
3202 my $netcount = 0;
3203
3e16d5fc
DM
3204 while (defined (my $line = <$srcfd>)) {
3205 next if $line =~ m/^\#vzdump\#/;
3206 next if $line =~ m/^lock:/;
3207 next if $line =~ m/^unused\d+:/;
3208
51586c3a
DM
3209 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3210 # try to convert old 1.X settings
3211 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3212 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
3213 my ($model, $macaddr) = split(/\=/, $devconfig);
3214 $macaddr = PVE::Tools::random_ether_addr() if !$macaddr || $opts->{unique};
3215 my $net = {
3216 model => $model,
3217 bridge => "vmbr$ind",
3218 macaddr => $macaddr,
3219 };
3220 my $netstr = print_net($net);
3221 print $outfd "net${netcount}: $netstr\n";
3222 $netcount++;
3223 }
3224 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && ($opts->{unique})) {
3225 my ($id, $netstr) = ($1, $2);
3226 my $net = parse_net($netstr);
3227 $net->{macaddr} = PVE::Tools::random_ether_addr() if $net->{macaddr};
3228 $netstr = print_net($net);
afdb31d5 3229 print $outfd "$id: $netstr\n";
51586c3a 3230 } elsif ($line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/) {
3e16d5fc
DM
3231 my $virtdev = $1;
3232 my $value = $2;
3233 if ($line =~ m/backup=no/) {
3234 print $outfd "#$line";
3235 } elsif ($virtdev && $map->{$virtdev}) {
3236 my $di = PVE::QemuServer::parse_drive($virtdev, $value);
3237 $di->{file} = $map->{$virtdev};
3238 $value = PVE::QemuServer::print_drive($vmid, $di);
3239 print $outfd "$virtdev: $value\n";
3240 } else {
3241 print $outfd $line;
3242 }
3243 } else {
3244 print $outfd $line;
3245 }
3246 }
3247
3248 $srcfd->close();
3249 $outfd->close();
3250 };
3251 my $err = $@;
3252
afdb31d5 3253 if ($err) {
3e16d5fc
DM
3254
3255 unlink $tmpfn;
3256
3257 restore_cleanup("$tmpdir/qmrestore.stat") if !$opts->{info};
afdb31d5 3258
3e16d5fc 3259 die $err;
afdb31d5 3260 }
3e16d5fc
DM
3261
3262 rmtree $tmpdir;
3263
3264 rename $tmpfn, $conffile ||
3265 die "unable to commit configuration file '$conffile'\n";
3266};
3267
1e3baf05 32681;