]>
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 $cpuinfo = PVE
:: ProcFSTools
:: read_cpuinfo
();
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 PVE
:: JSONSchema
:: register_standard_option
( 'skiplock' , {
41 description
=> "Ignore locks - only root is allowed to use this option." ,
46 PVE
:: JSONSchema
:: register_standard_option
( 'pve-qm-stateuri' , {
47 description
=> "Some command save/restore state from this location." ,
53 #no warnings 'redefine';
55 unless ( 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
);
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
);
78 die ( "no fairsched syscall for this arch" );
80 require 'asm/ioctl.ph' ;
81 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined (& KVM_GET_API_VERSION
);
85 my ( $parent, $weight, $desired ) = @_ ;
87 return syscall (& __NR_fairsched_mknod
, int ( $parent ), int ( $weight ), int ( $desired ));
93 return syscall (& __NR_fairsched_rmnod
, int ( $id ));
97 my ( $pid, $newid ) = @_ ;
99 return syscall (& __NR_fairsched_mvpr
, int ( $pid ), int ( $newid ));
102 sub fairsched_vcpus
{
103 my ( $id, $vcpus ) = @_ ;
105 return syscall (& __NR_fairsched_vcpus
, int ( $id ), int ( $vcpus ));
109 my ( $id, $op, $rate ) = @_ ;
111 return syscall (& __NR_fairsched_rate
, int ( $id ), int ( $op ), int ( $rate ));
114 use constant FAIRSCHED_SET_RATE
=> 0 ;
115 use constant FAIRSCHED_DROP_RATE
=> 1 ;
116 use constant FAIRSCHED_GET_RATE
=> 2 ;
118 sub fairsched_cpulimit
{
119 my ( $id, $limit ) = @_ ;
121 my $cpulim1024 = int ( $limit * 1024 / 100 );
122 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
124 return fairsched_rate
( $id, $op, $cpulim1024 );
127 my $nodename = PVE
:: INotify
:: nodename
();
129 mkdir "/etc/pve/nodes/ $nodename " ;
130 my $confdir = "/etc/pve/nodes/ $nodename/qemu -server" ;
133 my $var_run_tmpdir = "/var/run/qemu-server" ;
134 mkdir $var_run_tmpdir ;
136 my $lock_dir = "/var/lock/qemu-server" ;
139 my $pcisysfs = "/sys/bus/pci" ;
141 my $keymaphash = PVE
:: Tools
:: kvmkeymaps
();
147 description
=> "Specifies whether a VM will be started during system bootup." ,
153 description
=> "Automatic restart after crash (currently ignored)." ,
159 description
=> "Allow reboot. If set to '0' the VM exit on reboot." ,
165 description
=> "Lock/unlock the VM." ,
166 enum
=> [ qw(migrate backup) ],
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\n NOTE: This option is currently ignored." ,
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\n NOTE: You can disable fair-scheduler configuration by setting this to 0." ,
186 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device." ,
193 description
=> "Amount of target RAM for the VM in MB." ,
199 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file." ,
200 enum
=> [ keys %$keymaphash ],
206 description
=> "Set a name for the VM. Only used on the configuration web interface." ,
211 description
=> "Description for the VM. Only used on the configuration web interface." ,
216 enum
=> [ qw(other wxp w2k w2k3 w2k8 wvista win7 l24 l26) ],
217 description
=> <<EODESC,
218 Used to enable special optimization/features for specific
221 other => unspecified OS
222 wxp => Microsoft Windows XP
223 w2k => Microsoft Windows 2000
224 w2k3 => Microsoft Windows 2003
225 w2k8 => Microsoft Windows 2008
226 wvista => Microsoft Windows Vista
227 win7 => Microsoft Windows 7
228 l24 => Linux 2.4 Kernel
229 l26 => Linux 2.6/3.X Kernel
231 other|l24|l26 ... no special behaviour
232 wxp|w2k|w2k3|w2k8|wvista|win7 ... use --localtime switch
238 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)." ,
239 pattern
=> '[acdn]{1,4}' ,
244 type
=> 'string' , format
=> 'pve-qm-bootdisk' ,
245 description
=> "Enable booting from specified disk." ,
246 pattern
=> '(ide|scsi|virtio)\d+' ,
251 description
=> "The number of CPUs. Please use option -sockets instead." ,
258 description
=> "The number of CPU sockets." ,
265 description
=> "The number of cores per socket." ,
272 description
=> "Enable/disable ACPI." ,
278 description
=> "Enable/disable KVM hardware virtualization." ,
284 description
=> "Enable/disable time drift fix." ,
290 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS." ,
295 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution)." ,
300 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" ,
301 enum
=> [ qw(std cirrus vmware) ],
305 type
=> 'string' , format
=> 'pve-qm-watchdog' ,
306 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]' ,
307 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)" ,
312 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)" ,
313 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'." ,
314 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)' ,
320 description
=> <<EODESCR,
321 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
323 args: -no-reboot -no-hpet
330 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning. Else the mouse runs out of sync with normal vnc clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches." ,
335 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit." ,
339 migrate_downtime
=> {
342 description
=> "Set maximum tolerated downtime (in seconds) for migrations." ,
348 type
=> 'string' , format
=> 'pve-qm-drive' ,
349 typetext
=> 'volume' ,
350 description
=> "This is an alias for option -ide2" ,
354 description
=> "Emulated CPU type." ,
356 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom host) ],
361 # what about other qemu settings ?
363 #machine => 'string',
376 ##soundhw => 'string',
378 while ( my ( $k, $v ) = each %$confdesc ) {
379 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm- $k " , $v );
382 my $MAX_IDE_DISKS = 4 ;
383 my $MAX_SCSI_DISKS = 14 ;
384 my $MAX_VIRTIO_DISKS = 6 ;
385 my $MAX_USB_DEVICES = 5 ;
387 my $MAX_UNUSED_DISKS = 8 ;
388 my $MAX_HOSTPCI_DEVICES = 2 ;
389 my $MAX_SERIAL_PORTS = 4 ;
390 my $MAX_PARALLEL_PORTS = 3 ;
392 my $nic_model_list = [ 'rtl8139' , 'ne2k_pci' , 'e1000' , 'pcnet' , 'virtio' ,
393 'ne2k_isa' , 'i82551' , 'i82557b' , 'i82559er' ];
394 my $nic_model_list_txt = join ( ' ' , sort @$nic_model_list );
399 type
=> 'string' , format
=> 'pve-qm-net' ,
400 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>]" ,
401 description
=> <<EODESCR,
402 Specify network devices.
404 MODEL is one of: $nic_model_list_txt
406 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
407 automatically generated if not specified.
409 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
411 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'.
413 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
419 The DHCP server assign addresses to the guest starting from 10.0.2.15.
423 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-net" , $netdesc );
425 for ( my $i = 0 ; $i < $MAX_NETS ; $i++ ) {
426 $confdesc ->{ "net $i " } = $netdesc ;
433 type
=> 'string' , format
=> 'pve-qm-drive' ,
434 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]' ,
435 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to 3)." ,
437 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-ide" , $idedesc );
441 type
=> 'string' , format
=> 'pve-qm-drive' ,
442 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]' ,
443 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13)." ,
445 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-scsi" , $scsidesc );
449 type
=> 'string' , format
=> 'pve-qm-drive' ,
450 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]' ,
451 description
=> "Use volume as VIRTIO hard disk (n is 0 to 5)." ,
453 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-virtio" , $virtiodesc );
457 type
=> 'string' , format
=> 'pve-qm-usb-device' ,
458 typetext
=> 'host=HOSTUSBDEVICE' ,
459 description
=> <<EODESCR,
460 Configure an USB device (n is 0 to 4). This can be used to
461 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
463 'bus-port(.port)*' (decimal numbers) or
464 'vendor_id:product_id' (hexadeciaml numbers)
466 You can use the 'lsusb -t' command to list existing usb devices.
468 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
472 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-usb" , $usbdesc );
476 type
=> 'string' , format
=> 'pve-qm-hostpci' ,
477 typetext
=> "HOSTPCIDEVICE" ,
478 description
=> <<EODESCR,
479 Map host pci devices. HOSTPCIDEVICE syntax is:
481 'bus:dev.func' (hexadecimal numbers)
483 You can us the 'lspci' command to list existing pci devices.
485 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
487 Experimental: user reported problems with this option.
490 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-hostpci" , $hostpcidesc );
495 pattern
=> '/dev/ttyS\d+' ,
496 description
=> <<EODESCR,
497 Map host serial devices (n is 0 to 3).
499 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
501 Experimental: user reported problems with this option.
508 pattern
=> '/dev/parport\d+' ,
509 description
=> <<EODESCR,
510 Map host parallel devices (n is 0 to 2).
512 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
514 Experimental: user reported problems with this option.
518 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
519 $confdesc ->{ "parallel $i " } = $paralleldesc ;
522 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
523 $confdesc ->{ "serial $i " } = $serialdesc ;
526 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
527 $confdesc ->{ "hostpci $i " } = $hostpcidesc ;
530 for ( my $i = 0 ; $i < $MAX_IDE_DISKS ; $i++ ) {
531 $drivename_hash ->{ "ide $i " } = 1 ;
532 $confdesc ->{ "ide $i " } = $idedesc ;
535 for ( my $i = 0 ; $i < $MAX_SCSI_DISKS ; $i++ ) {
536 $drivename_hash ->{ "scsi $i " } = 1 ;
537 $confdesc ->{ "scsi $i " } = $scsidesc ;
540 for ( my $i = 0 ; $i < $MAX_VIRTIO_DISKS ; $i++ ) {
541 $drivename_hash ->{ "virtio $i " } = 1 ;
542 $confdesc ->{ "virtio $i " } = $virtiodesc ;
545 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
546 $confdesc ->{ "usb $i " } = $usbdesc ;
551 type
=> 'string' , format
=> 'pve-volume-id' ,
552 description
=> "Reference to unused volumes." ,
555 for ( my $i = 0 ; $i < $MAX_UNUSED_DISKS ; $i++ ) {
556 $confdesc ->{ "unused $i " } = $unuseddesc ;
559 my $kvm_api_version = 0 ;
563 return $kvm_api_version if $kvm_api_version ;
565 my $fh = IO
:: File-
> new ( "</dev/kvm" ) ||
568 if ( my $v = $fh -> ioctl ( KVM_GET_API_VERSION
(), 0 )) {
569 $kvm_api_version = $v ;
574 return $kvm_api_version ;
577 my $kvm_user_version ;
579 sub kvm_user_version
{
581 return $kvm_user_version if $kvm_user_version ;
583 $kvm_user_version = 'unknown' ;
585 my $tmp = `kvm -help 2>/dev/null` ;
587 if ( $tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+\.\d+) / ) {
588 $kvm_user_version = $2 ;
591 return $kvm_user_version ;
595 my $kernel_has_vhost_net = - c
'/dev/vhost-net' ;
598 # order is important - used to autoselect boot disk
599 return (( map { "ide $_ " } ( 0 .. ( $MAX_IDE_DISKS - 1 ))),
600 ( map { "scsi $_ " } ( 0 .. ( $MAX_SCSI_DISKS - 1 ))),
601 ( map { "virtio $_ " } ( 0 .. ( $MAX_VIRTIO_DISKS - 1 ))));
604 sub valid_drivename
{
607 return defined ( $drivename_hash ->{ $dev });
612 return defined ( $confdesc ->{ $key });
616 return $nic_model_list ;
619 sub os_list_description
{
624 w2k
=> 'Windows 2000' ,
625 w2k3
=>, 'Windows 2003' ,
626 w2k8
=> 'Windows 2008' ,
627 wvista
=> 'Windows Vista' ,
634 # a clumsy way to split an argument string into an array,
635 # we simply pass it to the cli (exec call)
636 # fixme: use Text::ParseWords::shellwords() ?
642 return $args if ! $str ;
644 my $cmd = 'perl -e \' foreach my $a ( @ARGV ) { print " $a\n "; } \' -- ' . $str ;
647 run_command
( $cmd, outfunc
=> sub {
655 die "unable to parse args: $str\n " if $err ;
660 sub disk_devive_info
{
663 die "unknown disk device format ' $dev '" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/ ;
671 } elsif ( $bus eq 'scsi' ) {
675 my $controller = int ( $index / $maxdev );
676 my $unit = $index % $maxdev ;
679 return { bus
=> $bus, desc
=> uc ( $bus ) . " $controller : $unit " ,
680 controller
=> $controller, unit
=> $unit, index => $index };
684 sub qemu_drive_name
{
685 my ( $dev, $media ) = @_ ;
687 my $info = disk_devive_info
( $dev );
690 if (( $info ->{ bus
} eq 'ide' ) || ( $info ->{ bus
} eq 'scsi' )) {
691 $mediastr = ( $media eq 'cdrom' ) ?
"-cd" : "-hd" ;
692 return sprintf ( " %s%i%s%i " , $info ->{ bus
}, $info ->{ controller
},
693 $mediastr, $info ->{ unit
});
695 return sprintf ( " %s%i " , $info ->{ bus
}, $info ->{ index });
703 return $cdrom_path if $cdrom_path ;
705 return $cdrom_path = "/dev/cdrom" if - l
"/dev/cdrom" ;
706 return $cdrom_path = "/dev/cdrom1" if - l
"/dev/cdrom1" ;
707 return $cdrom_path = "/dev/cdrom2" if - l
"/dev/cdrom2" ;
711 my ( $storecfg, $vmid, $cdrom ) = @_ ;
713 if ( $cdrom eq 'cdrom' ) {
714 return get_cdrom_path
();
715 } elsif ( $cdrom eq 'none' ) {
717 } elsif ( $cdrom =~ m
|^/|) {
720 return PVE
:: Storage
:: path
( $storecfg, $cdrom );
724 # try to convert old style file names to volume IDs
725 sub filename_to_volume_id
{
726 my ( $vmid, $file, $media ) = @_ ;
728 if (!( $file eq 'none' || $file eq 'cdrom' ||
729 $file =~ m
|^ /dev/ .+| || $file =~ m/^([^:]+):(.+)$/ )) {
731 return undef if $file =~ m
|/|;
733 if ( $media && $media eq 'cdrom' ) {
734 $file = "local:iso/ $file " ;
736 $file = "local: $vmid/$file " ;
743 sub verify_media_type
{
744 my ( $opt, $vtype, $media ) = @_ ;
749 if ( $media eq 'disk' ) {
751 } elsif ( $media eq 'cdrom' ) {
754 die "internal error" ;
757 return if ( $vtype eq $etype );
759 raise_param_exc
({ $opt => "unexpected media type ( $vtype != $etype )" });
762 sub cleanup_drive_path
{
763 my ( $opt, $storecfg, $drive ) = @_ ;
765 # try to convert filesystem paths to volume IDs
767 if (( $drive ->{ file
} !~ m/^(cdrom|none)$/ ) &&
768 ( $drive ->{ file
} !~ m
|^ /dev/ .+|) &&
769 ( $drive ->{ file
} !~ m/^([^:]+):(.+)$/ ) &&
770 ( $drive ->{ file
} !~ m/^\d+$/ )) {
771 my ( $vtype, $volid ) = PVE
:: Storage
:: path_to_volume_id
( $storecfg, $drive ->{ file
});
772 raise_param_exc
({ $opt => "unable to associate path ' $drive ->{file}' to any storage" }) if ! $vtype ;
773 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $vtype eq 'iso' ;
774 verify_media_type
( $opt, $vtype, $drive ->{ media
});
775 $drive ->{ file
} = $volid ;
778 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $drive ->{ file
} =~ m/^(cdrom|none)$/ ;
781 sub create_conf_nolock
{
782 my ( $vmid, $settings ) = @_ ;
784 my $filename = config_file
( $vmid );
786 die "configuration file ' $filename ' already exists \n " if - f
$filename ;
788 my $defaults = load_defaults
();
790 $settings ->{ name
} = "vm $vmid " if ! $settings ->{ name
};
791 $settings ->{ memory
} = $defaults ->{ memory
} if ! $settings ->{ memory
};
794 foreach my $opt ( keys %$settings ) {
795 next if ! $confdesc ->{ $opt };
797 my $value = $settings ->{ $opt };
800 $data .= " $opt : $value\n " ;
803 PVE
:: Tools
:: file_set_contents
( $filename, $data );
806 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
807 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
808 # [,aio=native|threads]
811 my ( $key, $data ) = @_ ;
815 # $key may be undefined - used to verify JSON parameters
816 if (! defined ( $key )) {
817 $res ->{ interface
} = 'unknown' ; # should not harm when used to verify parameters
819 } elsif ( $key =~ m/^([^\d]+)(\d+)$/ ) {
820 $res ->{ interface
} = $1 ;
826 foreach my $p ( split ( /,/ , $data )) {
827 next if $p =~ m/^\s*$/ ;
829 if ( $p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio)=(.+)$/ ) {
830 my ( $k, $v ) = ( $1, $2 );
832 $k = 'file' if $k eq 'volume' ;
834 return undef if defined $res ->{ $k };
838 if (! $res ->{ file
} && $p !~ m/=/ ) {
846 return undef if ! $res ->{ file
};
848 return undef if $res ->{ cache
} &&
849 $res ->{ cache
} !~ m/^(off|none|writethrough|writeback)$/ ;
850 return undef if $res ->{ snapshot
} && $res ->{ snapshot
} !~ m/^(on|off)$/ ;
851 return undef if $res ->{ cyls
} && $res ->{ cyls
} !~ m/^\d+$/ ;
852 return undef if $res ->{ heads
} && $res ->{ heads
} !~ m/^\d+$/ ;
853 return undef if $res ->{ secs
} && $res ->{ secs
} !~ m/^\d+$/ ;
854 return undef if $res ->{ media
} && $res ->{ media
} !~ m/^(disk|cdrom)$/ ;
855 return undef if $res ->{ trans
} && $res ->{ trans
} !~ m/^(none|lba|auto)$/ ;
856 return undef if $res ->{ format
} && $res ->{ format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/ ;
857 return undef if $res ->{ rerror
} && $res ->{ rerror
} !~ m/^(ignore|report|stop)$/ ;
858 return undef if $res ->{ werror
} && $res ->{ werror
} !~ m/^(enospc|ignore|report|stop)$/ ;
859 return undef if $res ->{ backup
} && $res ->{ backup
} !~ m/^(yes|no)$/ ;
860 return undef if $res ->{ aio
} && $res ->{ aio
} !~ m/^(native|threads)$/ ;
862 if ( $res ->{ media
} && ( $res ->{ media
} eq 'cdrom' )) {
863 return undef if $res ->{ snapshot
} || $res ->{ trans
} || $res ->{ format
};
864 return undef if $res ->{ heads
} || $res ->{ secs
} || $res ->{ cyls
};
865 return undef if $res ->{ interface
} eq 'virtio' ;
868 # rerror does not work with scsi drives
869 if ( $res ->{ rerror
}) {
870 return undef if $res ->{ interface
} eq 'scsi' ;
876 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio) ;
879 my ( $vmid, $drive ) = @_ ;
882 foreach my $o ( @qemu_drive_options, 'backup' ) {
883 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
886 return " $drive ->{file} $opts " ;
889 sub print_drivedevice_full
{
890 my ( $storecfg, $vmid, $drive ) = @_ ;
895 if ( $drive ->{ interface
} eq 'virtio' ) {
896 my $pciaddr = print_pci_addr
( " $drive ->{interface} $drive ->{index}" );
897 $device = "virtio-blk-pci,drive=drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index} $pciaddr " ;
900 elsif ( $drive ->{ interface
} eq 'scsi' ) {
903 my $controller = int ( $drive ->{ index } / $maxdev );
904 my $unit = $drive ->{ index } % $maxdev ;
906 $device = "scsi-disk,bus=scsi $controller .0,scsi-id= $unit,drive =drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index}" ;
909 elsif ( $drive ->{ interface
} eq 'ide' ){
912 my $controller = int ( $drive ->{ index } / $maxdev );
913 my $unit = $drive ->{ index } % $maxdev ;
915 $device = "ide-drive,bus=ide. $controller,unit = $unit,drive =drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index}" ;
918 if ( $drive ->{ interface
} eq 'usb' ){
919 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
925 sub print_drive_full
{
926 my ( $storecfg, $vmid, $drive ) = @_ ;
929 foreach my $o ( @qemu_drive_options ) {
930 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
933 # use linux-aio by default (qemu default is threads)
934 $opts .= ",aio=native" if ! $drive ->{ aio
};
937 my $volid = $drive ->{ file
};
938 if ( drive_is_cdrom
( $drive )) {
939 $path = get_iso_path
( $storecfg, $vmid, $volid );
941 if ( $volid =~ m
|^/|) {
944 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
948 my $pathinfo = $path ?
"file= $path, " : '' ;
950 return "${pathinfo}if=none,id=drive- $drive ->{interface} $drive ->{index} $opts " ;
957 return $drive && $drive ->{ media
} && ( $drive ->{ media
} eq 'cdrom' );
964 return undef if ! $value ;
968 if ( $value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/ ) {
969 $res ->{ pciid
} = $value ;
977 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
983 foreach my $kvp ( split ( /,/ , $data )) {
985 if ( $kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i ) {
987 my $mac = uc ( $3 ) || random_ether_addr
();
988 $res ->{ model
} = $model ;
989 $res ->{ macaddr
} = $mac ;
990 } elsif ( $kvp =~ m/^bridge=(\S+)$/ ) {
992 } elsif ( $kvp =~ m/^rate=(\d+(\.\d+)?)$/ ) {
1000 return undef if ! $res ->{ model
};
1008 my $res = " $net ->{model}" ;
1009 $res .= "= $net ->{macaddr}" if $net ->{ macaddr
};
1010 $res .= ",bridge= $net ->{bridge}" if $net ->{ bridge
};
1011 $res .= ",rate= $net ->{rate}" if $net ->{ rate
};
1016 sub add_random_macs
{
1017 my ( $settings ) = @_ ;
1019 foreach my $opt ( keys %$settings ) {
1020 next if $opt !~ m/^net(\d+)$/ ;
1021 my $net = parse_net
( $settings ->{ $opt });
1023 $settings ->{ $opt } = print_net
( $net );
1027 sub add_unused_volume
{
1028 my ( $config, $res, $volid ) = @_ ;
1031 for ( my $ind = $MAX_UNUSED_DISKS - 1 ; $ind >= 0 ; $ind --) {
1032 my $test = "unused $ind " ;
1033 if ( my $vid = $config ->{ $test }) {
1034 return if $vid eq $volid ; # do not add duplicates
1040 die "To many unused volume - please delete them first. \n " if ! $key ;
1042 $res ->{ $key } = $volid ;
1045 # fixme: remove all thos $noerr parameters?
1047 PVE
:: JSONSchema
:: register_format
( 'pve-qm-bootdisk' , \
& verify_bootdisk
);
1048 sub verify_bootdisk
{
1049 my ( $value, $noerr ) = @_ ;
1051 return $value if valid_drivename
( $value );
1053 return undef if $noerr ;
1055 die "invalid boot disk ' $value ' \n " ;
1058 PVE
:: JSONSchema
:: register_format
( 'pve-qm-net' , \
& verify_net
);
1060 my ( $value, $noerr ) = @_ ;
1062 return $value if parse_net
( $value );
1064 return undef if $noerr ;
1066 die "unable to parse network options \n " ;
1069 PVE
:: JSONSchema
:: register_format
( 'pve-qm-drive' , \
& verify_drive
);
1071 my ( $value, $noerr ) = @_ ;
1073 return $value if parse_drive
( undef , $value );
1075 return undef if $noerr ;
1077 die "unable to parse drive options \n " ;
1080 PVE
:: JSONSchema
:: register_format
( 'pve-qm-hostpci' , \
& verify_hostpci
);
1081 sub verify_hostpci
{
1082 my ( $value, $noerr ) = @_ ;
1084 return $value if parse_hostpci
( $value );
1086 return undef if $noerr ;
1088 die "unable to parse pci id \n " ;
1091 PVE
:: JSONSchema
:: register_format
( 'pve-qm-watchdog' , \
& verify_watchdog
);
1092 sub verify_watchdog
{
1093 my ( $value, $noerr ) = @_ ;
1095 return $value if parse_watchdog
( $value );
1097 return undef if $noerr ;
1099 die "unable to parse watchdog options \n " ;
1102 sub parse_watchdog
{
1105 return undef if ! $value ;
1109 foreach my $p ( split ( /,/ , $value )) {
1110 next if $p =~ m/^\s*$/ ;
1112 if ( $p =~ m/^(model=)?(i6300esb|ib700)$/ ) {
1114 } elsif ( $p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/ ) {
1115 $res ->{ action
} = $2 ;
1124 sub parse_usb_device
{
1127 return undef if ! $value ;
1129 my @dl = split ( /,/ , $value );
1133 foreach my $v ( @dl ) {
1134 if ( $v =~ m/^host=([0-9A-Fa-f]{4}):([0-9A-Fa-f]{4})$/ ) {
1136 $res ->{ vendorid
} = $1 ;
1137 $res ->{ productid
} = $2 ;
1138 } elsif ( $v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/ ) {
1140 $res ->{ hostbus
} = $1 ;
1141 $res ->{ hostport
} = $2 ;
1146 return undef if ! $found ;
1151 PVE
:: JSONSchema
:: register_format
( 'pve-qm-usb-device' , \
& verify_usb_device
);
1152 sub verify_usb_device
{
1153 my ( $value, $noerr ) = @_ ;
1155 return $value if parse_usb_device
( $value );
1157 return undef if $noerr ;
1159 die "unable to parse usb device \n " ;
1162 # add JSON properties for create and set function
1163 sub json_config_properties
{
1166 foreach my $opt ( keys %$confdesc ) {
1167 $prop ->{ $opt } = $confdesc ->{ $opt };
1174 my ( $key, $value ) = @_ ;
1176 die "unknown setting ' $key ' \n " if ! $confdesc ->{ $key };
1178 my $type = $confdesc ->{ $key }->{ type
};
1180 if (! defined ( $value )) {
1181 die "got undefined value \n " ;
1184 if ( $value =~ m/[\n\r]/ ) {
1185 die "property contains a line feed \n " ;
1188 if ( $type eq 'boolean' ) {
1189 return 1 if ( $value eq '1' ) || ( $value =~ m/^(on|yes|true)$/i );
1190 return 0 if ( $value eq '0' ) || ( $value =~ m/^(off|no|false)$/i );
1191 die "type check ('boolean') failed - got ' $value ' \n " ;
1192 } elsif ( $type eq 'integer' ) {
1193 return int ( $1 ) if $value =~ m/^(\d+)$/ ;
1194 die "type check ('integer') failed - got ' $value ' \n " ;
1195 } elsif ( $type eq 'string' ) {
1196 if ( my $fmt = $confdesc ->{ $key }->{ format
}) {
1197 if ( $fmt eq 'pve-qm-drive' ) {
1198 # special case - we need to pass $key to parse_drive()
1199 my $drive = parse_drive
( $key, $value );
1200 return $value if $drive ;
1201 die "unable to parse drive options \n " ;
1203 PVE
:: JSONSchema
:: check_format
( $fmt, $value );
1206 $value =~ s/^\"(.*)\"$/$1/ ;
1209 die "internal error"
1214 my ( $vmid, $code, @param ) = @_ ;
1216 my $filename = config_file_lock
( $vmid );
1218 lock_file
( $filename, 10 , $code, @param );
1223 sub cfs_config_path
{
1224 my ( $vmid, $node ) = @_ ;
1226 $node = $nodename if ! $node ;
1227 return "nodes/ $node/qemu -server/ $vmid .conf" ;
1230 sub check_iommu_support
{
1231 #fixme : need to check IOMMU support
1232 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1240 my ( $vmid, $node ) = @_ ;
1242 my $cfspath = cfs_config_path
( $vmid, $node );
1243 return "/etc/pve/ $cfspath " ;
1246 sub config_file_lock
{
1249 return " $lock_dir/lock - $vmid .conf" ;
1255 my $conf = config_file
( $vmid );
1256 utime undef , undef , $conf ;
1260 my ( $storecfg, $vmid, $settings ) = @_ ;
1265 foreach_drive
( $settings, sub {
1266 my ( $ds, $disk ) = @_ ;
1268 return if drive_is_cdrom
( $disk );
1270 my $file = $disk ->{ file
};
1272 if ( $file =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/ ) {
1273 my $storeid = $2 || 'local' ;
1275 my $defformat = PVE
:: Storage
:: storage_default_format
( $storecfg, $storeid );
1276 my $fmt = $disk ->{ format
} || $defformat ;
1277 syslog
( 'info' , "VM $vmid creating new disk - size is $size GB" );
1279 my $volid = PVE
:: Storage
:: vdisk_alloc
( $storecfg, $storeid, $vmid,
1280 $fmt, undef , $size*1024*1024 );
1282 $disk ->{ file
} = $volid ;
1283 delete $disk ->{ format
}; # no longer needed
1284 push @$vollist, $volid ;
1285 $settings ->{ $ds } = PVE
:: QemuServer
:: print_drive
( $vmid, $disk );
1288 if ( $disk ->{ file
} =~ m
|^ /dev/ .+|) {
1289 $path = $disk ->{ file
};
1291 $path = PVE
:: Storage
:: path
( $storecfg, $disk ->{ file
});
1293 if (!(- f
$path || - b
$path )) {
1294 die "image ' $path ' does not exists \n " ;
1303 syslog
( 'err' , "VM $vmid creating disks failed" );
1304 foreach my $volid ( @$vollist ) {
1305 eval { PVE
:: Storage
:: vdisk_free
( $storecfg, $volid ); };
1315 my ( $storecfg, $vmid, $volid ) = @_ ;
1317 die "reject to unlink absolute path ' $volid '"
1320 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1322 die "reject to unlink ' $volid ' - not owned by this VM"
1323 if ! $owner || ( $owner != $vmid );
1325 syslog
( 'info' , "VM $vmid deleting volume ' $volid '" );
1327 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1329 touch_config
( $vmid );
1333 my ( $storecfg, $vmid ) = @_ ;
1335 my $conffile = config_file
( $vmid );
1337 my $conf = load_config
( $vmid );
1341 # only remove disks owned by this VM
1342 foreach_drive
( $conf, sub {
1343 my ( $ds, $drive ) = @_ ;
1345 return if drive_is_cdrom
( $drive );
1347 my $volid = $drive ->{ file
};
1348 next if ! $volid || $volid =~ m
|^/|;
1350 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1351 next if ! $path || ! $owner || ( $owner != $vmid );
1353 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1358 # also remove unused disk
1360 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid );
1363 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1364 my ( $volid, $sid, $volname, $d ) = @_ ;
1365 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1375 sub load_diskinfo_old
{
1376 my ( $storecfg, $vmid, $conf ) = @_ ;
1382 foreach_drive
( $conf, sub {
1387 return if drive_is_cdrom
( $di );
1389 if ( $di ->{ file
} =~ m
|^ /dev/ .+|) {
1390 $info ->{ $di ->{ file
}}->{ size
} = PVE
:: Storage
:: file_size_info
( $di ->{ file
});
1392 push @$vollist, $di ->{ file
};
1397 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid, $vollist );
1399 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1400 my ( $volid, $sid, $volname, $d ) = @_ ;
1401 $info ->{ $volid } = $d ;
1406 foreach my $ds ( keys %$res ) {
1407 my $di = $res ->{ $ds };
1409 $res ->{ $ds }->{ disksize
} = $info ->{ $di ->{ file
}} ?
1410 $info ->{ $di ->{ file
}}->{ size
} / ( 1024 * 1024 ) : 0 ;
1419 my $cfspath = cfs_config_path
( $vmid );
1421 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath );
1423 die "no such VM (' $vmid ') \n " if ! defined ( $conf );
1428 sub parse_vm_config
{
1429 my ( $filename, $raw ) = @_ ;
1431 return undef if ! defined ( $raw );
1434 digest
=> Digest
:: SHA1
:: sha1_hex
( $raw ),
1437 $filename =~ m
| /qemu-server/ ( \d
+) \
. conf
$|
1438 || die "got strange filename ' $filename '" ;
1442 while ( $raw && $raw =~ s/^(.*?)(\n|$)// ) {
1445 next if $line =~ m/^\#/ ;
1447 next if $line =~ m/^\s*$/ ;
1449 if ( $line =~ m/^(description):\s*(.*\S)\s*$/ ) {
1451 my $value = PVE
:: Tools
:: decode_text
( $2 );
1452 $res ->{ $key } = $value ;
1453 } elsif ( $line =~ m/^(args):\s*(.*\S)\s*$/ ) {
1456 $res ->{ $key } = $value ;
1457 } elsif ( $line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/ ) {
1460 eval { $value = check_type
( $key, $value ); };
1462 warn "vm $vmid - unable to parse value of ' $key ' - $@ " ;
1464 my $fmt = $confdesc ->{ $key }->{ format
};
1465 if ( $fmt && $fmt eq 'pve-qm-drive' ) {
1466 my $v = parse_drive
( $key, $value );
1467 if ( my $volid = filename_to_volume_id
( $vmid, $v ->{ file
}, $v ->{ media
})) {
1468 $v ->{ file
} = $volid ;
1469 $value = print_drive
( $vmid, $v );
1471 warn "vm $vmid - unable to parse value of ' $key ' \n " ;
1476 if ( $key eq 'cdrom' ) {
1477 $res ->{ ide2
} = $value ;
1479 $res ->{ $key } = $value ;
1485 # convert old smp to sockets
1486 if ( $res ->{ smp
} && ! $res ->{ sockets
}) {
1487 $res ->{ sockets
} = $res ->{ smp
};
1495 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1497 lock_config
( $vmid, & change_config_nolock
, $settings, $unset, $skiplock );
1500 sub change_config_nolock
{
1501 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1505 $unset ->{ ide2
} = $unset ->{ cdrom
} if $unset ->{ cdrom
};
1507 check_lock
( $settings ) if ! $skiplock ;
1509 # we do not use 'smp' any longer
1510 if ( $settings ->{ sockets
}) {
1512 } elsif ( $settings ->{ smp
}) {
1513 $settings ->{ sockets
} = $settings ->{ smp
};
1517 my $new_volids = {};
1519 foreach my $key ( keys %$settings ) {
1520 next if $key eq 'digest' ;
1521 my $value = $settings ->{ $key };
1522 if ( $key eq 'description' ) {
1523 $value = PVE
:: Tools
:: encode_text
( $value );
1525 eval { $value = check_type
( $key, $value ); };
1526 die "unable to parse value of ' $key ' - $@ " if $@ ;
1527 if ( $key eq 'cdrom' ) {
1528 $res ->{ ide2
} = $value ;
1530 $res ->{ $key } = $value ;
1532 if ( valid_drivename
( $key )) {
1533 my $drive = PVE
:: QemuServer
:: parse_drive
( $key, $value );
1534 $new_volids ->{ $drive ->{ file
}} = 1 if $drive && $drive ->{ file
};
1538 my $filename = config_file
( $vmid );
1539 my $tmpfn = " $filename . $$ .tmp" ;
1541 my $fh = new IO
:: File
( $filename, "r" ) ||
1542 die "unable to read config for VM $vmid\n " ;
1544 my $werror = "unable to write config for VM $vmid\n " ;
1546 my $out = new IO
:: File
( $tmpfn, "w" ) || die $werror ;
1552 while ( my $line = < $fh >) {
1554 if (( $line =~ m/^\#/ ) || ( $line =~ m/^\s*$/ )) {
1555 die $werror unless print $out $line ;
1559 if ( $line =~ m/^([a-z][a-z_]*\d*):\s*(.*\S)\s*$/ ) {
1563 # remove 'unusedX' settings if we re-add a volume
1564 next if $key =~ m/^unused/ && $new_volids ->{ $value };
1566 # convert 'smp' to 'sockets'
1567 $key = 'sockets' if $key eq 'smp' ;
1569 next if $done ->{ $key };
1572 if ( defined ( $res ->{ $key })) {
1573 $value = $res ->{ $key };
1574 delete $res ->{ $key };
1576 if (! defined ( $unset ->{ $key })) {
1577 die $werror unless print $out " $key : $value\n " ;
1583 die "unable to parse config file: $line\n " ;
1586 foreach my $key ( keys %$res ) {
1588 if (! defined ( $unset ->{ $key })) {
1589 die $werror unless print $out " $key : $res ->{ $key } \n " ;
1604 if (! $out -> close ()) {
1605 $err = "close failed - $!\n " ;
1610 if (! rename ( $tmpfn, $filename )) {
1611 $err = "rename failed - $!\n " ;
1621 # we use static defaults from our JSON schema configuration
1622 foreach my $key ( keys %$confdesc ) {
1623 if ( defined ( my $default = $confdesc ->{ $key }->{ default })) {
1624 $res ->{ $key } = $default ;
1628 my $conf = PVE
:: Cluster
:: cfs_read_file
( 'datacenter.cfg' );
1629 $res ->{ keyboard
} = $conf ->{ keyboard
} if $conf ->{ keyboard
};
1635 my $vmlist = PVE
:: Cluster
:: get_vmlist
();
1637 return $res if ! $vmlist || ! $vmlist ->{ ids
};
1638 my $ids = $vmlist ->{ ids
};
1640 foreach my $vmid ( keys %$ids ) {
1641 my $d = $ids ->{ $vmid };
1642 next if ! $d ->{ node
} || $d ->{ node
} ne $nodename ;
1643 next if ! $d ->{ type
} || $d ->{ type
} ne 'qemu' ;
1644 $res ->{ $vmid }->{ exists } = 1 ;
1649 # test if VM uses local resources (to prevent migration)
1650 sub check_local_resources
{
1651 my ( $conf, $noerr ) = @_ ;
1655 $loc_res = 1 if $conf ->{ hostusb
}; # old syntax
1656 $loc_res = 1 if $conf ->{ hostpci
}; # old syntax
1658 foreach my $k ( keys %$conf ) {
1659 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/ ;
1662 die "VM uses local resources \n " if $loc_res && ! $noerr ;
1670 die "VM is locked ( $conf ->{lock}) \n " if $conf ->{ lock };
1674 my ( $pidfile, $pid ) = @_ ;
1676 my $fh = IO
:: File-
> new ( "/proc/ $pid/cmdline " , "r" );
1680 return undef if ! $line ;
1681 my @param = split ( /\0/ , $line );
1683 my $cmd = $param [ 0 ];
1684 return if ! $cmd || ( $cmd !~ m
| kvm
$|);
1686 for ( my $i = 0 ; $i < scalar ( @param ); $i++ ) {
1689 if (( $p eq '-pidfile' ) || ( $p eq '--pidfile' )) {
1690 my $p = $param [ $i+1 ];
1691 return 1 if $p && ( $p eq $pidfile );
1700 my ( $vmid, $nocheck ) = @_ ;
1702 my $filename = config_file
( $vmid );
1704 die "unable to find configuration file for VM $vmid - no such machine \n "
1705 if ! $nocheck && ! - f
$filename ;
1707 my $pidfile = pidfile_name
( $vmid );
1709 if ( my $fd = IO
:: File-
> new ( "< $pidfile " )) {
1714 my $mtime = $st -> mtime ;
1715 if ( $mtime > time ()) {
1716 warn "file ' $filename ' modified in future \n " ;
1719 if ( $line =~ m/^(\d+)$/ ) {
1721 if ( check_cmdline
( $pidfile, $pid )) {
1722 if ( my $pinfo = PVE
:: ProcFSTools
:: check_process_running
( $pid )) {
1734 my $vzlist = config_list
();
1736 my $fd = IO
:: Dir-
> new ( $var_run_tmpdir ) || return $vzlist ;
1738 while ( defined ( my $de = $fd -> read )) {
1739 next if $de !~ m/^(\d+)\.pid$/ ;
1741 next if ! defined ( $vzlist ->{ $vmid });
1742 if ( my $pid = check_running
( $vmid )) {
1743 $vzlist ->{ $vmid }->{ pid
} = $pid ;
1750 my $storage_timeout_hash = {};
1753 my ( $storecfg, $conf ) = @_ ;
1755 my $bootdisk = $conf ->{ bootdisk
};
1756 return undef if ! $bootdisk ;
1757 return undef if ! valid_drivename
( $bootdisk );
1759 return undef if ! $conf ->{ $bootdisk };
1761 my $drive = parse_drive
( $bootdisk, $conf ->{ $bootdisk });
1762 return undef if ! defined ( $drive );
1764 return undef if drive_is_cdrom
( $drive );
1766 my $volid = $drive ->{ file
};
1767 return undef if ! $volid ;
1773 if ( $volid =~ m
|^/|) {
1774 $path = $timeoutid = $volid ;
1776 $storeid = $timeoutid = PVE
:: Storage
:: parse_volume_id
( $volid );
1777 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
1780 my $last_timeout = $storage_timeout_hash ->{ $timeoutid };
1781 if ( $last_timeout ) {
1782 if (( time () - $last_timeout ) < 30 ) {
1783 # skip storage with errors
1786 delete $storage_timeout_hash ->{ $timeoutid };
1789 my ( $size, $format, $used );
1791 ( $size, $format, $used ) = PVE
:: Storage
:: file_size_info
( $path, 1 );
1793 if (! defined ( $format )) {
1795 $storage_timeout_hash ->{ $timeoutid } = time ();
1799 return wantarray ?
( $size, $used ) : $size ;
1802 my $last_proc_pid_stat ;
1805 my ( $opt_vmid ) = @_ ;
1809 my $storecfg = PVE
:: Storage
:: config
();
1811 my $list = vzlist
();
1812 my ( $uptime ) = PVE
:: ProcFSTools
:: read_proc_uptime
( 1 );
1814 foreach my $vmid ( keys %$list ) {
1815 next if $opt_vmid && ( $vmid ne $opt_vmid );
1817 my $cfspath = cfs_config_path
( $vmid );
1818 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath ) || {};
1821 $d ->{ pid
} = $list ->{ $vmid }->{ pid
};
1823 # fixme: better status?
1824 $d ->{ status
} = $list ->{ $vmid }->{ pid
} ?
'running' : 'stopped' ;
1826 my ( $size, $used ) = disksize
( $storecfg, $conf );
1827 if ( defined ( $size ) && defined ( $used )) {
1829 $d ->{ maxdisk
} = $size ;
1835 $d ->{ cpus
} = ( $conf ->{ sockets
} || 1 ) * ( $conf ->{ cores
} || 1 );
1836 $d ->{ name
} = $conf ->{ name
} || "VM $vmid " ;
1837 $d ->{ maxmem
} = $conf ->{ memory
} ?
$conf ->{ memory
}*( 1024 * 1024 ) : 0 ;
1848 $d ->{ diskwrite
} = 0 ;
1853 my $netdev = PVE
:: ProcFSTools
:: read_proc_net_dev
();
1854 foreach my $dev ( keys %$netdev ) {
1855 next if $dev !~ m/^tap([1-9]\d*)i/ ;
1857 my $d = $res ->{ $vmid };
1860 $d ->{ netout
} += $netdev ->{ $dev }->{ receive
};
1861 $d ->{ netin
} += $netdev ->{ $dev }->{ transmit
};
1864 my $cpucount = $cpuinfo ->{ cpus
} || 1 ;
1865 my $ctime = gettimeofday
;
1867 foreach my $vmid ( keys %$list ) {
1869 my $d = $res ->{ $vmid };
1870 my $pid = $d ->{ pid
};
1873 if ( my $fh = IO
:: File-
> new ( "/proc/ $pid/io " , "r" )) {
1875 while ( defined ( my $line = < $fh >)) {
1876 if ( $line =~ m/^([rw]char):\s+(\d+)$/ ) {
1881 $d ->{ diskread
} = $data ->{ rchar
} || 0 ;
1882 $d ->{ diskwrite
} = $data ->{ wchar
} || 0 ;
1885 my $pstat = PVE
:: ProcFSTools
:: read_proc_pid_stat
( $pid );
1886 next if ! $pstat ; # not running
1888 my $used = $pstat ->{ utime } + $pstat ->{ stime
};
1890 my $vcpus = $d ->{ cpus
} > $cpucount ?
$cpucount : $d ->{ cpus
};
1892 $d ->{ uptime
} = int (( $uptime - $pstat ->{ starttime
})/ $cpuinfo ->{ user_hz
});
1894 if ( $pstat ->{ vsize
}) {
1895 $d ->{ mem
} = int (( $pstat ->{ rss
}/ $pstat ->{ vsize
})* $d ->{ maxmem
});
1898 my $old = $last_proc_pid_stat ->{ $pid };
1900 $last_proc_pid_stat ->{ $pid } = {
1909 my $dtime = ( $ctime - $old ->{ time }) * $cpucount * $cpuinfo ->{ user_hz
};
1911 if ( $dtime > 1000 ) {
1912 my $dutime = $used - $old ->{ used
};
1914 $d ->{ cpu
} = $dutime/$dtime ;
1915 $d ->{ relcpu
} = ( $d ->{ cpu
} * $cpucount ) / $vcpus ;
1916 $last_proc_pid_stat ->{ $pid } = {
1920 relcpu
=> $d ->{ relcpu
},
1923 $d ->{ cpu
} = $old ->{ cpu
};
1924 $d ->{ relcpu
} = $old ->{ relcpu
};
1932 my ( $conf, $func ) = @_ ;
1934 foreach my $ds ( keys %$conf ) {
1935 next if ! valid_drivename
( $ds );
1937 my $drive = parse_drive
( $ds, $conf ->{ $ds });
1940 & $func ( $ds, $drive );
1944 sub config_to_command
{
1945 my ( $storecfg, $vmid, $conf, $defaults, $migrate_uri ) = @_ ;
1949 my $kvmver = kvm_user_version
();
1950 my $vernum = 0 ; # unknown
1951 if ( $kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/ ) {
1952 $vernum = $1*1000000+$2*1000+$3 ;
1955 die "detected old qemu-kvm binary ( $kvmver ) \n " if $vernum < 14000 ;
1957 my $have_ovz = - f
'/proc/vz/vestat' ;
1959 push @$cmd, '/usr/bin/kvm' ;
1961 push @$cmd, '-id' , $vmid ;
1965 my $socket = monitor_socket
( $vmid );
1966 push @$cmd, '-chardev' , "socket,id=monitor,path= $socket,server,nowait " ;
1967 push @$cmd, '-mon' , "chardev=monitor,mode=readline" ;
1969 $socket = vnc_socket
( $vmid );
1970 push @$cmd, '-vnc' , "unix: $socket,x509,password " ;
1972 push @$cmd, '-pidfile' , pidfile_name
( $vmid );
1974 push @$cmd, '-daemonize' ;
1976 push @$cmd, '-incoming' , $migrate_uri if $migrate_uri ;
1978 # include usb device config
1979 push @$cmd, '-readconfig' , '/usr/share/qemu-server/pve-usb.cfg' ;
1981 # enable absolute mouse coordinates (needed by vnc)
1982 my $tablet = defined ( $conf ->{ tablet
}) ?
$conf ->{ tablet
} : $defaults ->{ tablet
};
1983 push @$cmd, '-device' , 'usb-tablet,bus=ehci.0,port=6' if $tablet ;
1986 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
1987 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
1989 $pciaddr = print_pci_addr
( "hostpci $i " );
1990 push @$cmd, '-device' , "pci-assign,host= $d ->{pciid},id=hostpci $i$pciaddr " ;
1994 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1995 my $d = parse_usb_device
( $conf ->{ "usb $i " });
1997 if ( $d ->{ vendorid
} && $d ->{ productid
}) {
1998 push @$cmd, '-device' , "usb-host,vendorid= $d ->{vendorid},productid= $d ->{productid}" ;
1999 } elsif ( defined ( $d ->{ hostbus
}) && defined ( $d ->{ hostport
})) {
2000 push @$cmd, '-device' , "usb-host,hostbus= $d ->{hostbus},hostport= $d ->{hostport}" ;
2005 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
2006 if ( my $path = $conf ->{ "serial $i " }) {
2007 die "no such serial device \n " if ! - c
$path ;
2008 push @$cmd, '-chardev' , "tty,id=serial $i,path = $path " ;
2009 push @$cmd, '-device' , "isa-serial,chardev=serial $i " ;
2014 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
2015 if ( my $path = $conf ->{ "parallel $i " }) {
2016 die "no such parallel device \n " if ! - c
$path ;
2017 push @$cmd, '-chardev' , "parport,id=parallel $i,path = $path " ;
2018 push @$cmd, '-device' , "isa-parallel,chardev=parallel $i " ;
2022 my $vmname = $conf ->{ name
} || "vm $vmid " ;
2024 push @$cmd, '-name' , $vmname ;
2027 $sockets = $conf ->{ smp
} if $conf ->{ smp
}; # old style - no longer iused
2028 $sockets = $conf ->{ sockets
} if $conf ->{ sockets
};
2030 my $cores = $conf ->{ cores
} || 1 ;
2034 push @$cmd, '-smp' , "sockets= $sockets,cores = $cores " ;
2036 push @$cmd, '-cpu' , $conf ->{ cpu
} if $conf ->{ cpu
};
2038 push @$cmd, '-nodefaults' ;
2040 my $bootorder = $conf ->{ boot
} || $confdesc ->{ boot
}->{ default };
2041 push @$cmd, '-boot' , "menu=on,order= $bootorder " ;
2043 push @$cmd, '-no-acpi' if defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 ;
2045 push @$cmd, '-no-reboot' if defined ( $conf ->{ reboot
}) && $conf ->{ reboot
} == 0 ;
2047 my $vga = $conf ->{ vga
};
2049 if ( $conf ->{ ostype
} && ( $conf ->{ ostype
} eq 'win7' || $conf ->{ ostype
} eq 'w2k8' )) {
2056 push @$cmd, '-vga' , $vga if $vga ; # for kvm 77 and later
2059 my $tdf = defined ( $conf ->{ tdf
}) ?
$conf ->{ tdf
} : $defaults ->{ tdf
};
2060 push @$cmd, '-tdf' if $tdf ;
2062 my $nokvm = defined ( $conf ->{ kvm
}) && $conf ->{ kvm
} == 0 ?
1 : 0 ;
2064 if ( my $ost = $conf ->{ ostype
}) {
2065 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2067 if ( $ost =~ m/^w/ ) { # windows
2068 push @$cmd, '-localtime' if ! defined ( $conf ->{ localtime });
2070 # use rtc-td-hack when acpi is enabled
2071 if (!( defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 )) {
2072 push @$cmd, '-rtc-td-hack' ;
2083 push @$cmd, '-no-kvm' ;
2085 die "No accelerator found! \n " if ! $cpuinfo ->{ hvm
};
2088 push @$cmd, '-localtime' if $conf ->{ localtime };
2090 push @$cmd, '-startdate' , $conf ->{ startdate
} if $conf ->{ startdate
};
2092 push @$cmd, '-S' if $conf ->{ freeze
};
2094 # set keyboard layout
2095 my $kb = $conf ->{ keyboard
} || $defaults ->{ keyboard
};
2096 push @$cmd, '-k' , $kb if $kb ;
2099 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2100 #push @$cmd, '-soundhw', 'es1370';
2101 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2102 $pciaddr = print_pci_addr
( "balloon0" );
2103 push @$cmd, '-device' , "virtio-balloon-pci,id=balloon0 $pciaddr " if $conf ->{ balloon
};
2105 if ( $conf ->{ watchdog
}) {
2106 my $wdopts = parse_watchdog
( $conf ->{ watchdog
});
2107 push @$cmd, '-watchdog' , $wdopts ->{ model
} || 'i6300esb' ;
2108 push @$cmd, '-watchdog-action' , $wdopts ->{ action
} if $wdopts ->{ action
};
2112 my $scsicontroller = {};
2114 foreach_drive
( $conf, sub {
2115 my ( $ds, $drive ) = @_ ;
2118 PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
});
2119 push @$vollist, $drive ->{ file
};
2122 $use_virtio = 1 if $ds =~ m/^virtio/ ;
2123 if ( $drive ->{ interface
} eq 'scsi' ) {
2125 my $controller = int ( $drive ->{ index } / $maxdev );
2126 push @$cmd, '-device' , "lsi,id=scsi $controller " if ! $scsicontroller ->{ $controller };
2127 my $scsicontroller ->{ $controller }= 1 ;
2129 my $tmp = print_drive_full
( $storecfg, $vmid, $drive );
2130 $tmp .= ",boot=on" if $conf ->{ bootdisk
} && ( $conf ->{ bootdisk
} eq $ds );
2131 push @$cmd, '-drive' , $tmp ;
2132 push @$cmd, '-device' , print_drivedevice_full
( $storecfg,$vmid, $drive );
2135 push @$cmd, '-m' , $conf ->{ memory
} || $defaults ->{ memory
};
2139 foreach my $k ( sort keys %$conf ) {
2140 next if $k !~ m/^net(\d+)$/ ;
2143 die "got strange net id ' $i ' \n " if $i >= ${ MAX_NETS
};
2145 if ( $conf ->{ "net $i " } && ( my $net = parse_net
( $conf ->{ "net $i " }))) {
2149 my $ifname = "tap${vmid}i $i " ;
2151 # kvm uses TUNSETIFF ioctl, and that limits ifname length
2152 die "interface name ' $ifname ' is too long (max 15 character) \n "
2153 if length ( $ifname ) >= 16 ;
2155 my $device = $net ->{ model
};
2156 my $vhostparam = '' ;
2157 if ( $net ->{ model
} eq 'virtio' ) {
2159 $device = 'virtio-net-pci' ;
2160 $vhostparam = ',vhost=on' if $kernel_has_vhost_net ;
2163 if ( $net ->{ bridge
}) {
2164 push @$cmd, '-netdev' , "type=tap,id=${k},ifname=${ifname},script=/var/lib/qemu-server/pve-bridge $vhostparam " ;
2166 push @$cmd, '-netdev' , "type=user,id=${k},hostname= $vmname " ;
2169 # qemu > 0.15 always try to boot from network - we disable that by
2170 # not loading the pxe rom file
2171 my $extra = (! $conf ->{ boot
} || ( $conf ->{ boot
} !~ m/n/ )) ?
2173 push @$cmd, '-device' , " $device,$ {extra}mac= $net ->{macaddr},netdev=${k}" ;
2177 push @$cmd, '-net' , 'none' if ! $foundnet ;
2179 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2180 # when the VM uses virtio devices.
2181 if (! $use_virtio && $have_ovz ) {
2183 my $cpuunits = defined ( $conf ->{ cpuunits
}) ?
2184 $conf ->{ cpuunits
} : $defaults ->{ cpuunits
};
2186 push @$cmd, '-cpuunits' , $cpuunits if $cpuunits ;
2188 # fixme: cpulimit is currently ignored
2189 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2193 if ( $conf ->{ args
}) {
2194 my $aa = split_args
( $conf ->{ args
});
2198 return wantarray ?
( $cmd, $vollist ) : $cmd ;
2203 return "${var_run_tmpdir}/ $vmid .vnc" ;
2206 sub monitor_socket
{
2208 return "${var_run_tmpdir}/ $vmid .mon" ;
2213 return "${var_run_tmpdir}/ $vmid .pid" ;
2216 sub random_ether_addr
{
2218 my $rand = Digest
:: SHA1
:: sha1_hex
( rand (), time ());
2221 for ( my $i = 0 ; $i < 6 ; $i++ ) {
2222 my $ss = hex ( substr ( $rand, $i*2, 2 ));
2224 $ss &= 0xfe ; # clear multicast
2225 $ss |= 2 ; # set local id
2227 $ss = sprintf ( " %02X " , $ss );
2239 sub next_migrate_port
{
2241 for ( my $p = 60000 ; $p < 60010 ; $p++ ) {
2243 my $sock = IO
:: Socket
:: INET-
> new ( Listen
=> 5 ,
2244 LocalAddr
=> 'localhost' ,
2255 die "unable to find free migration port" ;
2259 my ( $storecfg, $vmid, $statefile, $skiplock ) = @_ ;
2261 lock_config
( $vmid, sub {
2262 my $conf = load_config
( $vmid );
2264 check_lock
( $conf ) if ! $skiplock ;
2266 if ( check_running
( $vmid )) {
2267 my $msg = "VM $vmid already running - start failed \n " ;
2268 syslog
( 'err' , $msg );
2271 syslog
( 'info' , "VM $vmid start" );
2275 my $migrate_port = 0 ;
2278 if ( $statefile eq 'tcp' ) {
2279 $migrate_port = next_migrate_port
();
2280 $migrate_uri = "tcp:localhost:${migrate_port}" ;
2282 if (- f
$statefile ) {
2283 $migrate_uri = "exec:cat $statefile " ;
2285 warn "state file ' $statefile ' does not exist - doing normal startup \n " ;
2290 my $defaults = load_defaults
();
2292 my ( $cmd, $vollist ) = config_to_command
( $storecfg, $vmid, $conf, $defaults, $migrate_uri );
2294 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
2295 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
2297 my $info = pci_device_info
( "0000: $d ->{pciid}" );
2298 die "IOMMU not present \n " if ! check_iommu_support
();
2299 die "no pci device info for device ' $d ->{pciid}' \n " if ! $info ;
2300 die "can't unbind pci device ' $d ->{pciid}' \n " if ! pci_dev_bind_to_stub
( $info );
2301 die "can't reset pci device ' $d ->{pciid}' \n " if ! pci_dev_reset
( $info );
2304 PVE
:: Storage
:: activate_volumes
( $storecfg, $vollist );
2306 eval { run_command
( $cmd, timeout
=> $migrate_uri ?
undef : 30 ); };
2311 my $msg = "start failed: $err " ;
2312 syslog
( 'err' , "VM $vmid $msg " );
2318 if ( $statefile eq 'tcp' ) {
2319 print "migration listens on port $migrate_port\n " ;
2322 # fixme: send resume - is that necessary ?
2323 eval { vm_monitor_command
( $vmid, "cont" , 1 ) };
2327 if ( my $migrate_speed =
2328 $conf ->{ migrate_speed
} || $defaults ->{ migrate_speed
}) {
2329 my $cmd = "migrate_set_speed ${migrate_speed}m" ;
2330 eval { vm_monitor_command
( $vmid, $cmd, 1 ); };
2333 if ( my $migrate_downtime =
2334 $conf ->{ migrate_downtime
} || $defaults ->{ migrate_downtime
}) {
2335 my $cmd = "migrate_set_downtime ${migrate_downtime}" ;
2336 eval { vm_monitor_command
( $vmid, $cmd, 1 ); };
2339 vm_balloonset
( $vmid, $conf ->{ balloon
}) if $conf ->{ balloon
};
2344 my ( $fh, $timeout ) = @_ ;
2346 my $sel = new IO
:: Select
;
2353 while ( scalar ( @ready = $sel -> can_read ( $timeout ))) {
2355 if ( $count = $fh -> sysread ( $buf, 8192 )) {
2356 if ( $buf =~ /^(.*)\(qemu\) $/s ) {
2363 if (! defined ( $count )) {
2370 die "monitor read timeout \n " if ! scalar ( @ready );
2375 sub vm_monitor_command
{
2376 my ( $vmid, $cmdstr, $nolog, $nocheck ) = @_ ;
2380 syslog
( "info" , "VM $vmid monitor command ' $cmdstr '" ) if ! $nolog ;
2383 die "VM not running \n " if ! check_running
( $vmid, $nocheck );
2385 my $sname = monitor_socket
( $vmid );
2387 my $sock = IO
:: Socket
:: UNIX-
> new ( Peer
=> $sname ) ||
2388 die "unable to connect to VM $vmid socket - $!\n " ;
2392 # hack: migrate sometime blocks the monitor (when migrate_downtime
2394 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2395 $timeout = 60 * 60 ; # 1 hour
2399 my $data = __read_avail
( $sock, $timeout );
2401 if ( $data !~ m/^QEMU\s+(\S+)\s+monitor\s/ ) {
2402 die "got unexpected qemu monitor banner \n " ;
2405 my $sel = new IO
:: Select
;
2408 if (! scalar ( my @ready = $sel -> can_write ( $timeout ))) {
2409 die "monitor write error - timeout" ;
2412 my $fullcmd = " $cmdstr\r " ;
2415 if (!( $b = $sock -> syswrite ( $fullcmd )) || ( $b != length ( $fullcmd ))) {
2416 die "monitor write error - $! " ;
2419 return if ( $cmdstr eq 'q' ) || ( $cmdstr eq 'quit' );
2423 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2424 $timeout = 60 * 60 ; # 1 hour
2425 } elsif ( $cmdstr =~ m/^(eject|change)/ ) {
2426 $timeout = 60 ; # note: cdrom mount command is slow
2428 if ( $res = __read_avail
( $sock, $timeout )) {
2430 my @lines = split ( " \r ? \n " , $res );
2432 shift @lines if $lines [ 0 ] !~ m/^unknown command/ ; # skip echo
2434 $res = join ( " \n " , @lines );
2442 syslog
( "err" , "VM $vmid monitor command failed - $err " );
2449 sub vm_commandline
{
2450 my ( $storecfg, $vmid ) = @_ ;
2452 my $conf = load_config
( $vmid );
2454 my $defaults = load_defaults
();
2456 my $cmd = config_to_command
( $storecfg, $vmid, $conf, $defaults );
2458 return join ( ' ' , @$cmd );
2462 my ( $vmid, $skiplock ) = @_ ;
2464 lock_config
( $vmid, sub {
2466 my $conf = load_config
( $vmid );
2468 check_lock
( $conf ) if ! $skiplock ;
2470 syslog
( "info" , "VM $vmid sending 'reset'" );
2472 vm_monitor_command
( $vmid, "system_reset" , 1 );
2477 my ( $vmid, $skiplock ) = @_ ;
2479 lock_config
( $vmid, sub {
2481 my $conf = load_config
( $vmid );
2483 check_lock
( $conf ) if ! $skiplock ;
2485 syslog
( "info" , "VM $vmid sending 'shutdown'" );
2487 vm_monitor_command
( $vmid, "system_powerdown" , 1 );
2491 # Note: use $nockeck to skip tests if VM configuration file exists.
2492 # We need that when migration VMs to other nodes (files already moved)
2494 my ( $vmid, $skiplock, $nocheck ) = @_ ;
2496 lock_config
( $vmid, sub {
2498 my $pid = check_running
( $vmid, $nocheck );
2501 syslog
( 'info' , "VM $vmid already stopped" );
2506 my $conf = load_config
( $vmid );
2507 check_lock
( $conf ) if ! $skiplock ;
2510 syslog
( "info" , "VM $vmid stopping" );
2512 eval { vm_monitor_command
( $vmid, "quit" , 1 , $nocheck ); };
2518 my $timeout = 50 ; # fixme: how long?
2521 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2526 if ( $count >= $timeout ) {
2527 syslog
( 'info' , "VM $vmid still running - terminating now with SIGTERM" );
2531 syslog
( 'info' , "VM $vmid quit failed - terminating now with SIGTERM" );
2539 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2544 if ( $count >= $timeout ) {
2545 syslog
( 'info' , "VM $vmid still running - terminating now with SIGKILL \n " );
2549 fairsched_rmnod
( $vmid ); # try to destroy group
2554 my ( $vmid, $skiplock ) = @_ ;
2556 lock_config
( $vmid, sub {
2558 my $conf = load_config
( $vmid );
2560 check_lock
( $conf ) if ! $skiplock ;
2562 syslog
( "info" , "VM $vmid suspend" );
2564 vm_monitor_command
( $vmid, "stop" , 1 );
2569 my ( $vmid, $skiplock ) = @_ ;
2571 lock_config
( $vmid, sub {
2573 my $conf = load_config
( $vmid );
2575 check_lock
( $conf ) if ! $skiplock ;
2577 syslog
( "info" , "VM $vmid resume" );
2579 vm_monitor_command
( $vmid, "cont" , 1 );
2584 my ( $vmid, $skiplock ) = @_ ;
2586 lock_config
( $vmid, sub {
2588 my $conf = load_config
( $vmid );
2590 check_lock
( $conf ) if ! $skiplock ;
2592 syslog
( "info" , "VM $vmid sending cntl-alt-delete" );
2594 vm_monitor_command
( $vmid, "sendkey ctrl-alt-delete" , 1 );
2599 my ( $storecfg, $vmid, $skiplock ) = @_ ;
2601 lock_config
( $vmid, sub {
2603 my $conf = load_config
( $vmid );
2605 check_lock
( $conf ) if ! $skiplock ;
2607 syslog
( "info" , "VM $vmid destroy called (removing all data)" );
2610 if (! check_running
( $vmid )) {
2611 fairsched_rmnod
( $vmid ); # try to destroy group
2612 destroy_vm
( $storecfg, $vmid );
2614 die "VM is running \n " ;
2621 syslog
( "err" , "VM $vmid destroy failed - $err " );
2630 $timeout = 3 * 60 if ! $timeout ;
2632 my $vzlist = vzlist
();
2634 foreach my $vmid ( keys %$vzlist ) {
2635 next if ! $vzlist ->{ $vmid }->{ pid
};
2641 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs \n " ;
2642 syslog
( 'info' , $msg );
2645 foreach my $vmid ( keys %$vzlist ) {
2646 next if ! $vzlist ->{ $vmid }->{ pid
};
2647 eval { vm_shutdown
( $vmid, 1 ); };
2648 print STDERR
$@ if $@ ;
2652 my $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2654 while (( $try < $maxtries ) && $count ) {
2660 foreach my $vmid ( keys %$vzlist ) {
2661 next if ! $vzlist ->{ $vmid }->{ pid
};
2669 foreach my $vmid ( keys %$vzlist ) {
2670 next if ! $vzlist ->{ $vmid }->{ pid
};
2672 $msg = "VM $vmid still running - sending stop now \n " ;
2673 syslog
( 'info' , $msg );
2676 eval { vm_monitor_command
( $vmid, "quit" , 1 ); };
2677 print STDERR
$@ if $@ ;
2682 $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2684 while (( $try < $maxtries ) && $count ) {
2690 foreach my $vmid ( keys %$vzlist ) {
2691 next if ! $vzlist ->{ $vmid }->{ pid
};
2699 foreach my $vmid ( keys %$vzlist ) {
2700 next if ! $vzlist ->{ $vmid }->{ pid
};
2702 $msg = "VM $vmid still running - terminating now with SIGTERM \n " ;
2703 syslog
( 'info' , $msg );
2705 kill 15 , $vzlist ->{ $vmid }->{ pid
};
2708 # this is called by system shotdown scripts, so remaining
2709 # processes gets killed anyways (no need to send kill -9 here)
2711 $msg = "Qemu Server stopped \n " ;
2712 syslog
( 'info' , $msg );
2720 my ( $filename, $buf ) = @_ ;
2722 my $fh = IO
:: File-
> new ( $filename, "w" );
2723 return undef if ! $fh ;
2725 my $res = print $fh $buf ;
2732 sub pci_device_info
{
2737 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/ ;
2738 my ( $domain, $bus, $slot, $func ) = ( $1, $2, $3, $4 );
2740 my $irq = file_read_firstline
( " $pcisysfs/devices/$name/irq " );
2741 return undef if ! defined ( $irq ) || $irq !~ m/^\d+$/ ;
2743 my $vendor = file_read_firstline
( " $pcisysfs/devices/$name/vendor " );
2744 return undef if ! defined ( $vendor ) || $vendor !~ s/^0x// ;
2746 my $product = file_read_firstline
( " $pcisysfs/devices/$name/device " );
2747 return undef if ! defined ( $product ) || $product !~ s/^0x// ;
2752 product
=> $product,
2758 has_fl_reset
=> - f
" $pcisysfs/devices/$name/reset " || 0 ,
2767 my $name = $dev ->{ name
};
2769 my $fn = " $pcisysfs/devices/$name/reset " ;
2771 return file_write
( $fn, "1" );
2774 sub pci_dev_bind_to_stub
{
2777 my $name = $dev ->{ name
};
2779 my $testdir = " $pcisysfs/drivers/pci -stub/ $name " ;
2780 return 1 if - d
$testdir ;
2782 my $data = " $dev ->{vendor} $dev ->{product}" ;
2783 return undef if ! file_write
( " $pcisysfs/drivers/pci -stub/new_id" , $data );
2785 my $fn = " $pcisysfs/devices/$name/driver/unbind " ;
2786 if (! file_write
( $fn, $name )) {
2787 return undef if - f
$fn ;
2790 $fn = " $pcisysfs/drivers/pci -stub/bind" ;
2791 if (! - d
$testdir ) {
2792 return undef if ! file_write
( $fn, $name );
2798 sub print_pci_addr
{
2803 balloon0
=> { bus
=> 0 , addr
=> 3 },
2804 virtio0
=> { bus
=> 0 , addr
=> 10 },
2805 virtio1
=> { bus
=> 0 , addr
=> 11 },
2806 virtio2
=> { bus
=> 0 , addr
=> 12 },
2807 virtio3
=> { bus
=> 0 , addr
=> 13 },
2808 virtio4
=> { bus
=> 0 , addr
=> 14 },
2809 virtio5
=> { bus
=> 0 , addr
=> 15 },
2810 hostpci0
=> { bus
=> 0 , addr
=> 16 },
2811 hostpci1
=> { bus
=> 0 , addr
=> 17 },
2815 if ( defined ( $devices ->{ $id }->{ bus
}) && defined ( $devices ->{ $id }->{ addr
})) {
2816 my $addr = sprintf ( "0x %x " , $devices ->{ $id }->{ addr
});
2817 $res = ",bus=pci. $devices ->{ $id }->{bus},addr= $addr " ;
2824 my ( $vmid, $value ) = @_ ;
2826 vm_monitor_command
( $vmid, "balloon $value " , 1 );