]>
git.proxmox.com Git - qemu-server.git/blob - PVE/QemuServer.pm
1 package PVE
:: QemuServer
;
20 use Storable
qw(dclone) ;
21 use PVE
:: Exception
qw(raise raise_param_exc) ;
23 use PVE
:: Tools
qw(run_command lock_file file_read_firstline) ;
24 use PVE
:: Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file) ;
27 use Time
:: HiRes qw
( gettimeofday
);
29 my $clock_ticks = POSIX
:: sysconf
(& POSIX
:: _SC_CLK_TCK
);
31 # Note about locking: we use flock on the config file protect
32 # against concurent actions.
33 # Aditionaly, we have a 'lock' setting in the config file. This
34 # can be set to 'migrate' or 'backup'. Most actions are not
35 # allowed when such lock is set. But you can ignore this kind of
36 # lock with the --skiplock flag.
38 cfs_register_file
( '/qemu-server/' , \
& parse_vm_config
);
40 #no warnings 'redefine';
42 unless ( defined (& _VZSYSCALLS_H_
)) {
43 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined (& _VZSYSCALLS_H_
);
44 require 'sys/syscall.ph' ;
45 if ( defined (& __x86_64__
)) {
46 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined (& __NR_fairsched_vcpus
);
47 eval 'sub __NR_fairsched_mknod () {504;}' unless defined (& __NR_fairsched_mknod
);
48 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined (& __NR_fairsched_rmnod
);
49 eval 'sub __NR_fairsched_chwt () {506;}' unless defined (& __NR_fairsched_chwt
);
50 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined (& __NR_fairsched_mvpr
);
51 eval 'sub __NR_fairsched_rate () {508;}' unless defined (& __NR_fairsched_rate
);
52 eval 'sub __NR_setluid () {501;}' unless defined (& __NR_setluid
);
53 eval 'sub __NR_setublimit () {502;}' unless defined (& __NR_setublimit
);
55 elsif ( defined ( & __i386__
) ) {
56 eval 'sub __NR_fairsched_mknod () {500;}' unless defined (& __NR_fairsched_mknod
);
57 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined (& __NR_fairsched_rmnod
);
58 eval 'sub __NR_fairsched_chwt () {502;}' unless defined (& __NR_fairsched_chwt
);
59 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined (& __NR_fairsched_mvpr
);
60 eval 'sub __NR_fairsched_rate () {504;}' unless defined (& __NR_fairsched_rate
);
61 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined (& __NR_fairsched_vcpus
);
62 eval 'sub __NR_setluid () {511;}' unless defined (& __NR_setluid
);
63 eval 'sub __NR_setublimit () {512;}' unless defined (& __NR_setublimit
);
65 die ( "no fairsched syscall for this arch" );
67 require 'asm/ioctl.ph' ;
68 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined (& KVM_GET_API_VERSION
);
72 my ( $parent, $weight, $desired ) = @_ ;
74 return syscall (& __NR_fairsched_mknod
, int ( $parent ), int ( $weight ), int ( $desired ));
80 return syscall (& __NR_fairsched_rmnod
, int ( $id ));
84 my ( $pid, $newid ) = @_ ;
86 return syscall (& __NR_fairsched_mvpr
, int ( $pid ), int ( $newid ));
90 my ( $id, $vcpus ) = @_ ;
92 return syscall (& __NR_fairsched_vcpus
, int ( $id ), int ( $vcpus ));
96 my ( $id, $op, $rate ) = @_ ;
98 return syscall (& __NR_fairsched_rate
, int ( $id ), int ( $op ), int ( $rate ));
101 use constant FAIRSCHED_SET_RATE
=> 0 ;
102 use constant FAIRSCHED_DROP_RATE
=> 1 ;
103 use constant FAIRSCHED_GET_RATE
=> 2 ;
105 sub fairsched_cpulimit
{
106 my ( $id, $limit ) = @_ ;
108 my $cpulim1024 = int ( $limit * 1024 / 100 );
109 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
111 return fairsched_rate
( $id, $op, $cpulim1024 );
114 my $nodename = PVE
:: INotify
:: nodename
();
116 mkdir "/etc/pve/nodes/ $nodename " ;
117 my $confdir = "/etc/pve/nodes/ $nodename/qemu -server" ;
120 my $var_run_tmpdir = "/var/run/qemu-server" ;
121 mkdir $var_run_tmpdir ;
123 my $lock_dir = "/var/lock/qemu-server" ;
126 my $pcisysfs = "/sys/bus/pci" ;
128 my $keymaphash = PVE
:: Tools
:: kvmkeymaps
();
134 description
=> "Specifies whether a VM will be started during system bootup." ,
140 description
=> "Automatic restart after crash (currently ignored)." ,
146 description
=> "Allow reboot. If set to '0' the VM exit on reboot." ,
152 description
=> "Lock/unlock the VM." ,
153 enum
=> [ qw(migrate backup) ],
158 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\n NOTE: This option is currently ignored." ,
165 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\n NOTE: You can disable fair-scheduler configuration by setting this to 0." ,
173 description
=> "Amount of RAM for the VM in MB." ,
180 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file." ,
181 enum
=> [ keys %$keymaphash ],
187 description
=> "Set a name for the VM. Only used on the configuration web interface." ,
192 description
=> "Description for the VM. Only used on the configuration web interface." ,
197 enum
=> [ qw(other wxp w2k w2k3 w2k8 wvista win7 l24 l26) ],
198 description
=> <<EODESC,
199 Used to enable special optimization/features for specific
202 other => unspecified OS
203 wxp => Microsoft Windows XP
204 w2k => Microsoft Windows 2000
205 w2k3 => Microsoft Windows 2003
206 w2k8 => Microsoft Windows 2008
207 wvista => Microsoft Windows Vista
208 win7 => Microsoft Windows 7
209 l24 => Linux 2.4 Kernel
210 l26 => Linux 2.6/3.X Kernel
212 other|l24|l26 ... no special behaviour
213 wxp|w2k|w2k3|w2k8|wvista|win7 ... use --localtime switch
219 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)." ,
220 pattern
=> '[acdn]{1,4}' ,
225 type
=> 'string' , format
=> 'pve-qm-bootdisk' ,
226 description
=> "Enable booting from specified disk." ,
227 pattern
=> '(ide|scsi|virtio)\d+' ,
232 description
=> "The number of CPUs. Please use option -sockets instead." ,
239 description
=> "The number of CPU sockets." ,
246 description
=> "The number of cores per socket." ,
253 description
=> "Enable/disable ACPI." ,
259 description
=> "Enable/disable KVM hardware virtualization." ,
265 description
=> "Enable/disable time drift fix." ,
271 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS." ,
276 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution)." ,
281 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" ,
282 enum
=> [ qw(std cirrus vmware) ],
286 type
=> 'string' , format
=> 'pve-qm-watchdog' ,
287 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]' ,
288 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)" ,
293 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)" ,
294 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'." ,
295 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)' ,
301 description
=> <<EODESCR,
302 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
304 args: -no-reboot -no-hpet
311 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." ,
316 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit." ,
320 migrate_downtime
=> {
323 description
=> "Set maximum tolerated downtime (in seconds) for migrations." ,
329 type
=> 'string' , format
=> 'pve-qm-drive' ,
330 typetext
=> 'volume' ,
331 description
=> "This is an alias for option -ide2" ,
335 description
=> "Emulated CPU type." ,
337 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom host) ],
342 # what about other qemu settings ?
344 #machine => 'string',
357 ##soundhw => 'string',
359 while ( my ( $k, $v ) = each %$confdesc ) {
360 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm- $k " , $v );
363 my $MAX_IDE_DISKS = 4 ;
364 my $MAX_SCSI_DISKS = 14 ;
365 my $MAX_VIRTIO_DISKS = 6 ;
366 my $MAX_USB_DEVICES = 5 ;
368 my $MAX_UNUSED_DISKS = 8 ;
369 my $MAX_HOSTPCI_DEVICES = 2 ;
370 my $MAX_SERIAL_PORTS = 4 ;
371 my $MAX_PARALLEL_PORTS = 3 ;
373 my $nic_model_list = [ 'rtl8139' , 'ne2k_pci' , 'e1000' , 'pcnet' , 'virtio' ,
374 'ne2k_isa' , 'i82551' , 'i82557b' , 'i82559er' ];
375 my $nic_model_list_txt = join ( ' ' , sort @$nic_model_list );
380 type
=> 'string' , format
=> 'pve-qm-net' ,
381 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>]" ,
382 description
=> <<EODESCR,
383 Specify network devices.
385 MODEL is one of: $nic_model_list_txt
387 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
388 automatically generated if not specified.
390 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
392 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
394 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
400 The DHCP server assign addresses to the guest starting from 10.0.2.15.
404 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-net" , $netdesc );
406 for ( my $i = 0 ; $i < $MAX_NETS ; $i++ ) {
407 $confdesc ->{ "net $i " } = $netdesc ;
414 type
=> 'string' , format
=> 'pve-qm-drive' ,
415 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]' ,
416 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to 3)." ,
418 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-ide" , $idedesc );
422 type
=> 'string' , format
=> 'pve-qm-drive' ,
423 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]' ,
424 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13)." ,
426 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-scsi" , $scsidesc );
430 type
=> 'string' , format
=> 'pve-qm-drive' ,
431 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]' ,
432 description
=> "Use volume as VIRTIO hard disk (n is 0 to 5)." ,
434 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-virtio" , $virtiodesc );
438 type
=> 'string' , format
=> 'pve-qm-usb-device' ,
439 typetext
=> 'host=HOSTUSBDEVICE' ,
440 description
=> <<EODESCR,
441 Configure an USB device (n is 0 to 4). This can be used to
442 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
444 'bus-port(.port)*' (decimal numbers) or
445 'vendor_id:product_id' (hexadeciaml numbers)
447 You can use the 'lsusb -t' command to list existing usb devices.
449 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
453 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-usb" , $usbdesc );
457 type
=> 'string' , format
=> 'pve-qm-hostpci' ,
458 typetext
=> "HOSTPCIDEVICE" ,
459 description
=> <<EODESCR,
460 Map host pci devices. HOSTPCIDEVICE syntax is:
462 'bus:dev.func' (hexadecimal numbers)
464 You can us the 'lspci' command to list existing pci devices.
466 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
468 Experimental: user reported problems with this option.
471 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-hostpci" , $hostpcidesc );
476 pattern
=> '/dev/ttyS\d+' ,
477 description
=> <<EODESCR,
478 Map host serial devices (n is 0 to 3).
480 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
482 Experimental: user reported problems with this option.
489 pattern
=> '/dev/parport\d+' ,
490 description
=> <<EODESCR,
491 Map host parallel devices (n is 0 to 2).
493 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
495 Experimental: user reported problems with this option.
499 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
500 $confdesc ->{ "parallel $i " } = $paralleldesc ;
503 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
504 $confdesc ->{ "serial $i " } = $serialdesc ;
507 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
508 $confdesc ->{ "hostpci $i " } = $hostpcidesc ;
511 for ( my $i = 0 ; $i < $MAX_IDE_DISKS ; $i++ ) {
512 $drivename_hash ->{ "ide $i " } = 1 ;
513 $confdesc ->{ "ide $i " } = $idedesc ;
516 for ( my $i = 0 ; $i < $MAX_SCSI_DISKS ; $i++ ) {
517 $drivename_hash ->{ "scsi $i " } = 1 ;
518 $confdesc ->{ "scsi $i " } = $scsidesc ;
521 for ( my $i = 0 ; $i < $MAX_VIRTIO_DISKS ; $i++ ) {
522 $drivename_hash ->{ "virtio $i " } = 1 ;
523 $confdesc ->{ "virtio $i " } = $virtiodesc ;
526 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
527 $confdesc ->{ "usb $i " } = $usbdesc ;
532 type
=> 'string' , format
=> 'pve-volume-id' ,
533 description
=> "Reference to unused volumes." ,
536 for ( my $i = 0 ; $i < $MAX_UNUSED_DISKS ; $i++ ) {
537 $confdesc ->{ "unused $i " } = $unuseddesc ;
540 my $kvm_api_version = 0 ;
544 return $kvm_api_version if $kvm_api_version ;
546 my $fh = IO
:: File-
> new ( "</dev/kvm" ) ||
549 if ( my $v = $fh -> ioctl ( KVM_GET_API_VERSION
(), 0 )) {
550 $kvm_api_version = $v ;
555 return $kvm_api_version ;
558 my $kvm_user_version ;
560 sub kvm_user_version
{
562 return $kvm_user_version if $kvm_user_version ;
564 $kvm_user_version = 'unknown' ;
566 my $tmp = `kvm -help 2>/dev/null` ;
568 if ( $tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+\.\d+) / ) {
569 $kvm_user_version = $2 ;
572 return $kvm_user_version ;
576 my $kernel_has_vhost_net = - c
'/dev/vhost-net' ;
579 # order is important - used to autoselect boot disk
580 return (( map { "ide $_ " } ( 0 .. ( $MAX_IDE_DISKS - 1 ))),
581 ( map { "scsi $_ " } ( 0 .. ( $MAX_SCSI_DISKS - 1 ))),
582 ( map { "virtio $_ " } ( 0 .. ( $MAX_VIRTIO_DISKS - 1 ))));
585 sub valid_drivename
{
588 return defined ( $drivename_hash ->{ $dev });
593 return defined ( $confdesc ->{ $key });
597 return $nic_model_list ;
600 sub os_list_description
{
605 w2k
=> 'Windows 2000' ,
606 w2k3
=>, 'Windows 2003' ,
607 w2k8
=> 'Windows 2008' ,
608 wvista
=> 'Windows Vista' ,
615 # a clumsy way to split an argument string into an array,
616 # we simply pass it to the cli (exec call)
617 # fixme: use Text::ParseWords::shellwords() ?
623 return $args if ! $str ;
625 my $cmd = 'perl -e \' foreach my $a ( @ARGV ) { print " $a\n "; } \' -- ' . $str ;
628 run_command
( $cmd, outfunc
=> sub {
636 die "unable to parse args: $str\n " if $err ;
641 sub disk_devive_info
{
644 die "unknown disk device format ' $dev '" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/ ;
652 } elsif ( $bus eq 'scsi' ) {
656 my $controller = int ( $index / $maxdev );
657 my $unit = $index % $maxdev ;
660 return { bus
=> $bus, desc
=> uc ( $bus ) . " $controller : $unit " ,
661 controller
=> $controller, unit
=> $unit, index => $index };
665 sub qemu_drive_name
{
666 my ( $dev, $media ) = @_ ;
668 my $info = disk_devive_info
( $dev );
671 if (( $info ->{ bus
} eq 'ide' ) || ( $info ->{ bus
} eq 'scsi' )) {
672 $mediastr = ( $media eq 'cdrom' ) ?
"-cd" : "-hd" ;
673 return sprintf ( " %s%i%s%i " , $info ->{ bus
}, $info ->{ controller
},
674 $mediastr, $info ->{ unit
});
676 return sprintf ( " %s%i " , $info ->{ bus
}, $info ->{ index });
684 return $cdrom_path if $cdrom_path ;
686 return $cdrom_path = "/dev/cdrom" if - l
"/dev/cdrom" ;
687 return $cdrom_path = "/dev/cdrom1" if - l
"/dev/cdrom1" ;
688 return $cdrom_path = "/dev/cdrom2" if - l
"/dev/cdrom2" ;
692 my ( $storecfg, $vmid, $cdrom ) = @_ ;
694 if ( $cdrom eq 'cdrom' ) {
695 return get_cdrom_path
();
696 } elsif ( $cdrom eq 'none' ) {
698 } elsif ( $cdrom =~ m
|^/|) {
701 return PVE
:: Storage
:: path
( $storecfg, $cdrom );
705 # try to convert old style file names to volume IDs
706 sub filename_to_volume_id
{
707 my ( $vmid, $file, $media ) = @_ ;
709 if (!( $file eq 'none' || $file eq 'cdrom' ||
710 $file =~ m
|^ /dev/ .+| || $file =~ m/^([^:]+):(.+)$/ )) {
712 return undef if $file =~ m
|/|;
714 if ( $media && $media eq 'cdrom' ) {
715 $file = "local:iso/ $file " ;
717 $file = "local: $vmid/$file " ;
724 sub verify_media_type
{
725 my ( $opt, $vtype, $media ) = @_ ;
730 if ( $media eq 'disk' ) {
732 } elsif ( $media eq 'cdrom' ) {
735 die "internal error" ;
738 return if ( $vtype eq $etype );
740 raise_param_exc
({ $opt => "unexpected media type ( $vtype != $etype )" });
743 sub cleanup_drive_path
{
744 my ( $opt, $storecfg, $drive ) = @_ ;
746 # try to convert filesystem paths to volume IDs
748 if (( $drive ->{ file
} !~ m/^(cdrom|none)$/ ) &&
749 ( $drive ->{ file
} !~ m
|^ /dev/ .+|) &&
750 ( $drive ->{ file
} !~ m/^([^:]+):(.+)$/ ) &&
751 ( $drive ->{ file
} !~ m/^\d+$/ )) {
752 my ( $vtype, $volid ) = PVE
:: Storage
:: path_to_volume_id
( $storecfg, $drive ->{ file
});
753 raise_param_exc
({ $opt => "unable to associate path ' $drive ->{file}' to any storage" }) if ! $vtype ;
754 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $vtype eq 'iso' ;
755 verify_media_type
( $opt, $vtype, $drive ->{ media
});
756 $drive ->{ file
} = $volid ;
759 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $drive ->{ file
} =~ m/^(cdrom|none)$/ ;
762 sub create_conf_nolock
{
763 my ( $vmid, $settings ) = @_ ;
765 my $filename = config_file
( $vmid );
767 die "configuration file ' $filename ' already exists \n " if - f
$filename ;
769 my $defaults = load_defaults
();
771 $settings ->{ name
} = "vm $vmid " if ! $settings ->{ name
};
772 $settings ->{ memory
} = $defaults ->{ memory
} if ! $settings ->{ memory
};
775 foreach my $opt ( keys %$settings ) {
776 next if ! $confdesc ->{ $opt };
778 my $value = $settings ->{ $opt };
781 $data .= " $opt : $value\n " ;
784 PVE
:: Tools
:: file_set_contents
( $filename, $data );
787 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
788 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
789 # [,aio=native|threads]
792 my ( $key, $data ) = @_ ;
796 # $key may be undefined - used to verify JSON parameters
797 if (! defined ( $key )) {
798 $res ->{ interface
} = 'unknown' ; # should not harm when used to verify parameters
800 } elsif ( $key =~ m/^([^\d]+)(\d+)$/ ) {
801 $res ->{ interface
} = $1 ;
807 foreach my $p ( split ( /,/ , $data )) {
808 next if $p =~ m/^\s*$/ ;
810 if ( $p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio)=(.+)$/ ) {
811 my ( $k, $v ) = ( $1, $2 );
813 $k = 'file' if $k eq 'volume' ;
815 return undef if defined $res ->{ $k };
819 if (! $res ->{ file
} && $p !~ m/=/ ) {
827 return undef if ! $res ->{ file
};
829 return undef if $res ->{ cache
} &&
830 $res ->{ cache
} !~ m/^(off|none|writethrough|writeback)$/ ;
831 return undef if $res ->{ snapshot
} && $res ->{ snapshot
} !~ m/^(on|off)$/ ;
832 return undef if $res ->{ cyls
} && $res ->{ cyls
} !~ m/^\d+$/ ;
833 return undef if $res ->{ heads
} && $res ->{ heads
} !~ m/^\d+$/ ;
834 return undef if $res ->{ secs
} && $res ->{ secs
} !~ m/^\d+$/ ;
835 return undef if $res ->{ media
} && $res ->{ media
} !~ m/^(disk|cdrom)$/ ;
836 return undef if $res ->{ trans
} && $res ->{ trans
} !~ m/^(none|lba|auto)$/ ;
837 return undef if $res ->{ format
} && $res ->{ format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/ ;
838 return undef if $res ->{ rerror
} && $res ->{ rerror
} !~ m/^(ignore|report|stop)$/ ;
839 return undef if $res ->{ werror
} && $res ->{ werror
} !~ m/^(enospc|ignore|report|stop)$/ ;
840 return undef if $res ->{ backup
} && $res ->{ backup
} !~ m/^(yes|no)$/ ;
841 return undef if $res ->{ aio
} && $res ->{ aio
} !~ m/^(native|threads)$/ ;
843 if ( $res ->{ media
} && ( $res ->{ media
} eq 'cdrom' )) {
844 return undef if $res ->{ snapshot
} || $res ->{ trans
} || $res ->{ format
};
845 return undef if $res ->{ heads
} || $res ->{ secs
} || $res ->{ cyls
};
846 return undef if $res ->{ interface
} eq 'virtio' ;
849 # rerror does not work with scsi drives
850 if ( $res ->{ rerror
}) {
851 return undef if $res ->{ interface
} eq 'scsi' ;
857 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio) ;
860 my ( $vmid, $drive ) = @_ ;
863 foreach my $o ( @qemu_drive_options, 'backup' ) {
864 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
867 return " $drive ->{file} $opts " ;
870 sub print_drivedevice_full
{
871 my ( $storecfg, $vmid, $drive ) = @_ ;
876 if ( $drive ->{ interface
} eq 'virtio' ) {
878 $device = "virtio-blk-pci,drive=drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index}" ;
881 elsif ( $drive ->{ interface
} eq 'scsi' ) {
884 my $controller = int ( $drive ->{ index } / $maxdev );
885 my $unit = $drive ->{ index } % $maxdev ;
887 $device = "scsi-disk,bus=scsi $controller .0,scsi-id= $unit,drive =drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index}" ;
890 elsif ( $drive ->{ interface
} eq 'ide' ){
893 my $controller = int ( $drive ->{ index } / $maxdev );
894 my $unit = $drive ->{ index } % $maxdev ;
896 $device = "ide-drive,bus=ide. $controller,unit = $unit,drive =drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index}" ;
899 if ( $drive ->{ interface
} eq 'usb' ){
900 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
906 sub print_drive_full
{
907 my ( $storecfg, $vmid, $drive ) = @_ ;
910 foreach my $o ( @qemu_drive_options ) {
911 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
914 # use linux-aio by default (qemu default is threads)
915 $opts .= ",aio=native" if ! $drive ->{ aio
};
918 my $volid = $drive ->{ file
};
919 if ( drive_is_cdrom
( $drive )) {
920 $path = get_iso_path
( $storecfg, $vmid, $volid );
922 if ( $volid =~ m
|^/|) {
925 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
929 my $pathinfo = $path ?
"file= $path, " : '' ;
931 return "${pathinfo}if=none,id=drive- $drive ->{interface} $drive ->{index} $opts " ;
938 return $drive && $drive ->{ media
} && ( $drive ->{ media
} eq 'cdrom' );
945 return undef if ! $value ;
949 if ( $value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/ ) {
950 $res ->{ pciid
} = $value ;
958 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
964 foreach my $kvp ( split ( /,/ , $data )) {
966 if ( $kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i ) {
968 my $mac = uc ( $3 ) || random_ether_addr
();
969 $res ->{ model
} = $model ;
970 $res ->{ macaddr
} = $mac ;
971 } elsif ( $kvp =~ m/^bridge=(\S+)$/ ) {
973 } elsif ( $kvp =~ m/^rate=(\d+(\.\d+)?)$/ ) {
981 return undef if ! $res ->{ model
};
989 my $res = " $net ->{model}" ;
990 $res .= "= $net ->{macaddr}" if $net ->{ macaddr
};
991 $res .= ",bridge= $net ->{bridge}" if $net ->{ bridge
};
992 $res .= ",rate= $net ->{rate}" if $net ->{ rate
};
997 sub add_random_macs
{
1000 foreach my $opt ( keys %$settings ) {
1001 next if $opt !~ m/^net(\d+)$/ ;
1002 my $net = parse_net
( $settings ->{ $opt });
1004 $settings ->{ $opt } = print_net
( $net );
1008 sub add_unused_volume
{
1009 my ( $config, $res, $volid ) = @_ ;
1012 for ( my $ind = $MAX_UNUSED_DISKS - 1 ; $ind >= 0 ; $ind --) {
1013 my $test = "unused $ind " ;
1014 if ( my $vid = $config ->{ $test }) {
1015 return if $vid eq $volid ; # do not add duplicates
1021 die "To many unused volume - please delete them first. \n " if ! $key ;
1023 $res ->{ $key } = $volid ;
1026 # fixme: remove all thos $noerr parameters?
1028 PVE
:: JSONSchema
:: register_format
( 'pve-qm-bootdisk' , \
& verify_bootdisk
);
1029 sub verify_bootdisk
{
1030 my ( $value, $noerr ) = @_ ;
1032 return $value if valid_drivename
( $value );
1034 return undef if $noerr ;
1036 die "invalid boot disk ' $value ' \n " ;
1039 PVE
:: JSONSchema
:: register_format
( 'pve-qm-net' , \
& verify_net
);
1041 my ( $value, $noerr ) = @_ ;
1043 return $value if parse_net
( $value );
1045 return undef if $noerr ;
1047 die "unable to parse network options \n " ;
1050 PVE
:: JSONSchema
:: register_format
( 'pve-qm-drive' , \
& verify_drive
);
1052 my ( $value, $noerr ) = @_ ;
1054 return $value if parse_drive
( undef , $value );
1056 return undef if $noerr ;
1058 die "unable to parse drive options \n " ;
1061 PVE
:: JSONSchema
:: register_format
( 'pve-qm-hostpci' , \
& verify_hostpci
);
1062 sub verify_hostpci
{
1063 my ( $value, $noerr ) = @_ ;
1065 return $value if parse_hostpci
( $value );
1067 return undef if $noerr ;
1069 die "unable to parse pci id \n " ;
1072 PVE
:: JSONSchema
:: register_format
( 'pve-qm-watchdog' , \
& verify_watchdog
);
1073 sub verify_watchdog
{
1074 my ( $value, $noerr ) = @_ ;
1076 return $value if parse_watchdog
( $value );
1078 return undef if $noerr ;
1080 die "unable to parse watchdog options \n " ;
1083 sub parse_watchdog
{
1086 return undef if ! $value ;
1090 foreach my $p ( split ( /,/ , $value )) {
1091 next if $p =~ m/^\s*$/ ;
1093 if ( $p =~ m/^(model=)?(i6300esb|ib700)$/ ) {
1095 } elsif ( $p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/ ) {
1096 $res ->{ action
} = $2 ;
1105 sub parse_usb_device
{
1108 return undef if ! $value ;
1110 my @dl = split ( /,/ , $value );
1114 foreach my $v ( @dl ) {
1115 if ( $v =~ m/^host=([0-9A-Fa-f]{4}):([0-9A-Fa-f]{4})$/ ) {
1117 $res ->{ vendorid
} = $1 ;
1118 $res ->{ productid
} = $2 ;
1119 } elsif ( $v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/ ) {
1121 $res ->{ hostbus
} = $1 ;
1122 $res ->{ hostport
} = $2 ;
1127 return undef if ! $found ;
1132 PVE
:: JSONSchema
:: register_format
( 'pve-qm-usb-device' , \
& verify_usb_device
);
1133 sub verify_usb_device
{
1134 my ( $value, $noerr ) = @_ ;
1136 return $value if parse_usb_device
( $value );
1138 return undef if $noerr ;
1140 die "unable to parse usb device \n " ;
1143 # add JSON properties for create and set function
1144 sub json_config_properties
{
1147 foreach my $opt ( keys %$confdesc ) {
1148 $prop ->{ $opt } = $confdesc ->{ $opt };
1155 my ( $key, $value ) = @_ ;
1157 die "unknown setting ' $key ' \n " if ! $confdesc ->{ $key };
1159 my $type = $confdesc ->{ $key }->{ type
};
1161 if (! defined ( $value )) {
1162 die "got undefined value \n " ;
1165 if ( $value =~ m/[\n\r]/ ) {
1166 die "property contains a line feed \n " ;
1169 if ( $type eq 'boolean' ) {
1170 return 1 if ( $value eq '1' ) || ( $value =~ m/^(on|yes|true)$/i );
1171 return 0 if ( $value eq '0' ) || ( $value =~ m/^(off|no|false)$/i );
1172 die "type check ('boolean') failed - got ' $value ' \n " ;
1173 } elsif ( $type eq 'integer' ) {
1174 return int ( $1 ) if $value =~ m/^(\d+)$/ ;
1175 die "type check ('integer') failed - got ' $value ' \n " ;
1176 } elsif ( $type eq 'string' ) {
1177 if ( my $fmt = $confdesc ->{ $key }->{ format
}) {
1178 if ( $fmt eq 'pve-qm-drive' ) {
1179 # special case - we need to pass $key to parse_drive()
1180 my $drive = parse_drive
( $key, $value );
1181 return $value if $drive ;
1182 die "unable to parse drive options \n " ;
1184 PVE
:: JSONSchema
:: check_format
( $fmt, $value );
1187 $value =~ s/^\"(.*)\"$/$1/ ;
1190 die "internal error"
1195 my ( $vmid, $code, @param ) = @_ ;
1197 my $filename = config_file_lock
( $vmid );
1199 lock_file
( $filename, 10 , $code, @param );
1204 sub cfs_config_path
{
1205 my ( $vmid, $node ) = @_ ;
1207 $node = $nodename if ! $node ;
1208 return "nodes/ $node/qemu -server/ $vmid .conf" ;
1211 sub check_iommu_support
{
1212 #fixme : need to check IOMMU support
1213 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1221 my ( $vmid, $node ) = @_ ;
1223 my $cfspath = cfs_config_path
( $vmid, $node );
1224 return "/etc/pve/ $cfspath " ;
1227 sub config_file_lock
{
1230 return " $lock_dir/lock - $vmid .conf" ;
1236 my $conf = config_file
( $vmid );
1237 utime undef , undef , $conf ;
1241 my ( $storecfg, $vmid, $settings ) = @_ ;
1246 foreach_drive
( $settings, sub {
1247 my ( $ds, $disk ) = @_ ;
1249 return if drive_is_cdrom
( $disk );
1251 my $file = $disk ->{ file
};
1253 if ( $file =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/ ) {
1254 my $storeid = $2 || 'local' ;
1256 my $defformat = PVE
:: Storage
:: storage_default_format
( $storecfg, $storeid );
1257 my $fmt = $disk ->{ format
} || $defformat ;
1258 syslog
( 'info' , "VM $vmid creating new disk - size is $size GB" );
1260 my $volid = PVE
:: Storage
:: vdisk_alloc
( $storecfg, $storeid, $vmid,
1261 $fmt, undef , $size*1024*1024 );
1263 $disk ->{ file
} = $volid ;
1264 delete ( $disk ->{ format
}); # no longer needed
1265 push @$vollist, $volid ;
1266 $settings ->{ $ds } = PVE
:: QemuServer
:: print_drive
( $vmid, $disk );
1269 if ( $disk ->{ file
} =~ m
|^ /dev/ .+|) {
1270 $path = $disk ->{ file
};
1272 $path = PVE
:: Storage
:: path
( $storecfg, $disk ->{ file
});
1274 if (!(- f
$path || - b
$path )) {
1275 die "image ' $path ' does not exists \n " ;
1284 syslog
( 'err' , "VM $vmid creating disks failed" );
1285 foreach my $volid ( @$vollist ) {
1286 eval { PVE
:: Storage
:: vdisk_free
( $storecfg, $volid ); };
1296 my ( $storecfg, $vmid, $volid ) = @_ ;
1298 die "reject to unlink absolute path ' $volid '"
1301 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1303 die "reject to unlink ' $volid ' - not owned by this VM"
1304 if ! $owner || ( $owner != $vmid );
1306 syslog
( 'info' , "VM $vmid deleting volume ' $volid '" );
1308 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1310 touch_config
( $vmid );
1314 my ( $storecfg, $vmid ) = @_ ;
1316 my $conffile = config_file
( $vmid );
1318 my $conf = load_config
( $vmid );
1322 # only remove disks owned by this VM
1323 foreach_drive
( $conf, sub {
1324 my ( $ds, $drive ) = @_ ;
1326 return if drive_is_cdrom
( $drive );
1328 my $volid = $drive ->{ file
};
1329 next if ! $volid || $volid =~ m
|^/|;
1331 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1332 next if ! $path || ! $owner || ( $owner != $vmid );
1334 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1339 # also remove unused disk
1341 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid );
1344 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1345 my ( $volid, $sid, $volname, $d ) = @_ ;
1346 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1356 sub load_diskinfo_old
{
1357 my ( $storecfg, $vmid, $conf ) = @_ ;
1363 foreach_drive
( $conf, sub {
1368 return if drive_is_cdrom
( $di );
1370 if ( $di ->{ file
} =~ m
|^ /dev/ .+|) {
1371 $info ->{ $di ->{ file
}}->{ size
} = PVE
:: Storage
:: file_size_info
( $di ->{ file
});
1373 push @$vollist, $di ->{ file
};
1378 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid, $vollist );
1380 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1381 my ( $volid, $sid, $volname, $d ) = @_ ;
1382 $info ->{ $volid } = $d ;
1387 foreach my $ds ( keys %$res ) {
1388 my $di = $res ->{ $ds };
1390 $res ->{ $ds }->{ disksize
} = $info ->{ $di ->{ file
}} ?
1391 $info ->{ $di ->{ file
}}->{ size
} / ( 1024 * 1024 ) : 0 ;
1400 my $cfspath = cfs_config_path
( $vmid );
1402 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath );
1404 die "no such VM (' $vmid ') \n " if ! defined ( $conf );
1409 sub parse_vm_config
{
1410 my ( $filename, $raw ) = @_ ;
1412 return undef if ! defined ( $raw );
1415 digest
=> Digest
:: SHA1
:: sha1_hex
( $raw ),
1418 $filename =~ m
| /qemu-server/ ( \d
+) \
. conf
$|
1419 || die "got strange filename ' $filename '" ;
1423 while ( $raw && $raw =~ s/^(.*?)(\n|$)// ) {
1426 next if $line =~ m/^\#/ ;
1428 next if $line =~ m/^\s*$/ ;
1430 if ( $line =~ m/^(description):\s*(.*\S)\s*$/ ) {
1432 my $value = PVE
:: Tools
:: decode_text
( $2 );
1433 $res ->{ $key } = $value ;
1434 } elsif ( $line =~ m/^(args):\s*(.*\S)\s*$/ ) {
1437 $res ->{ $key } = $value ;
1438 } elsif ( $line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/ ) {
1441 eval { $value = check_type
( $key, $value ); };
1443 warn "vm $vmid - unable to parse value of ' $key ' - $@ " ;
1445 my $fmt = $confdesc ->{ $key }->{ format
};
1446 if ( $fmt && $fmt eq 'pve-qm-drive' ) {
1447 my $v = parse_drive
( $key, $value );
1448 if ( my $volid = filename_to_volume_id
( $vmid, $v ->{ file
}, $v ->{ media
})) {
1449 $v ->{ file
} = $volid ;
1450 $value = print_drive
( $vmid, $v );
1452 warn "vm $vmid - unable to parse value of ' $key ' \n " ;
1457 if ( $key eq 'cdrom' ) {
1458 $res ->{ ide2
} = $value ;
1460 $res ->{ $key } = $value ;
1466 # convert old smp to sockets
1467 if ( $res ->{ smp
} && ! $res ->{ sockets
}) {
1468 $res ->{ sockets
} = $res ->{ smp
};
1476 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1478 lock_config
( $vmid, & change_config_nolock
, $settings, $unset, $skiplock );
1481 sub change_config_nolock
{
1482 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1486 $unset ->{ ide2
} = $unset ->{ cdrom
} if $unset ->{ cdrom
};
1488 check_lock
( $settings ) if ! $skiplock ;
1490 # we do not use 'smp' any longer
1491 if ( $settings ->{ sockets
}) {
1493 } elsif ( $settings ->{ smp
}) {
1494 $settings ->{ sockets
} = $settings ->{ smp
};
1498 my $new_volids = {};
1500 foreach my $key ( keys %$settings ) {
1501 next if $key eq 'digest' ;
1502 my $value = $settings ->{ $key };
1503 if ( $key eq 'description' ) {
1504 $value = PVE
:: Tools
:: encode_text
( $value );
1506 eval { $value = check_type
( $key, $value ); };
1507 die "unable to parse value of ' $key ' - $@ " if $@ ;
1508 if ( $key eq 'cdrom' ) {
1509 $res ->{ ide2
} = $value ;
1511 $res ->{ $key } = $value ;
1513 if ( valid_drivename
( $key )) {
1514 my $drive = PVE
:: QemuServer
:: parse_drive
( $key, $value );
1515 $new_volids ->{ $drive ->{ file
}} = 1 if $drive && $drive ->{ file
};
1519 my $filename = config_file
( $vmid );
1520 my $tmpfn = " $filename . $$ .tmp" ;
1522 my $fh = new IO
:: File
( $filename, "r" ) ||
1523 die "unable to read config for VM $vmid\n " ;
1525 my $werror = "unable to write config for VM $vmid\n " ;
1527 my $out = new IO
:: File
( $tmpfn, "w" ) || die $werror ;
1533 while ( my $line = < $fh >) {
1535 if (( $line =~ m/^\#/ ) || ( $line =~ m/^\s*$/ )) {
1536 die $werror unless print $out $line ;
1540 if ( $line =~ m/^([a-z][a-z_]*\d*):\s*(.*\S)\s*$/ ) {
1544 # remove 'unusedX' settings if we re-add a volume
1545 next if $key =~ m/^unused/ && $new_volids ->{ $value };
1547 # convert 'smp' to 'sockets'
1548 $key = 'sockets' if $key eq 'smp' ;
1550 next if $done ->{ $key };
1553 if ( defined ( $res ->{ $key })) {
1554 $value = $res ->{ $key };
1555 delete $res ->{ $key };
1557 if (! defined ( $unset ->{ $key })) {
1558 die $werror unless print $out " $key : $value\n " ;
1564 die "unable to parse config file: $line\n " ;
1567 foreach my $key ( keys %$res ) {
1569 if (! defined ( $unset ->{ $key })) {
1570 die $werror unless print $out " $key : $res ->{ $key } \n " ;
1585 if (! $out -> close ()) {
1586 $err = "close failed - $!\n " ;
1591 if (! rename ( $tmpfn, $filename )) {
1592 $err = "rename failed - $!\n " ;
1602 # we use static defaults from our JSON schema configuration
1603 foreach my $key ( keys %$confdesc ) {
1604 if ( defined ( my $default = $confdesc ->{ $key }->{ default })) {
1605 $res ->{ $key } = $default ;
1609 my $conf = PVE
:: Cluster
:: cfs_read_file
( 'datacenter.cfg' );
1610 $res ->{ keyboard
} = $conf ->{ keyboard
} if $conf ->{ keyboard
};
1616 my $vmlist = PVE
:: Cluster
:: get_vmlist
();
1618 return $res if ! $vmlist || ! $vmlist ->{ ids
};
1619 my $ids = $vmlist ->{ ids
};
1621 foreach my $vmid ( keys %$ids ) {
1622 my $d = $ids ->{ $vmid };
1623 next if ! $d ->{ node
} || $d ->{ node
} ne $nodename ;
1624 $res ->{ $vmid }->{ exists } = 1 ;
1629 # test if VM uses local resources (to prevent migration)
1630 sub check_local_resources
{
1631 my ( $conf, $noerr ) = @_ ;
1636 $loc_res = 1 if $conf ->{ hostusb
}; # old syntax
1637 $loc_res = 1 if $conf ->{ hostpci
}; # old syntax
1639 foreach my $k ( keys %$conf ) {
1640 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/ ;
1643 die "VM uses local resources \n " if $loc_res && ! $noerr ;
1651 die "VM is locked ( $conf ->{lock}) \n " if $conf ->{ lock };
1655 my ( $pidfile, $pid ) = @_ ;
1657 my $fh = IO
:: File-
> new ( "/proc/ $pid/cmdline " , "r" );
1658 if ( defined ( $fh )) {
1661 return undef if ! $line ;
1662 my @param = split ( /\0/ , $line );
1664 my $cmd = $param [ 0 ];
1665 return if ! $cmd || ( $cmd !~ m
| kvm
$|);
1667 for ( my $i = 0 ; $i < scalar ( @param ); $i++ ) {
1670 if (( $p eq '-pidfile' ) || ( $p eq '--pidfile' )) {
1671 my $p = $param [ $i+1 ];
1672 return 1 if $p && ( $p eq $pidfile );
1683 my $filename = config_file
( $vmid );
1685 die "unable to find configuration file for VM $vmid - no such machine \n "
1688 my $pidfile = pidfile_name
( $vmid );
1690 if ( my $fd = IO
:: File-
> new ( "< $pidfile " )) {
1691 my $st = stat ( $fd );
1695 my $mtime = $st -> mtime ;
1696 if ( $mtime > time ()) {
1697 warn "file ' $filename ' modified in future \n " ;
1700 if ( $line =~ m/^(\d+)$/ ) {
1703 return $pid if ((- d
"/proc/ $pid " ) && check_cmdline
( $pidfile, $pid ));
1712 my $vzlist = config_list
();
1714 my $fd = IO
:: Dir-
> new ( $var_run_tmpdir ) || return $vzlist ;
1716 while ( defined ( my $de = $fd -> read )) {
1717 next if $de !~ m/^(\d+)\.pid$/ ;
1719 next if ! defined ( $vzlist ->{ $vmid });
1720 if ( my $pid = check_running
( $vmid )) {
1721 $vzlist ->{ $vmid }->{ pid
} = $pid ;
1728 my $storage_timeout_hash = {};
1731 my ( $storecfg, $conf ) = @_ ;
1733 my $bootdisk = $conf ->{ bootdisk
};
1734 return undef if ! $bootdisk ;
1735 return undef if ! valid_drivename
( $bootdisk );
1737 return undef if ! $conf ->{ $bootdisk };
1739 my $drive = parse_drive
( $bootdisk, $conf ->{ $bootdisk });
1740 return undef if ! defined ( $drive );
1742 return undef if drive_is_cdrom
( $drive );
1744 my $volid = $drive ->{ file
};
1745 return undef if ! $volid ;
1751 if ( $volid =~ m
|^/|) {
1752 $path = $timeoutid = $volid ;
1754 $storeid = $timeoutid = PVE
:: Storage
:: parse_volume_id
( $volid );
1755 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
1758 my $last_timeout = $storage_timeout_hash ->{ $timeoutid };
1759 if ( $last_timeout ) {
1760 if (( time () - $last_timeout ) < 30 ) {
1761 # skip storage with errors
1764 delete $storage_timeout_hash ->{ $timeoutid };
1767 my ( $size, $format, $used );
1769 ( $size, $format, $used ) = PVE
:: Storage
:: file_size_info
( $path, 1 );
1771 if (! defined ( $format )) {
1773 $storage_timeout_hash ->{ $timeoutid } = time ();
1777 return wantarray ?
( $size, $used ) : $size ;
1780 my $last_proc_pid_stat ;
1783 my ( $opt_vmid ) = @_ ;
1787 my $storecfg = PVE
:: Storage
:: config
();
1789 my $list = vzlist
();
1790 my ( $uptime ) = PVE
:: ProcFSTools
:: read_proc_uptime
();
1792 foreach my $vmid ( keys %$list ) {
1793 next if $opt_vmid && ( $vmid ne $opt_vmid );
1795 my $cfspath = cfs_config_path
( $vmid );
1796 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath ) || {};
1799 $d ->{ pid
} = $list ->{ $vmid }->{ pid
};
1801 # fixme: better status?
1802 $d ->{ status
} = $list ->{ $vmid }->{ pid
} ?
'running' : 'stopped' ;
1804 my ( $size, $used ) = disksize
( $storecfg, $conf );
1805 if ( defined ( $size ) && defined ( $used )) {
1807 $d ->{ maxdisk
} = $size ;
1813 $d ->{ cpus
} = ( $conf ->{ sockets
} || 1 ) * ( $conf ->{ cores
} || 1 );
1814 $d ->{ name
} = $conf ->{ name
} || "VM $vmid " ;
1815 $d ->{ maxmem
} = $conf ->{ memory
} ?
$conf ->{ memory
}*( 1024 * 1024 ) : 0 ;
1827 $d ->{ diskwrite
} = 0 ;
1832 my $netdev = PVE
:: ProcFSTools
:: read_proc_net_dev
();
1833 foreach my $dev ( keys %$netdev ) {
1834 next if $dev !~ m/^tap([1-9]\d*)i/ ;
1836 my $d = $res ->{ $vmid };
1839 $d ->{ netout
} += $netdev ->{ $dev }->{ receive
};
1840 $d ->{ netin
} += $netdev ->{ $dev }->{ transmit
};
1843 my $cpuinfo = PVE
:: ProcFSTools
:: read_cpuinfo
();
1844 my $cpucount = $cpuinfo ->{ cpus
} || 1 ;
1845 my $ctime = gettimeofday
;
1847 foreach my $vmid ( keys %$list ) {
1849 my $d = $res ->{ $vmid };
1850 my $pid = $d ->{ pid
};
1853 if ( my $fh = IO
:: File-
> new ( "/proc/ $pid/io " , "r" )) {
1855 while ( defined ( my $line = < $fh >)) {
1856 if ( $line =~ m/^([rw]char):\s+(\d+)$/ ) {
1861 $d ->{ diskread
} = $data ->{ rchar
} || 0 ;
1862 $d ->{ diskwrite
} = $data ->{ wchar
} || 0 ;
1865 my $statstr = file_read_firstline
( "/proc/ $pid/stat " );
1868 my ( $utime, $stime, $vsize, $rss, $starttime );
1869 if ( $statstr =~ m/^$pid \(.*\) \S (-?\d+) -?\d+ -?\d+ -?\d+ -?\d+ \d+ \d+ \d+ \d+ \d+ (\d+) (\d+) (-?\d+) (-?\d+) -?\d+ -?\d+ -?\d+ 0 (\d+) (\d+) (-?\d+) \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ -?\d+ -?\d+ \d+ \d+ \d+/ ) {
1870 ( $utime, $stime, $vsize, $rss, $starttime ) = ( $2, $3, $7, $8 * 4096 , $6 );
1875 my $used = $utime + $stime ;
1877 my $vcpus = $d ->{ cpus
} > $cpucount ?
$cpucount : $d ->{ cpus
};
1879 $d ->{ uptime
} = int ( $uptime - ( $starttime/100 ));
1882 $d ->{ mem
} = int (( $rss/$vsize )* $d ->{ maxmem
});
1885 my $old = $last_proc_pid_stat ->{ $pid };
1887 $last_proc_pid_stat ->{ $pid } = {
1896 my $dtime = ( $ctime - $old ->{ time }) * $cpucount * $clock_ticks ;
1898 if ( $dtime > 1000 ) {
1899 my $dutime = $used - $old ->{ used
};
1901 $d ->{ cpu
} = $dutime/$dtime ;
1902 $d ->{ relcpu
} = ( $d ->{ cpu
} * $cpucount ) / $vcpus ;
1903 $last_proc_pid_stat ->{ $pid } = {
1907 relcpu
=> $d ->{ relcpu
},
1910 $d ->{ cpu
} = $old ->{ cpu
};
1911 $d ->{ relcpu
} = $old ->{ relcpu
};
1919 my ( $conf, $func ) = @_ ;
1921 foreach my $ds ( keys %$conf ) {
1922 next if ! valid_drivename
( $ds );
1924 my $drive = parse_drive
( $ds, $conf ->{ $ds });
1927 & $func ( $ds, $drive );
1931 sub config_to_command
{
1932 my ( $storecfg, $vmid, $conf, $defaults, $migrate_uri ) = @_ ;
1936 my $kvmver = kvm_user_version
();
1937 my $vernum = 0 ; # unknown
1938 if ( $kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/ ) {
1939 $vernum = $1*1000000+$2*1000+$3 ;
1942 die "detected old qemu-kvm binary ( $kvmver ) \n " if $vernum < 14000 ;
1944 my $have_ovz = - f
'/proc/vz/vestat' ;
1946 push @$cmd, '/usr/bin/kvm' ;
1948 push @$cmd, '-id' , $vmid ;
1952 my $socket = monitor_socket
( $vmid );
1953 push @$cmd, '-chardev' , "socket,id=monitor,path= $socket,server,nowait " ;
1954 push @$cmd, '-mon' , "chardev=monitor,mode=readline" ;
1956 $socket = vnc_socket
( $vmid );
1957 push @$cmd, '-vnc' , "unix: $socket,x509,password " ;
1959 push @$cmd, '-pidfile' , pidfile_name
( $vmid );
1961 push @$cmd, '-daemonize' ;
1963 push @$cmd, '-incoming' , $migrate_uri if $migrate_uri ;
1965 # include usb device config
1966 push @$cmd, '-readconfig' , '/usr/share/qemu-server/pve-usb.cfg' ;
1968 # enable absolute mouse coordinates (needed by vnc)
1969 my $tablet = defined ( $conf ->{ tablet
}) ?
$conf ->{ tablet
} : $defaults ->{ tablet
};
1970 push @$cmd, '-device' , 'usb-tablet,bus=ehci.0,port=6' if $tablet ;
1973 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
1974 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
1976 push @$cmd, '-device' , "pci-assign,host= $d ->{pciid},id=hostpci $i " ;
1980 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1981 my $d = parse_usb_device
( $conf ->{ "usb $i " });
1983 if ( $d ->{ vendorid
} && $d ->{ productid
}) {
1984 push @$cmd, '-device' , "usb-host,vendorid= $d ->{vendorid},productid= $d ->{productid}" ;
1985 } elsif ( defined ( $d ->{ hostbus
}) && defined ( $d ->{ hostport
})) {
1986 push @$cmd, '-device' , "usb-host,hostbus= $d ->{hostbus},hostport= $d ->{hostport}" ;
1991 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
1992 push @$cmd, '-chardev' , "tty,id=serial $i,path = $conf ->{serial $i }" ;
1993 push @$cmd, '-device' , "isa-serial,chardev=serial $i " ;
1997 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
1998 push @$cmd, '-chardev' , "parport,id=parallel $i,path = $conf ->{parallel $i }" ;
1999 push @$cmd, '-device' , "isa-parallel,chardev=parallel $i " ;
2002 my $vmname = $conf ->{ name
} || "vm $vmid " ;
2004 push @$cmd, '-name' , $vmname ;
2007 $sockets = $conf ->{ smp
} if $conf ->{ smp
}; # old style - no longer iused
2008 $sockets = $conf ->{ sockets
} if $conf ->{ sockets
};
2010 my $cores = $conf ->{ cores
} || 1 ;
2014 push @$cmd, '-smp' , "sockets= $sockets,cores = $cores " ;
2016 push @$cmd, '-cpu' , $conf ->{ cpu
} if $conf ->{ cpu
};
2018 $boot_opt = "menu=on" ;
2019 if ( $conf ->{ boot
}) {
2020 $boot_opt .= ",order= $conf ->{boot}" ;
2023 push @$cmd, '-nodefaults' ;
2025 push @$cmd, '-boot' , $boot_opt if $boot_opt ;
2027 push @$cmd, '-no-acpi' if defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 ;
2029 push @$cmd, '-no-reboot' if defined ( $conf ->{ reboot
}) && $conf ->{ reboot
} == 0 ;
2031 my $vga = $conf ->{ vga
};
2033 if ( $conf ->{ ostype
} && ( $conf ->{ ostype
} eq 'win7' || $conf ->{ ostype
} eq 'w2k8' )) {
2040 push @$cmd, '-vga' , $vga if $vga ; # for kvm 77 and later
2043 my $tdf = defined ( $conf ->{ tdf
}) ?
$conf ->{ tdf
} : $defaults ->{ tdf
};
2044 push @$cmd, '-tdf' if $tdf ;
2046 my $nokvm = defined ( $conf ->{ kvm
}) && $conf ->{ kvm
} == 0 ?
1 : 0 ;
2048 if ( my $ost = $conf ->{ ostype
}) {
2049 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2051 if ( $ost =~ m/^w/ ) { # windows
2052 push @$cmd, '-localtime' if ! defined ( $conf ->{ localtime });
2054 # use rtc-td-hack when acpi is enabled
2055 if (!( defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 )) {
2056 push @$cmd, '-rtc-td-hack' ;
2066 push @$cmd, '-no-kvm' if $nokvm ;
2068 push @$cmd, '-localtime' if $conf ->{ localtime };
2070 push @$cmd, '-startdate' , $conf ->{ startdate
} if $conf ->{ startdate
};
2072 push @$cmd, '-S' if $conf ->{ freeze
};
2074 # set keyboard layout
2075 my $kb = $conf ->{ keyboard
} || $defaults ->{ keyboard
};
2076 push @$cmd, '-k' , $kb if $kb ;
2079 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2080 #push @$cmd, '-soundhw', 'es1370';
2081 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2083 if ( $conf ->{ watchdog
}) {
2084 my $wdopts = parse_watchdog
( $conf ->{ watchdog
});
2085 push @$cmd, '-watchdog' , $wdopts ->{ model
} || 'i6300esb' ;
2086 push @$cmd, '-watchdog-action' , $wdopts ->{ action
} if $wdopts ->{ action
};
2090 my $scsicontroller = {};
2092 foreach_drive
( $conf, sub {
2093 my ( $ds, $drive ) = @_ ;
2096 PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
});
2097 push @$vollist, $drive ->{ file
};
2100 $use_virtio = 1 if $ds =~ m/^virtio/ ;
2101 if ( $drive ->{ interface
} eq 'scsi' ) {
2103 my $controller = int ( $drive ->{ index } / $maxdev );
2104 push @$cmd, '-device' , "lsi,id=scsi $controller " if ! $scsicontroller ->{ $controller };
2105 my $scsicontroller ->{ $controller }= 1 ;
2107 my $tmp = print_drive_full
( $storecfg, $vmid, $drive );
2108 $tmp .= ",boot=on" if $conf ->{ bootdisk
} && ( $conf ->{ bootdisk
} eq $ds );
2109 push @$cmd, '-drive' , $tmp ;
2110 push @$cmd, '-device' , print_drivedevice_full
( $storecfg,$vmid, $drive );
2113 push @$cmd, '-m' , $conf ->{ memory
} || $defaults ->{ memory
};
2117 foreach my $k ( sort keys %$conf ) {
2118 next if $k !~ m/^net(\d+)$/ ;
2121 die "got strange net id ' $i ' \n " if $i >= ${ MAX_NETS
};
2123 if ( $conf ->{ "net $i " } && ( my $net = parse_net
( $conf ->{ "net $i " }))) {
2127 my $ifname = "tap${vmid}i $i " ;
2129 # kvm uses TUNSETIFF ioctl, and that limits ifname length
2130 die "interface name ' $ifname ' is too long (max 15 character) \n "
2131 if length ( $ifname ) >= 16 ;
2133 my $device = $net ->{ model
};
2134 my $vhostparam = '' ;
2135 if ( $net ->{ model
} eq 'virtio' ) {
2137 $device = 'virtio-net-pci' ;
2138 $vhostparam = ',vhost=on' if $kernel_has_vhost_net ;
2141 if ( $net ->{ bridge
}) {
2142 push @$cmd, '-netdev' , "type=tap,id=${k},ifname=${ifname},script=/var/lib/qemu-server/pve-bridge $vhostparam " ;
2144 push @$cmd, '-netdev' , "type=user,id=${k},hostname= $vmname " ;
2147 # qemu > 0.15 always try to boot from network - we disable that by
2148 # not loading the pxe rom file
2149 my $extra = (! $conf ->{ boot
} || ( $conf ->{ boot
} !~ m/n/ )) ?
2151 push @$cmd, '-device' , " $device,$ {extra}mac= $net ->{macaddr},netdev=${k}" ;
2155 push @$cmd, '-net' , 'none' if ! $foundnet ;
2157 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2158 # when the VM uses virtio devices.
2159 if (! $use_virtio && $have_ovz ) {
2161 my $cpuunits = defined ( $conf ->{ cpuunits
}) ?
2162 $conf ->{ cpuunits
} : $defaults ->{ cpuunits
};
2164 push @$cmd, '-cpuunits' , $cpuunits if $cpuunits ;
2166 # fixme: cpulimit is currently ignored
2167 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2171 if ( $conf ->{ args
}) {
2172 my $aa = split_args
( $conf ->{ args
});
2176 return wantarray ?
( $cmd, $vollist ) : $cmd ;
2181 return "${var_run_tmpdir}/ $vmid .vnc" ;
2184 sub monitor_socket
{
2186 return "${var_run_tmpdir}/ $vmid .mon" ;
2191 return "${var_run_tmpdir}/ $vmid .pid" ;
2194 sub random_ether_addr
{
2196 my $rand = Digest
:: SHA1
:: sha1_hex
( rand (), time ());
2199 for ( my $i = 0 ; $i < 6 ; $i++ ) {
2200 my $ss = hex ( substr ( $rand, $i*2, 2 ));
2202 $ss &= 0xfe ; # clear multicast
2203 $ss |= 2 ; # set local id
2205 $ss = sprintf ( " %02X " , $ss );
2217 sub next_migrate_port
{
2219 for ( my $p = 60000 ; $p < 60010 ; $p++ ) {
2221 my $sock = IO
:: Socket
:: INET-
> new ( Listen
=> 5 ,
2222 LocalAddr
=> 'localhost' ,
2233 die "unable to find free migration port" ;
2237 my ( $storecfg, $vmid, $statefile, $skiplock ) = @_ ;
2239 lock_config
( $vmid, sub {
2240 my $conf = load_config
( $vmid );
2242 check_lock
( $conf ) if ! $skiplock ;
2244 if ( check_running
( $vmid )) {
2245 my $msg = "VM $vmid already running - start failed \n " ;
2246 syslog
( 'err' , $msg );
2249 syslog
( 'info' , "VM $vmid start" );
2253 my $migrate_port = 0 ;
2256 if ( $statefile eq 'tcp' ) {
2257 $migrate_port = next_migrate_port
();
2258 $migrate_uri = "tcp:localhost:${migrate_port}" ;
2260 if (- f
$statefile ) {
2261 $migrate_uri = "exec:cat $statefile " ;
2263 warn "state file ' $statefile ' does not exist - doing normal startup \n " ;
2268 my $defaults = load_defaults
();
2270 my ( $cmd, $vollist ) = config_to_command
( $storecfg, $vmid, $conf, $defaults, $migrate_uri );
2272 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
2273 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
2275 my $info = pci_device_info
( "0000: $d ->{pciid}" );
2276 die "IOMMU not present \n " if ! check_iommu_support
();
2277 die "no pci device info for device ' $d ->{pciid}' \n " if ! $info ;
2278 die "can't unbind pci device ' $d ->{pciid}' \n " if ! pci_dev_bind_to_stub
( $info );
2279 die "can't reset pci device ' $d ->{pciid}' \n " if ! pci_dev_reset
( $info );
2282 PVE
:: Storage
:: activate_volumes
( $storecfg, $vollist );
2284 eval { run_command
( $cmd, timeout
=> $migrate_uri ?
undef : 30 ); };
2289 my $msg = "start failed: $err " ;
2290 syslog
( 'err' , "VM $vmid $msg " );
2296 if ( $statefile eq 'tcp' ) {
2297 print "migration listens on port $migrate_port\n " ;
2300 # fixme: send resume - is that necessary ?
2301 eval { vm_monitor_command
( $vmid, "cont" , 1 ) };
2305 if ( my $migrate_speed =
2306 $conf ->{ migrate_speed
} || $defaults ->{ migrate_speed
}) {
2307 my $cmd = "migrate_set_speed ${migrate_speed}m" ;
2308 eval { vm_monitor_command
( $vmid, $cmd, 1 ); };
2311 if ( my $migrate_downtime =
2312 $conf ->{ migrate_downtime
} || $defaults ->{ migrate_downtime
}) {
2313 my $cmd = "migrate_set_downtime ${migrate_downtime}" ;
2314 eval { vm_monitor_command
( $vmid, $cmd, 1 ); };
2320 my ( $fh, $timeout ) = @_ ;
2322 my $sel = new IO
:: Select
;
2329 while ( scalar ( @ready = $sel -> can_read ( $timeout ))) {
2331 if ( $count = $fh -> sysread ( $buf, 8192 )) {
2332 if ( $buf =~ /^(.*)\(qemu\) $/s ) {
2339 if (! defined ( $count )) {
2346 die "monitor read timeout \n " if ! scalar ( @ready );
2351 sub vm_monitor_command
{
2352 my ( $vmid, $cmdstr, $nolog ) = @_ ;
2356 syslog
( "info" , "VM $vmid monitor command ' $cmdstr '" ) if ! $nolog ;
2359 die "VM not running \n " if ! check_running
( $vmid );
2361 my $sname = monitor_socket
( $vmid );
2363 my $sock = IO
:: Socket
:: UNIX-
> new ( Peer
=> $sname ) ||
2364 die "unable to connect to VM $vmid socket - $!\n " ;
2368 # hack: migrate sometime blocks the monitor (when migrate_downtime
2370 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2371 $timeout = 60 * 60 ; # 1 hour
2375 my $data = __read_avail
( $sock, $timeout );
2377 if ( $data !~ m/^QEMU\s+(\S+)\s+monitor\s/ ) {
2378 die "got unexpected qemu monitor banner \n " ;
2381 my $sel = new IO
:: Select
;
2384 if (! scalar ( my @ready = $sel -> can_write ( $timeout ))) {
2385 die "monitor write error - timeout" ;
2388 my $fullcmd = " $cmdstr\r " ;
2391 if (!( $b = $sock -> syswrite ( $fullcmd )) || ( $b != length ( $fullcmd ))) {
2392 die "monitor write error - $! " ;
2395 return if ( $cmdstr eq 'q' ) || ( $cmdstr eq 'quit' );
2399 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2400 $timeout = 60 * 60 ; # 1 hour
2401 } elsif ( $cmdstr =~ m/^(eject|change)/ ) {
2402 $timeout = 60 ; # note: cdrom mount command is slow
2404 if ( $res = __read_avail
( $sock, $timeout )) {
2406 my @lines = split ( " \r ? \n " , $res );
2408 shift @lines if $lines [ 0 ] !~ m/^unknown command/ ; # skip echo
2410 $res = join ( " \n " , @lines );
2418 syslog
( "err" , "VM $vmid monitor command failed - $err " );
2425 sub vm_commandline
{
2426 my ( $storecfg, $vmid ) = @_ ;
2428 my $conf = load_config
( $vmid );
2430 my $defaults = load_defaults
();
2432 my $cmd = config_to_command
( $storecfg, $vmid, $conf, $defaults );
2434 return join ( ' ' , @$cmd );
2438 my ( $vmid, $skiplock ) = @_ ;
2440 lock_config
( $vmid, sub {
2442 my $conf = load_config
( $vmid );
2444 check_lock
( $conf ) if ! $skiplock ;
2446 syslog
( "info" , "VM $vmid sending 'reset'" );
2448 vm_monitor_command
( $vmid, "system_reset" , 1 );
2453 my ( $vmid, $skiplock ) = @_ ;
2455 lock_config
( $vmid, sub {
2457 my $conf = load_config
( $vmid );
2459 check_lock
( $conf ) if ! $skiplock ;
2461 syslog
( "info" , "VM $vmid sending 'shutdown'" );
2463 vm_monitor_command
( $vmid, "system_powerdown" , 1 );
2468 my ( $vmid, $skiplock ) = @_ ;
2470 lock_config
( $vmid, sub {
2472 my $pid = check_running
( $vmid );
2475 syslog
( 'info' , "VM $vmid already stopped" );
2479 my $conf = load_config
( $vmid );
2481 check_lock
( $conf ) if ! $skiplock ;
2483 syslog
( "info" , "VM $vmid stopping" );
2485 eval { vm_monitor_command
( $vmid, "quit" , 1 ); };
2491 my $timeout = 50 ; # fixme: how long?
2494 while (( $count < $timeout ) && check_running
( $vmid )) {
2499 if ( $count >= $timeout ) {
2500 syslog
( 'info' , "VM $vmid still running - terminating now with SIGTERM" );
2504 syslog
( 'info' , "VM $vmid quit failed - terminating now with SIGTERM" );
2512 while (( $count < $timeout ) && check_running
( $vmid )) {
2517 if ( $count >= $timeout ) {
2518 syslog
( 'info' , "VM $vmid still running - terminating now with SIGKILL \n " );
2522 fairsched_rmnod
( $vmid ); # try to destroy group
2527 my ( $vmid, $skiplock ) = @_ ;
2529 lock_config
( $vmid, sub {
2531 my $conf = load_config
( $vmid );
2533 check_lock
( $conf ) if ! $skiplock ;
2535 syslog
( "info" , "VM $vmid suspend" );
2537 vm_monitor_command
( $vmid, "stop" , 1 );
2542 my ( $vmid, $skiplock ) = @_ ;
2544 lock_config
( $vmid, sub {
2546 my $conf = load_config
( $vmid );
2548 check_lock
( $conf ) if ! $skiplock ;
2550 syslog
( "info" , "VM $vmid resume" );
2552 vm_monitor_command
( $vmid, "cont" , 1 );
2557 my ( $vmid, $skiplock ) = @_ ;
2559 lock_config
( $vmid, sub {
2561 my $conf = load_config
( $vmid );
2563 check_lock
( $conf ) if ! $skiplock ;
2565 syslog
( "info" , "VM $vmid sending cntl-alt-delete" );
2567 vm_monitor_command
( $vmid, "sendkey ctrl-alt-delete" , 1 );
2572 my ( $storecfg, $vmid, $skiplock ) = @_ ;
2574 lock_config
( $vmid, sub {
2576 my $conf = load_config
( $vmid );
2578 check_lock
( $conf ) if ! $skiplock ;
2580 syslog
( "info" , "VM $vmid destroy called (removing all data)" );
2583 if (! check_running
( $vmid )) {
2584 fairsched_rmnod
( $vmid ); # try to destroy group
2585 destroy_vm
( $storecfg, $vmid );
2587 die "VM is running \n " ;
2594 syslog
( "err" , "VM $vmid destroy failed - $err " );
2603 $timeout = 3 * 60 if ! $timeout ;
2605 my $vzlist = vzlist
();
2607 foreach my $vmid ( keys %$vzlist ) {
2608 next if ! $vzlist ->{ $vmid }->{ pid
};
2614 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs \n " ;
2615 syslog
( 'info' , $msg );
2618 foreach my $vmid ( keys %$vzlist ) {
2619 next if ! $vzlist ->{ $vmid }->{ pid
};
2620 eval { vm_shutdown
( $vmid, 1 ); };
2621 print STDERR
$@ if $@ ;
2625 my $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2627 while (( $try < $maxtries ) && $count ) {
2633 foreach my $vmid ( keys %$vzlist ) {
2634 next if ! $vzlist ->{ $vmid }->{ pid
};
2642 foreach my $vmid ( keys %$vzlist ) {
2643 next if ! $vzlist ->{ $vmid }->{ pid
};
2645 $msg = "VM $vmid still running - sending stop now \n " ;
2646 syslog
( 'info' , $msg );
2649 eval { vm_monitor_command
( $vmid, "quit" , 1 ); };
2650 print STDERR
$@ if $@ ;
2655 $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2657 while (( $try < $maxtries ) && $count ) {
2663 foreach my $vmid ( keys %$vzlist ) {
2664 next if ! $vzlist ->{ $vmid }->{ pid
};
2672 foreach my $vmid ( keys %$vzlist ) {
2673 next if ! $vzlist ->{ $vmid }->{ pid
};
2675 $msg = "VM $vmid still running - terminating now with SIGTERM \n " ;
2676 syslog
( 'info' , $msg );
2678 kill 15 , $vzlist ->{ $vmid }->{ pid
};
2681 # this is called by system shotdown scripts, so remaining
2682 # processes gets killed anyways (no need to send kill -9 here)
2684 $msg = "Qemu Server stopped \n " ;
2685 syslog
( 'info' , $msg );
2693 my ( $filename, $buf ) = @_ ;
2695 my $fh = IO
:: File-
> new ( $filename, "w" );
2696 return undef if ! $fh ;
2698 my $res = print $fh $buf ;
2705 sub pci_device_info
{
2710 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/ ;
2711 my ( $domain, $bus, $slot, $func ) = ( $1, $2, $3, $4 );
2713 my $irq = file_read_firstline
( " $pcisysfs/devices/$name/irq " );
2714 return undef if ! defined ( $irq ) || $irq !~ m/^\d+$/ ;
2716 my $vendor = file_read_firstline
( " $pcisysfs/devices/$name/vendor " );
2717 return undef if ! defined ( $vendor ) || $vendor !~ s/^0x// ;
2719 my $product = file_read_firstline
( " $pcisysfs/devices/$name/device " );
2720 return undef if ! defined ( $product ) || $product !~ s/^0x// ;
2725 product
=> $product,
2731 has_fl_reset
=> - f
" $pcisysfs/devices/$name/reset " || 0 ,
2740 my $name = $dev ->{ name
};
2742 my $fn = " $pcisysfs/devices/$name/reset " ;
2744 return file_write
( $fn, "1" );
2747 sub pci_dev_bind_to_stub
{
2750 my $name = $dev ->{ name
};
2752 my $testdir = " $pcisysfs/drivers/pci -stub/ $name " ;
2753 return 1 if - d
$testdir ;
2755 my $data = " $dev ->{vendor} $dev ->{product}" ;
2756 return undef if ! file_write
( " $pcisysfs/drivers/pci -stub/new_id" , $data );
2758 my $fn = " $pcisysfs/devices/$name/driver/unbind " ;
2759 if (! file_write
( $fn, $name )) {
2760 return undef if - f
$fn ;
2763 $fn = " $pcisysfs/drivers/pci -stub/bind" ;
2764 if (! - d
$testdir ) {
2765 return undef if ! file_write
( $fn, $name );