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