]>
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" ;
145 description
=> "Specifies whether a VM will be started during system bootup." ,
151 description
=> "Automatic restart after crash (currently ignored)." ,
157 description
=> "Activate hotplug for disk and network device" ,
163 description
=> "Allow reboot. If set to '0' the VM exit on reboot." ,
169 description
=> "Lock/unlock the VM." ,
170 enum
=> [ qw(migrate backup) ],
175 description
=> "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit. \n\n NOTE: This option is currently ignored." ,
182 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs. \n\n NOTE: You can disable fair-scheduler configuration by setting this to 0." ,
190 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device." ,
197 description
=> "Amount of target RAM for the VM in MB." ,
203 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file." ,
204 enum
=> PVE
:: Tools
:: kvmkeymaplist
(),
210 description
=> "Set a name for the VM. Only used on the configuration web interface." ,
215 description
=> "Description for the VM. Only used on the configuration web interface." ,
220 enum
=> [ qw(other wxp w2k w2k3 w2k8 wvista win7 l24 l26) ],
221 description
=> <<EODESC,
222 Used to enable special optimization/features for specific
225 other => unspecified OS
226 wxp => Microsoft Windows XP
227 w2k => Microsoft Windows 2000
228 w2k3 => Microsoft Windows 2003
229 w2k8 => Microsoft Windows 2008
230 wvista => Microsoft Windows Vista
231 win7 => Microsoft Windows 7
232 l24 => Linux 2.4 Kernel
233 l26 => Linux 2.6/3.X Kernel
235 other|l24|l26 ... no special behaviour
236 wxp|w2k|w2k3|w2k8|wvista|win7 ... use --localtime switch
242 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)." ,
243 pattern
=> '[acdn]{1,4}' ,
248 type
=> 'string' , format
=> 'pve-qm-bootdisk' ,
249 description
=> "Enable booting from specified disk." ,
250 pattern
=> '(ide|scsi|virtio)\d+' ,
255 description
=> "The number of CPUs. Please use option -sockets instead." ,
262 description
=> "The number of CPU sockets." ,
269 description
=> "The number of cores per socket." ,
276 description
=> "Enable/disable ACPI." ,
282 description
=> "Enable/disable KVM hardware virtualization." ,
288 description
=> "Enable/disable time drift fix." ,
294 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS." ,
299 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution)." ,
304 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win7/w2k8, and 'cirrur' for other OS types" ,
305 enum
=> [ qw(std cirrus vmware) ],
309 type
=> 'string' , format
=> 'pve-qm-watchdog' ,
310 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]' ,
311 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)" ,
316 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)" ,
317 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'." ,
318 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)' ,
324 description
=> <<EODESCR,
325 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
327 args: -no-reboot -no-hpet
334 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning. Else the mouse runs out of sync with normal vnc clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches." ,
339 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit." ,
343 migrate_downtime
=> {
346 description
=> "Set maximum tolerated downtime (in seconds) for migrations." ,
352 type
=> 'string' , format
=> 'pve-qm-drive' ,
353 typetext
=> 'volume' ,
354 description
=> "This is an alias for option -ide2" ,
358 description
=> "Emulated CPU type." ,
360 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom host) ],
365 # what about other qemu settings ?
367 #machine => 'string',
380 ##soundhw => 'string',
382 while ( my ( $k, $v ) = each %$confdesc ) {
383 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm- $k " , $v );
386 my $MAX_IDE_DISKS = 4 ;
387 my $MAX_SCSI_DISKS = 14 ;
388 my $MAX_VIRTIO_DISKS = 6 ;
389 my $MAX_USB_DEVICES = 5 ;
391 my $MAX_UNUSED_DISKS = 8 ;
392 my $MAX_HOSTPCI_DEVICES = 2 ;
393 my $MAX_SERIAL_PORTS = 4 ;
394 my $MAX_PARALLEL_PORTS = 3 ;
396 my $nic_model_list = [ 'rtl8139' , 'ne2k_pci' , 'e1000' , 'pcnet' , 'virtio' ,
397 'ne2k_isa' , 'i82551' , 'i82557b' , 'i82559er' ];
398 my $nic_model_list_txt = join ( ' ' , sort @$nic_model_list );
403 type
=> 'string' , format
=> 'pve-qm-net' ,
404 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>]" ,
405 description
=> <<EODESCR,
406 Specify network devices.
408 MODEL is one of: $nic_model_list_txt
410 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
411 automatically generated if not specified.
413 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
415 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'.
417 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
423 The DHCP server assign addresses to the guest starting from 10.0.2.15.
427 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-net" , $netdesc );
429 for ( my $i = 0 ; $i < $MAX_NETS ; $i++ ) {
430 $confdesc ->{ "net $i " } = $netdesc ;
437 type
=> 'string' , format
=> 'pve-qm-drive' ,
438 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
439 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to 3)." ,
441 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-ide" , $idedesc );
445 type
=> 'string' , format
=> 'pve-qm-drive' ,
446 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
447 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13)." ,
449 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-scsi" , $scsidesc );
453 type
=> 'string' , format
=> 'pve-qm-drive' ,
454 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
455 description
=> "Use volume as VIRTIO hard disk (n is 0 to 5)." ,
457 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-virtio" , $virtiodesc );
461 type
=> 'string' , format
=> 'pve-qm-usb-device' ,
462 typetext
=> 'host=HOSTUSBDEVICE' ,
463 description
=> <<EODESCR,
464 Configure an USB device (n is 0 to 4). This can be used to
465 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
467 'bus-port(.port)*' (decimal numbers) or
468 'vendor_id:product_id' (hexadeciaml numbers)
470 You can use the 'lsusb -t' command to list existing usb devices.
472 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
476 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-usb" , $usbdesc );
480 type
=> 'string' , format
=> 'pve-qm-hostpci' ,
481 typetext
=> "HOSTPCIDEVICE" ,
482 description
=> <<EODESCR,
483 Map host pci devices. HOSTPCIDEVICE syntax is:
485 'bus:dev.func' (hexadecimal numbers)
487 You can us the 'lspci' command to list existing pci devices.
489 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
491 Experimental: user reported problems with this option.
494 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-hostpci" , $hostpcidesc );
499 pattern
=> '/dev/ttyS\d+' ,
500 description
=> <<EODESCR,
501 Map host serial devices (n is 0 to 3).
503 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
505 Experimental: user reported problems with this option.
512 pattern
=> '/dev/parport\d+' ,
513 description
=> <<EODESCR,
514 Map host parallel devices (n is 0 to 2).
516 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
518 Experimental: user reported problems with this option.
522 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
523 $confdesc ->{ "parallel $i " } = $paralleldesc ;
526 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
527 $confdesc ->{ "serial $i " } = $serialdesc ;
530 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
531 $confdesc ->{ "hostpci $i " } = $hostpcidesc ;
534 for ( my $i = 0 ; $i < $MAX_IDE_DISKS ; $i++ ) {
535 $drivename_hash ->{ "ide $i " } = 1 ;
536 $confdesc ->{ "ide $i " } = $idedesc ;
539 for ( my $i = 0 ; $i < $MAX_SCSI_DISKS ; $i++ ) {
540 $drivename_hash ->{ "scsi $i " } = 1 ;
541 $confdesc ->{ "scsi $i " } = $scsidesc ;
544 for ( my $i = 0 ; $i < $MAX_VIRTIO_DISKS ; $i++ ) {
545 $drivename_hash ->{ "virtio $i " } = 1 ;
546 $confdesc ->{ "virtio $i " } = $virtiodesc ;
549 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
550 $confdesc ->{ "usb $i " } = $usbdesc ;
555 type
=> 'string' , format
=> 'pve-volume-id' ,
556 description
=> "Reference to unused volumes." ,
559 for ( my $i = 0 ; $i < $MAX_UNUSED_DISKS ; $i++ ) {
560 $confdesc ->{ "unused $i " } = $unuseddesc ;
563 my $kvm_api_version = 0 ;
567 return $kvm_api_version if $kvm_api_version ;
569 my $fh = IO
:: File-
> new ( "</dev/kvm" ) ||
572 if ( my $v = $fh -> ioctl ( KVM_GET_API_VERSION
(), 0 )) {
573 $kvm_api_version = $v ;
578 return $kvm_api_version ;
581 my $kvm_user_version ;
583 sub kvm_user_version
{
585 return $kvm_user_version if $kvm_user_version ;
587 $kvm_user_version = 'unknown' ;
589 my $tmp = `kvm -help 2>/dev/null` ;
591 if ( $tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?) / ) {
592 $kvm_user_version = $2 ;
595 return $kvm_user_version ;
599 my $kernel_has_vhost_net = - c
'/dev/vhost-net' ;
602 # order is important - used to autoselect boot disk
603 return (( map { "ide $_ " } ( 0 .. ( $MAX_IDE_DISKS - 1 ))),
604 ( map { "scsi $_ " } ( 0 .. ( $MAX_SCSI_DISKS - 1 ))),
605 ( map { "virtio $_ " } ( 0 .. ( $MAX_VIRTIO_DISKS - 1 ))));
608 sub valid_drivename
{
611 return defined ( $drivename_hash ->{ $dev });
616 return defined ( $confdesc ->{ $key });
620 return $nic_model_list ;
623 sub os_list_description
{
628 w2k
=> 'Windows 2000' ,
629 w2k3
=>, 'Windows 2003' ,
630 w2k8
=> 'Windows 2008' ,
631 wvista
=> 'Windows Vista' ,
638 sub disk_devive_info
{
641 die "unknown disk device format ' $dev '" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/ ;
649 } elsif ( $bus eq 'scsi' ) {
653 my $controller = int ( $index / $maxdev );
654 my $unit = $index % $maxdev ;
657 return { bus
=> $bus, desc
=> uc ( $bus ) . " $controller : $unit " ,
658 controller
=> $controller, unit
=> $unit, index => $index };
662 sub qemu_drive_name
{
663 my ( $dev, $media ) = @_ ;
665 my $info = disk_devive_info
( $dev );
668 if (( $info ->{ bus
} eq 'ide' ) || ( $info ->{ bus
} eq 'scsi' )) {
669 $mediastr = ( $media eq 'cdrom' ) ?
"-cd" : "-hd" ;
670 return sprintf ( " %s%i%s%i " , $info ->{ bus
}, $info ->{ controller
},
671 $mediastr, $info ->{ unit
});
673 return sprintf ( " %s%i " , $info ->{ bus
}, $info ->{ index });
681 return $cdrom_path if $cdrom_path ;
683 return $cdrom_path = "/dev/cdrom" if - l
"/dev/cdrom" ;
684 return $cdrom_path = "/dev/cdrom1" if - l
"/dev/cdrom1" ;
685 return $cdrom_path = "/dev/cdrom2" if - l
"/dev/cdrom2" ;
689 my ( $storecfg, $vmid, $cdrom ) = @_ ;
691 if ( $cdrom eq 'cdrom' ) {
692 return get_cdrom_path
();
693 } elsif ( $cdrom eq 'none' ) {
695 } elsif ( $cdrom =~ m
|^/|) {
698 return PVE
:: Storage
:: path
( $storecfg, $cdrom );
702 # try to convert old style file names to volume IDs
703 sub filename_to_volume_id
{
704 my ( $vmid, $file, $media ) = @_ ;
706 if (!( $file eq 'none' || $file eq 'cdrom' ||
707 $file =~ m
|^ /dev/ .+| || $file =~ m/^([^:]+):(.+)$/ )) {
709 return undef if $file =~ m
|/|;
711 if ( $media && $media eq 'cdrom' ) {
712 $file = "local:iso/ $file " ;
714 $file = "local: $vmid/$file " ;
721 sub verify_media_type
{
722 my ( $opt, $vtype, $media ) = @_ ;
727 if ( $media eq 'disk' ) {
729 } elsif ( $media eq 'cdrom' ) {
732 die "internal error" ;
735 return if ( $vtype eq $etype );
737 raise_param_exc
({ $opt => "unexpected media type ( $vtype != $etype )" });
740 sub cleanup_drive_path
{
741 my ( $opt, $storecfg, $drive ) = @_ ;
743 # try to convert filesystem paths to volume IDs
745 if (( $drive ->{ file
} !~ m/^(cdrom|none)$/ ) &&
746 ( $drive ->{ file
} !~ m
|^ /dev/ .+|) &&
747 ( $drive ->{ file
} !~ m/^([^:]+):(.+)$/ ) &&
748 ( $drive ->{ file
} !~ m/^\d+$/ )) {
749 my ( $vtype, $volid ) = PVE
:: Storage
:: path_to_volume_id
( $storecfg, $drive ->{ file
});
750 raise_param_exc
({ $opt => "unable to associate path ' $drive ->{file}' to any storage" }) if ! $vtype ;
751 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $vtype eq 'iso' ;
752 verify_media_type
( $opt, $vtype, $drive ->{ media
});
753 $drive ->{ file
} = $volid ;
756 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $drive ->{ file
} =~ m/^(cdrom|none)$/ ;
759 sub create_conf_nolock
{
760 my ( $vmid, $settings ) = @_ ;
762 my $filename = config_file
( $vmid );
764 die "configuration file ' $filename ' already exists \n " if - f
$filename ;
766 my $defaults = load_defaults
();
768 $settings ->{ name
} = "vm $vmid " if ! $settings ->{ name
};
769 $settings ->{ memory
} = $defaults ->{ memory
} if ! $settings ->{ memory
};
772 foreach my $opt ( keys %$settings ) {
773 next if ! $confdesc ->{ $opt };
775 my $value = $settings ->{ $opt };
778 $data .= " $opt : $value\n " ;
781 PVE
:: Tools
:: file_set_contents
( $filename, $data );
784 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
785 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
786 # [,aio=native|threads]
789 my ( $key, $data ) = @_ ;
793 # $key may be undefined - used to verify JSON parameters
794 if (! defined ( $key )) {
795 $res ->{ interface
} = 'unknown' ; # should not harm when used to verify parameters
797 } elsif ( $key =~ m/^([^\d]+)(\d+)$/ ) {
798 $res ->{ interface
} = $1 ;
804 foreach my $p ( split ( /,/ , $data )) {
805 next if $p =~ m/^\s*$/ ;
807 if ( $p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio)=(.+)$/ ) {
808 my ( $k, $v ) = ( $1, $2 );
810 $k = 'file' if $k eq 'volume' ;
812 return undef if defined $res ->{ $k };
816 if (! $res ->{ file
} && $p !~ m/=/ ) {
824 return undef if ! $res ->{ file
};
826 return undef if $res ->{ cache
} &&
827 $res ->{ cache
} !~ m/^(off|none|writethrough|writeback|unsafe)$/ ;
828 return undef if $res ->{ snapshot
} && $res ->{ snapshot
} !~ m/^(on|off)$/ ;
829 return undef if $res ->{ cyls
} && $res ->{ cyls
} !~ m/^\d+$/ ;
830 return undef if $res ->{ heads
} && $res ->{ heads
} !~ m/^\d+$/ ;
831 return undef if $res ->{ secs
} && $res ->{ secs
} !~ m/^\d+$/ ;
832 return undef if $res ->{ media
} && $res ->{ media
} !~ m/^(disk|cdrom)$/ ;
833 return undef if $res ->{ trans
} && $res ->{ trans
} !~ m/^(none|lba|auto)$/ ;
834 return undef if $res ->{ format
} && $res ->{ format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/ ;
835 return undef if $res ->{ rerror
} && $res ->{ rerror
} !~ m/^(ignore|report|stop)$/ ;
836 return undef if $res ->{ werror
} && $res ->{ werror
} !~ m/^(enospc|ignore|report|stop)$/ ;
837 return undef if $res ->{ backup
} && $res ->{ backup
} !~ m/^(yes|no)$/ ;
838 return undef if $res ->{ aio
} && $res ->{ aio
} !~ m/^(native|threads)$/ ;
840 if ( $res ->{ media
} && ( $res ->{ media
} eq 'cdrom' )) {
841 return undef if $res ->{ snapshot
} || $res ->{ trans
} || $res ->{ format
};
842 return undef if $res ->{ heads
} || $res ->{ secs
} || $res ->{ cyls
};
843 return undef if $res ->{ interface
} eq 'virtio' ;
846 # rerror does not work with scsi drives
847 if ( $res ->{ rerror
}) {
848 return undef if $res ->{ interface
} eq 'scsi' ;
854 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio) ;
857 my ( $vmid, $drive ) = @_ ;
860 foreach my $o ( @qemu_drive_options, 'backup' ) {
861 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
864 return " $drive ->{file} $opts " ;
867 sub print_drivedevice_full
{
868 my ( $storecfg, $vmid, $drive ) = @_ ;
873 if ( $drive ->{ interface
} eq 'virtio' ) {
874 my $pciaddr = print_pci_addr
( " $drive ->{interface} $drive ->{index}" );
875 $device = "virtio-blk-pci,drive=drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index} $pciaddr " ;
876 } elsif ( $drive ->{ interface
} eq 'scsi' ) {
878 my $controller = int ( $drive ->{ index } / $maxdev );
879 my $unit = $drive ->{ index } % $maxdev ;
880 my $devicetype = 'hd' ;
882 if ( drive_is_cdrom
( $drive )) {
885 if ( $drive ->{ file
} =~ m
|^/|) {
886 $path = $drive ->{ file
};
888 $path = PVE
:: Storage
:: path
( $storecfg, $drive ->{ file
});
890 if ( $path =~ m
|^ /dev/ | ) {
891 $devicetype = 'block' ;
895 $device = "scsi- $devicetype,bus =lsi $controller .0,scsi-id= $unit,drive =drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index}" ;
896 } elsif ( $drive ->{ interface
} eq 'ide' ){
898 my $controller = int ( $drive ->{ index } / $maxdev );
899 my $unit = $drive ->{ index } % $maxdev ;
900 my $devicetype = ( $drive ->{ media
} && $drive ->{ media
} eq 'cdrom' ) ?
"cd" : "hd" ;
902 $device = "ide- $devicetype,bus =ide. $controller,unit = $unit,drive =drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index}" ;
903 } elsif ( $drive ->{ interface
} eq 'usb' ) {
905 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
907 die "unsupported interface type" ;
910 $device .= ",bootindex= $drive ->{bootindex}" if $drive ->{ bootindex
};
915 sub print_drive_full
{
916 my ( $storecfg, $vmid, $drive ) = @_ ;
919 foreach my $o ( @qemu_drive_options ) {
920 next if $o eq 'bootindex' ;
921 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
924 # use linux-aio by default (qemu default is threads)
925 $opts .= ",aio=native" if ! $drive ->{ aio
};
928 my $volid = $drive ->{ file
};
929 if ( drive_is_cdrom
( $drive )) {
930 $path = get_iso_path
( $storecfg, $vmid, $volid );
932 if ( $volid =~ m
|^/|) {
935 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
937 if (! $drive ->{ cache
} && ( $path =~ m
|^ /dev/ | || $path =~ m
| \
. raw
$|)) {
938 $opts .= ",cache=none" ;
942 my $pathinfo = $path ?
"file= $path, " : '' ;
944 return "${pathinfo}if=none,id=drive- $drive ->{interface} $drive ->{index} $opts " ;
951 return $drive && $drive ->{ media
} && ( $drive ->{ media
} eq 'cdrom' );
958 return undef if ! $value ;
962 if ( $value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/ ) {
963 $res ->{ pciid
} = $value ;
971 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
977 foreach my $kvp ( split ( /,/ , $data )) {
979 if ( $kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i ) {
981 my $mac = uc ( $3 ) || PVE
:: Tools
:: random_ether_addr
();
982 $res ->{ model
} = $model ;
983 $res ->{ macaddr
} = $mac ;
984 } elsif ( $kvp =~ m/^bridge=(\S+)$/ ) {
986 } elsif ( $kvp =~ m/^rate=(\d+(\.\d+)?)$/ ) {
994 return undef if ! $res ->{ model
};
1002 my $res = " $net ->{model}" ;
1003 $res .= "= $net ->{macaddr}" if $net ->{ macaddr
};
1004 $res .= ",bridge= $net ->{bridge}" if $net ->{ bridge
};
1005 $res .= ",rate= $net ->{rate}" if $net ->{ rate
};
1010 sub add_random_macs
{
1011 my ( $settings ) = @_ ;
1013 foreach my $opt ( keys %$settings ) {
1014 next if $opt !~ m/^net(\d+)$/ ;
1015 my $net = parse_net
( $settings ->{ $opt });
1017 $settings ->{ $opt } = print_net
( $net );
1021 sub add_unused_volume
{
1022 my ( $config, $volid, $vmid ) = @_ ;
1025 for ( my $ind = $MAX_UNUSED_DISKS - 1 ; $ind >= 0 ; $ind --) {
1026 my $test = "unused $ind " ;
1027 if ( my $vid = $config ->{ $test }) {
1028 return if $vid eq $volid ; # do not add duplicates
1034 die "To many unused volume - please delete them first. \n " if ! $key ;
1036 PVE
:: QemuServer
:: change_config_nolock
( $vmid, { $key => $volid }, {}, 1 );
1037 $config ->{ $key } = $volid ;
1040 # fixme: remove all thos $noerr parameters?
1042 PVE
:: JSONSchema
:: register_format
( 'pve-qm-bootdisk' , \
& verify_bootdisk
);
1043 sub verify_bootdisk
{
1044 my ( $value, $noerr ) = @_ ;
1046 return $value if valid_drivename
( $value );
1048 return undef if $noerr ;
1050 die "invalid boot disk ' $value ' \n " ;
1053 PVE
:: JSONSchema
:: register_format
( 'pve-qm-net' , \
& verify_net
);
1055 my ( $value, $noerr ) = @_ ;
1057 return $value if parse_net
( $value );
1059 return undef if $noerr ;
1061 die "unable to parse network options \n " ;
1064 PVE
:: JSONSchema
:: register_format
( 'pve-qm-drive' , \
& verify_drive
);
1066 my ( $value, $noerr ) = @_ ;
1068 return $value if parse_drive
( undef , $value );
1070 return undef if $noerr ;
1072 die "unable to parse drive options \n " ;
1075 PVE
:: JSONSchema
:: register_format
( 'pve-qm-hostpci' , \
& verify_hostpci
);
1076 sub verify_hostpci
{
1077 my ( $value, $noerr ) = @_ ;
1079 return $value if parse_hostpci
( $value );
1081 return undef if $noerr ;
1083 die "unable to parse pci id \n " ;
1086 PVE
:: JSONSchema
:: register_format
( 'pve-qm-watchdog' , \
& verify_watchdog
);
1087 sub verify_watchdog
{
1088 my ( $value, $noerr ) = @_ ;
1090 return $value if parse_watchdog
( $value );
1092 return undef if $noerr ;
1094 die "unable to parse watchdog options \n " ;
1097 sub parse_watchdog
{
1100 return undef if ! $value ;
1104 foreach my $p ( split ( /,/ , $value )) {
1105 next if $p =~ m/^\s*$/ ;
1107 if ( $p =~ m/^(model=)?(i6300esb|ib700)$/ ) {
1109 } elsif ( $p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/ ) {
1110 $res ->{ action
} = $2 ;
1119 sub parse_usb_device
{
1122 return undef if ! $value ;
1124 my @dl = split ( /,/ , $value );
1128 foreach my $v ( @dl ) {
1129 if ( $v =~ m/^host=([0-9A-Fa-f]{4}):([0-9A-Fa-f]{4})$/ ) {
1131 $res ->{ vendorid
} = $1 ;
1132 $res ->{ productid
} = $2 ;
1133 } elsif ( $v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/ ) {
1135 $res ->{ hostbus
} = $1 ;
1136 $res ->{ hostport
} = $2 ;
1141 return undef if ! $found ;
1146 PVE
:: JSONSchema
:: register_format
( 'pve-qm-usb-device' , \
& verify_usb_device
);
1147 sub verify_usb_device
{
1148 my ( $value, $noerr ) = @_ ;
1150 return $value if parse_usb_device
( $value );
1152 return undef if $noerr ;
1154 die "unable to parse usb device \n " ;
1157 # add JSON properties for create and set function
1158 sub json_config_properties
{
1161 foreach my $opt ( keys %$confdesc ) {
1162 $prop ->{ $opt } = $confdesc ->{ $opt };
1169 my ( $key, $value ) = @_ ;
1171 die "unknown setting ' $key ' \n " if ! $confdesc ->{ $key };
1173 my $type = $confdesc ->{ $key }->{ type
};
1175 if (! defined ( $value )) {
1176 die "got undefined value \n " ;
1179 if ( $value =~ m/[\n\r]/ ) {
1180 die "property contains a line feed \n " ;
1183 if ( $type eq 'boolean' ) {
1184 return 1 if ( $value eq '1' ) || ( $value =~ m/^(on|yes|true)$/i );
1185 return 0 if ( $value eq '0' ) || ( $value =~ m/^(off|no|false)$/i );
1186 die "type check ('boolean') failed - got ' $value ' \n " ;
1187 } elsif ( $type eq 'integer' ) {
1188 return int ( $1 ) if $value =~ m/^(\d+)$/ ;
1189 die "type check ('integer') failed - got ' $value ' \n " ;
1190 } elsif ( $type eq 'string' ) {
1191 if ( my $fmt = $confdesc ->{ $key }->{ format
}) {
1192 if ( $fmt eq 'pve-qm-drive' ) {
1193 # special case - we need to pass $key to parse_drive()
1194 my $drive = parse_drive
( $key, $value );
1195 return $value if $drive ;
1196 die "unable to parse drive options \n " ;
1198 PVE
:: JSONSchema
:: check_format
( $fmt, $value );
1201 $value =~ s/^\"(.*)\"$/$1/ ;
1204 die "internal error"
1209 my ( $vmid, $code, @param ) = @_ ;
1211 my $filename = config_file_lock
( $vmid );
1213 my $res = lock_file
( $filename, 10 , $code, @param );
1220 sub cfs_config_path
{
1221 my ( $vmid, $node ) = @_ ;
1223 $node = $nodename if ! $node ;
1224 return "nodes/ $node/qemu -server/ $vmid .conf" ;
1227 sub check_iommu_support
{
1228 #fixme : need to check IOMMU support
1229 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1237 my ( $vmid, $node ) = @_ ;
1239 my $cfspath = cfs_config_path
( $vmid, $node );
1240 return "/etc/pve/ $cfspath " ;
1243 sub config_file_lock
{
1246 return " $lock_dir/lock - $vmid .conf" ;
1252 my $conf = config_file
( $vmid );
1253 utime undef , undef , $conf ;
1257 my ( $storecfg, $vmid, $settings, $conf, $default_storage ) = @_ ;
1262 foreach_drive
( $settings, sub {
1263 my ( $ds, $disk ) = @_ ;
1265 return if drive_is_cdrom
( $disk );
1267 my $file = $disk ->{ file
};
1269 if ( $file =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/ ) {
1270 my $storeid = $2 || $default_storage ;
1272 my $defformat = PVE
:: Storage
:: storage_default_format
( $storecfg, $storeid );
1273 my $fmt = $disk ->{ format
} || $defformat ;
1274 syslog
( 'info' , "VM $vmid creating new disk - size is $size GB" );
1276 my $volid = PVE
:: Storage
:: vdisk_alloc
( $storecfg, $storeid, $vmid,
1277 $fmt, undef , $size*1024*1024 );
1279 $disk ->{ file
} = $volid ;
1280 delete $disk ->{ format
}; # no longer needed
1281 push @$vollist, $volid ;
1282 $settings ->{ $ds } = PVE
:: QemuServer
:: print_drive
( $vmid, $disk );
1285 if ( $disk ->{ file
} =~ m
|^ /dev/ .+|) {
1286 $path = $disk ->{ file
};
1288 $path = PVE
:: Storage
:: path
( $storecfg, $disk ->{ file
});
1290 if (!(- f
$path || - b
$path )) {
1291 die "image ' $path ' does not exists \n " ;
1300 syslog
( 'err' , "VM $vmid creating disks failed" );
1301 foreach my $volid ( @$vollist ) {
1302 eval { PVE
:: Storage
:: vdisk_free
( $storecfg, $volid ); };
1312 my ( $storecfg, $vmid, $keep_empty_config ) = @_ ;
1314 my $conffile = config_file
( $vmid );
1316 my $conf = load_config
( $vmid );
1320 # only remove disks owned by this VM
1321 foreach_drive
( $conf, sub {
1322 my ( $ds, $drive ) = @_ ;
1324 return if drive_is_cdrom
( $drive );
1326 my $volid = $drive ->{ file
};
1327 return if ! $volid || $volid =~ m
|^/|;
1329 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1330 return if ! $path || ! $owner || ( $owner != $vmid );
1332 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1335 if ( $keep_empty_config ) {
1336 PVE
:: Tools
:: file_set_contents
( $conffile, "memory: 128 \n " );
1341 # also remove unused disk
1343 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid );
1346 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1347 my ( $volid, $sid, $volname, $d ) = @_ ;
1348 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1358 sub load_diskinfo_old
{
1359 my ( $storecfg, $vmid, $conf ) = @_ ;
1365 foreach_drive
( $conf, sub {
1370 return if drive_is_cdrom
( $di );
1372 if ( $di ->{ file
} =~ m
|^ /dev/ .+|) {
1373 $info ->{ $di ->{ file
}}->{ size
} = PVE
:: Storage
:: file_size_info
( $di ->{ file
});
1375 push @$vollist, $di ->{ file
};
1380 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid, $vollist );
1382 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1383 my ( $volid, $sid, $volname, $d ) = @_ ;
1384 $info ->{ $volid } = $d ;
1389 foreach my $ds ( keys %$res ) {
1390 my $di = $res ->{ $ds };
1392 $res ->{ $ds }->{ disksize
} = $info ->{ $di ->{ file
}} ?
1393 $info ->{ $di ->{ file
}}->{ size
} / ( 1024 * 1024 ) : 0 ;
1402 my $cfspath = cfs_config_path
( $vmid );
1404 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath );
1406 die "no such VM (' $vmid ') \n " if ! defined ( $conf );
1411 sub parse_vm_config
{
1412 my ( $filename, $raw ) = @_ ;
1414 return undef if ! defined ( $raw );
1417 digest
=> Digest
:: SHA1
:: sha1_hex
( $raw ),
1420 $filename =~ m
| /qemu-server/ ( \d
+) \
. conf
$|
1421 || die "got strange filename ' $filename '" ;
1425 while ( $raw && $raw =~ s/^(.*?)(\n|$)// ) {
1428 next if $line =~ m/^\#/ ;
1430 next if $line =~ m/^\s*$/ ;
1432 if ( $line =~ m/^(description):\s*(.*\S)\s*$/ ) {
1434 my $value = PVE
:: Tools
:: decode_text
( $2 );
1435 $res ->{ $key } = $value ;
1436 } elsif ( $line =~ m/^(args):\s*(.*\S)\s*$/ ) {
1439 $res ->{ $key } = $value ;
1440 } elsif ( $line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/ ) {
1443 eval { $value = check_type
( $key, $value ); };
1445 warn "vm $vmid - unable to parse value of ' $key ' - $@ " ;
1447 my $fmt = $confdesc ->{ $key }->{ format
};
1448 if ( $fmt && $fmt eq 'pve-qm-drive' ) {
1449 my $v = parse_drive
( $key, $value );
1450 if ( my $volid = filename_to_volume_id
( $vmid, $v ->{ file
}, $v ->{ media
})) {
1451 $v ->{ file
} = $volid ;
1452 $value = print_drive
( $vmid, $v );
1454 warn "vm $vmid - unable to parse value of ' $key ' \n " ;
1459 if ( $key eq 'cdrom' ) {
1460 $res ->{ ide2
} = $value ;
1462 $res ->{ $key } = $value ;
1468 # convert old smp to sockets
1469 if ( $res ->{ smp
} && ! $res ->{ sockets
}) {
1470 $res ->{ sockets
} = $res ->{ smp
};
1478 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1480 lock_config
( $vmid, & change_config_nolock
, $settings, $unset, $skiplock );
1483 sub change_config_nolock
{
1484 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1488 $unset ->{ ide2
} = $unset ->{ cdrom
} if $unset ->{ cdrom
};
1490 check_lock
( $settings ) if ! $skiplock ;
1492 # we do not use 'smp' any longer
1493 if ( $settings ->{ sockets
}) {
1495 } elsif ( $settings ->{ smp
}) {
1496 $settings ->{ sockets
} = $settings ->{ smp
};
1500 my $new_volids = {};
1502 foreach my $key ( keys %$settings ) {
1503 next if $key eq 'digest' ;
1504 my $value = $settings ->{ $key };
1505 if ( $key eq 'description' ) {
1506 $value = PVE
:: Tools
:: encode_text
( $value );
1508 eval { $value = check_type
( $key, $value ); };
1509 die "unable to parse value of ' $key ' - $@ " if $@ ;
1510 if ( $key eq 'cdrom' ) {
1511 $res ->{ ide2
} = $value ;
1513 $res ->{ $key } = $value ;
1515 if ( valid_drivename
( $key )) {
1516 my $drive = PVE
:: QemuServer
:: parse_drive
( $key, $value );
1517 $new_volids ->{ $drive ->{ file
}} = 1 if $drive && $drive ->{ file
};
1521 my $filename = config_file
( $vmid );
1522 my $tmpfn = " $filename . $$ .tmp" ;
1524 my $fh = new IO
:: File
( $filename, "r" ) ||
1525 die "unable to read config for VM $vmid\n " ;
1527 my $werror = "unable to write config for VM $vmid\n " ;
1529 my $out = new IO
:: File
( $tmpfn, "w" ) || die $werror ;
1535 while ( my $line = < $fh >) {
1537 if (( $line =~ m/^\#/ ) || ( $line =~ m/^\s*$/ )) {
1538 die $werror unless print $out $line ;
1542 if ( $line =~ m/^([a-z][a-z_]*\d*):\s*(.*\S)\s*$/ ) {
1546 # remove 'unusedX' settings if we re-add a volume
1547 next if $key =~ m/^unused/ && $new_volids ->{ $value };
1549 # convert 'smp' to 'sockets'
1550 $key = 'sockets' if $key eq 'smp' ;
1552 next if $done ->{ $key };
1555 if ( defined ( $res ->{ $key })) {
1556 $value = $res ->{ $key };
1557 delete $res ->{ $key };
1559 if (! defined ( $unset ->{ $key })) {
1560 die $werror unless print $out " $key : $value\n " ;
1566 die "unable to parse config file: $line\n " ;
1569 foreach my $key ( keys %$res ) {
1571 if (! defined ( $unset ->{ $key })) {
1572 die $werror unless print $out " $key : $res ->{ $key } \n " ;
1587 if (! $out -> close ()) {
1588 $err = "close failed - $!\n " ;
1593 if (! rename ( $tmpfn, $filename )) {
1594 $err = "rename failed - $!\n " ;
1604 # we use static defaults from our JSON schema configuration
1605 foreach my $key ( keys %$confdesc ) {
1606 if ( defined ( my $default = $confdesc ->{ $key }->{ default })) {
1607 $res ->{ $key } = $default ;
1611 my $conf = PVE
:: Cluster
:: cfs_read_file
( 'datacenter.cfg' );
1612 $res ->{ keyboard
} = $conf ->{ keyboard
} if $conf ->{ keyboard
};
1618 my $vmlist = PVE
:: Cluster
:: get_vmlist
();
1620 return $res if ! $vmlist || ! $vmlist ->{ ids
};
1621 my $ids = $vmlist ->{ ids
};
1623 foreach my $vmid ( keys %$ids ) {
1624 my $d = $ids ->{ $vmid };
1625 next if ! $d ->{ node
} || $d ->{ node
} ne $nodename ;
1626 next if ! $d ->{ type
} || $d ->{ type
} ne 'qemu' ;
1627 $res ->{ $vmid }->{ exists } = 1 ;
1632 # test if VM uses local resources (to prevent migration)
1633 sub check_local_resources
{
1634 my ( $conf, $noerr ) = @_ ;
1638 $loc_res = 1 if $conf ->{ hostusb
}; # old syntax
1639 $loc_res = 1 if $conf ->{ hostpci
}; # old syntax
1641 foreach my $k ( keys %$conf ) {
1642 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/ ;
1645 die "VM uses local resources \n " if $loc_res && ! $noerr ;
1653 die "VM is locked ( $conf ->{lock}) \n " if $conf ->{ lock };
1657 my ( $pidfile, $pid ) = @_ ;
1659 my $fh = IO
:: File-
> new ( "/proc/ $pid/cmdline " , "r" );
1663 return undef if ! $line ;
1664 my @param = split ( /\0/ , $line );
1666 my $cmd = $param [ 0 ];
1667 return if ! $cmd || ( $cmd !~ m
| kvm
$|);
1669 for ( my $i = 0 ; $i < scalar ( @param ); $i++ ) {
1672 if (( $p eq '-pidfile' ) || ( $p eq '--pidfile' )) {
1673 my $p = $param [ $i+1 ];
1674 return 1 if $p && ( $p eq $pidfile );
1683 my ( $vmid, $nocheck ) = @_ ;
1685 my $filename = config_file
( $vmid );
1687 die "unable to find configuration file for VM $vmid - no such machine \n "
1688 if ! $nocheck && ! - f
$filename ;
1690 my $pidfile = pidfile_name
( $vmid );
1692 if ( my $fd = IO
:: File-
> new ( "< $pidfile " )) {
1697 my $mtime = $st -> mtime ;
1698 if ( $mtime > time ()) {
1699 warn "file ' $filename ' modified in future \n " ;
1702 if ( $line =~ m/^(\d+)$/ ) {
1704 if ( check_cmdline
( $pidfile, $pid )) {
1705 if ( my $pinfo = PVE
:: ProcFSTools
:: check_process_running
( $pid )) {
1717 my $vzlist = config_list
();
1719 my $fd = IO
:: Dir-
> new ( $var_run_tmpdir ) || return $vzlist ;
1721 while ( defined ( my $de = $fd -> read )) {
1722 next if $de !~ m/^(\d+)\.pid$/ ;
1724 next if ! defined ( $vzlist ->{ $vmid });
1725 if ( my $pid = check_running
( $vmid )) {
1726 $vzlist ->{ $vmid }->{ pid
} = $pid ;
1733 my $storage_timeout_hash = {};
1736 my ( $storecfg, $conf ) = @_ ;
1738 my $bootdisk = $conf ->{ bootdisk
};
1739 return undef if ! $bootdisk ;
1740 return undef if ! valid_drivename
( $bootdisk );
1742 return undef if ! $conf ->{ $bootdisk };
1744 my $drive = parse_drive
( $bootdisk, $conf ->{ $bootdisk });
1745 return undef if ! defined ( $drive );
1747 return undef if drive_is_cdrom
( $drive );
1749 my $volid = $drive ->{ file
};
1750 return undef if ! $volid ;
1756 if ( $volid =~ m
|^/|) {
1757 $path = $timeoutid = $volid ;
1760 $storeid = $timeoutid = PVE
:: Storage
:: parse_volume_id
( $volid );
1761 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
1769 my $last_timeout = $storage_timeout_hash ->{ $timeoutid };
1770 if ( $last_timeout ) {
1771 if (( time () - $last_timeout ) < 30 ) {
1772 # skip storage with errors
1775 delete $storage_timeout_hash ->{ $timeoutid };
1778 my ( $size, $format, $used );
1780 ( $size, $format, $used ) = PVE
:: Storage
:: file_size_info
( $path, 1 );
1782 if (! defined ( $format )) {
1784 $storage_timeout_hash ->{ $timeoutid } = time ();
1788 return wantarray ?
( $size, $used ) : $size ;
1791 my $last_proc_pid_stat ;
1794 my ( $opt_vmid ) = @_ ;
1798 my $storecfg = PVE
:: Storage
:: config
();
1800 my $list = vzlist
();
1801 my ( $uptime ) = PVE
:: ProcFSTools
:: read_proc_uptime
( 1 );
1803 my $cpucount = $cpuinfo ->{ cpus
} || 1 ;
1805 foreach my $vmid ( keys %$list ) {
1806 next if $opt_vmid && ( $vmid ne $opt_vmid );
1808 my $cfspath = cfs_config_path
( $vmid );
1809 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath ) || {};
1812 $d ->{ pid
} = $list ->{ $vmid }->{ pid
};
1814 # fixme: better status?
1815 $d ->{ status
} = $list ->{ $vmid }->{ pid
} ?
'running' : 'stopped' ;
1817 my ( $size, $used ) = disksize
( $storecfg, $conf );
1818 if ( defined ( $size ) && defined ( $used )) {
1820 $d ->{ maxdisk
} = $size ;
1826 $d ->{ cpus
} = ( $conf ->{ sockets
} || 1 ) * ( $conf ->{ cores
} || 1 );
1827 $d ->{ cpus
} = $cpucount if $d ->{ cpus
} > $cpucount ;
1829 $d ->{ name
} = $conf ->{ name
} || "VM $vmid " ;
1830 $d ->{ maxmem
} = $conf ->{ memory
} ?
$conf ->{ memory
}*( 1024 * 1024 ) : 0 ;
1840 $d ->{ diskwrite
} = 0 ;
1845 my $netdev = PVE
:: ProcFSTools
:: read_proc_net_dev
();
1846 foreach my $dev ( keys %$netdev ) {
1847 next if $dev !~ m/^tap([1-9]\d*)i/ ;
1849 my $d = $res ->{ $vmid };
1852 $d ->{ netout
} += $netdev ->{ $dev }->{ receive
};
1853 $d ->{ netin
} += $netdev ->{ $dev }->{ transmit
};
1856 my $ctime = gettimeofday
;
1858 foreach my $vmid ( keys %$list ) {
1860 my $d = $res ->{ $vmid };
1861 my $pid = $d ->{ pid
};
1864 if ( my $fh = IO
:: File-
> new ( "/proc/ $pid/io " , "r" )) {
1866 while ( defined ( my $line = < $fh >)) {
1867 if ( $line =~ m/^([rw]char):\s+(\d+)$/ ) {
1872 $d ->{ diskread
} = $data ->{ rchar
} || 0 ;
1873 $d ->{ diskwrite
} = $data ->{ wchar
} || 0 ;
1876 my $pstat = PVE
:: ProcFSTools
:: read_proc_pid_stat
( $pid );
1877 next if ! $pstat ; # not running
1879 my $used = $pstat ->{ utime } + $pstat ->{ stime
};
1881 $d ->{ uptime
} = int (( $uptime - $pstat ->{ starttime
})/ $cpuinfo ->{ user_hz
});
1883 if ( $pstat ->{ vsize
}) {
1884 $d ->{ mem
} = int (( $pstat ->{ rss
}/ $pstat ->{ vsize
})* $d ->{ maxmem
});
1887 my $old = $last_proc_pid_stat ->{ $pid };
1889 $last_proc_pid_stat ->{ $pid } = {
1897 my $dtime = ( $ctime - $old ->{ time }) * $cpucount * $cpuinfo ->{ user_hz
};
1899 if ( $dtime > 1000 ) {
1900 my $dutime = $used - $old ->{ used
};
1902 $d ->{ cpu
} = (( $dutime/$dtime )* $cpucount ) / $d ->{ cpus
};
1903 $last_proc_pid_stat ->{ $pid } = {
1909 $d ->{ cpu
} = $old ->{ cpu
};
1917 my ( $conf, $func ) = @_ ;
1919 foreach my $ds ( keys %$conf ) {
1920 next if ! valid_drivename
( $ds );
1922 my $drive = parse_drive
( $ds, $conf ->{ $ds });
1925 & $func ( $ds, $drive );
1929 sub config_to_command
{
1930 my ( $storecfg, $vmid, $conf, $defaults, $migrate_uri ) = @_ ;
1934 my $kvmver = kvm_user_version
();
1935 my $vernum = 0 ; # unknown
1936 if ( $kvmver =~ m/^(\d+)\.(\d+)$/ ) {
1937 $vernum = $1*1000000+$2*1000 ;
1938 } elsif ( $kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/ ) {
1939 $vernum = $1*1000000+$2*1000+$3 ;
1942 die "detected old qemu-kvm binary ( $kvmver ) \n " if $vernum < 15000 ;
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 ;
1966 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1967 next if ! $conf ->{ "usb $i " };
1970 # include usb device config
1971 push @$cmd, '-readconfig' , '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2 ;
1973 # enable absolute mouse coordinates (needed by vnc)
1974 my $tablet = defined ( $conf ->{ tablet
}) ?
$conf ->{ tablet
} : $defaults ->{ tablet
};
1977 push @$cmd, '-device' , 'usb-tablet,bus=ehci.0,port=6' ;
1979 push @$cmd, '-usbdevice' , 'tablet' ;
1984 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
1985 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
1987 $pciaddr = print_pci_addr
( "hostpci $i " );
1988 push @$cmd, '-device' , "pci-assign,host= $d ->{pciid},id=hostpci $i$pciaddr " ;
1992 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1993 my $d = parse_usb_device
( $conf ->{ "usb $i " });
1995 if ( $d ->{ vendorid
} && $d ->{ productid
}) {
1996 push @$cmd, '-device' , "usb-host,vendorid= $d ->{vendorid},productid= $d ->{productid}" ;
1997 } elsif ( defined ( $d ->{ hostbus
}) && defined ( $d ->{ hostport
})) {
1998 push @$cmd, '-device' , "usb-host,hostbus= $d ->{hostbus},hostport= $d ->{hostport}" ;
2003 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
2004 if ( my $path = $conf ->{ "serial $i " }) {
2005 die "no such serial device \n " if ! - c
$path ;
2006 push @$cmd, '-chardev' , "tty,id=serial $i,path = $path " ;
2007 push @$cmd, '-device' , "isa-serial,chardev=serial $i " ;
2012 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
2013 if ( my $path = $conf ->{ "parallel $i " }) {
2014 die "no such parallel device \n " if ! - c
$path ;
2015 push @$cmd, '-chardev' , "parport,id=parallel $i,path = $path " ;
2016 push @$cmd, '-device' , "isa-parallel,chardev=parallel $i " ;
2020 my $vmname = $conf ->{ name
} || "vm $vmid " ;
2022 push @$cmd, '-name' , $vmname ;
2025 $sockets = $conf ->{ smp
} if $conf ->{ smp
}; # old style - no longer iused
2026 $sockets = $conf ->{ sockets
} if $conf ->{ sockets
};
2028 my $cores = $conf ->{ cores
} || 1 ;
2030 push @$cmd, '-smp' , "sockets= $sockets,cores = $cores " ;
2032 push @$cmd, '-cpu' , $conf ->{ cpu
} if $conf ->{ cpu
};
2034 push @$cmd, '-nodefaults' ;
2036 my $bootorder = $conf ->{ boot
} || $confdesc ->{ boot
}->{ default };
2038 my $bootindex_hash = {};
2040 foreach my $o ( split ( // , $bootorder )) {
2041 $bootindex_hash ->{ $o } = $i*100 ;
2045 push @$cmd, '-boot' , "menu=on" ;
2047 push @$cmd, '-no-acpi' if defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 ;
2049 push @$cmd, '-no-reboot' if defined ( $conf ->{ reboot
}) && $conf ->{ reboot
} == 0 ;
2051 my $vga = $conf ->{ vga
};
2053 if ( $conf ->{ ostype
} && ( $conf ->{ ostype
} eq 'win7' || $conf ->{ ostype
} eq 'w2k8' )) {
2060 push @$cmd, '-vga' , $vga if $vga ; # for kvm 77 and later
2063 my $tdf = defined ( $conf ->{ tdf
}) ?
$conf ->{ tdf
} : $defaults ->{ tdf
};
2064 push @$cmd, '-tdf' if $tdf ;
2066 my $nokvm = defined ( $conf ->{ kvm
}) && $conf ->{ kvm
} == 0 ?
1 : 0 ;
2068 if ( my $ost = $conf ->{ ostype
}) {
2069 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2071 if ( $ost =~ m/^w/ ) { # windows
2072 push @$cmd, '-localtime' if ! defined ( $conf ->{ localtime });
2074 # use rtc-td-hack when acpi is enabled
2075 if (!( defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 )) {
2076 push @$cmd, '-rtc-td-hack' ;
2087 push @$cmd, '-no-kvm' ;
2089 die "No accelerator found! \n " if ! $cpuinfo ->{ hvm
};
2092 push @$cmd, '-localtime' if $conf ->{ localtime };
2094 push @$cmd, '-startdate' , $conf ->{ startdate
} if $conf ->{ startdate
};
2096 push @$cmd, '-S' if $conf ->{ freeze
};
2098 # set keyboard layout
2099 my $kb = $conf ->{ keyboard
} || $defaults ->{ keyboard
};
2100 push @$cmd, '-k' , $kb if $kb ;
2103 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2104 #push @$cmd, '-soundhw', 'es1370';
2105 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2106 $pciaddr = print_pci_addr
( "balloon0" );
2107 push @$cmd, '-device' , "virtio-balloon-pci,id=balloon0 $pciaddr " if $conf ->{ balloon
};
2109 if ( $conf ->{ watchdog
}) {
2110 my $wdopts = parse_watchdog
( $conf ->{ watchdog
});
2111 $pciaddr = print_pci_addr
( "watchdog" );
2112 my $watchdog = $wdopts ->{ model
} || 'i6300esb' ;
2113 push @$cmd, '-device' , " $watchdog$pciaddr " ;
2114 push @$cmd, '-watchdog-action' , $wdopts ->{ action
} if $wdopts ->{ action
};
2118 my $scsicontroller = {};
2120 foreach_drive
( $conf, sub {
2121 my ( $ds, $drive ) = @_ ;
2123 if ( PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
}, 1 )) {
2124 push @$vollist, $drive ->{ file
};
2127 $use_virtio = 1 if $ds =~ m/^virtio/ ;
2129 if ( drive_is_cdrom
( $drive )) {
2130 if ( $bootindex_hash ->{ d
}) {
2131 $drive ->{ bootindex
} = $bootindex_hash ->{ d
};
2132 $bootindex_hash ->{ d
} += 1 ;
2135 if ( $bootindex_hash ->{ c
}) {
2136 $drive ->{ bootindex
} = $bootindex_hash ->{ c
} if $conf ->{ bootdisk
} && ( $conf ->{ bootdisk
} eq $ds );
2137 $bootindex_hash ->{ c
} += 1 ;
2141 if ( $drive ->{ interface
} eq 'scsi' ) {
2143 my $controller = int ( $drive ->{ index } / $maxdev );
2144 $pciaddr = print_pci_addr
( "lsi $controller " );
2145 push @$cmd, '-device' , "lsi,id=lsi $controller$pciaddr " if ! $scsicontroller ->{ $controller };
2146 $scsicontroller ->{ $controller }= 1 ;
2149 push @$cmd, '-drive' , print_drive_full
( $storecfg, $vmid, $drive );
2150 push @$cmd, '-device' , print_drivedevice_full
( $storecfg,$vmid, $drive );
2153 push @$cmd, '-m' , $conf ->{ memory
} || $defaults ->{ memory
};
2157 foreach my $k ( sort keys %$conf ) {
2158 next if $k !~ m/^net(\d+)$/ ;
2161 die "got strange net id ' $i ' \n " if $i >= ${ MAX_NETS
};
2163 if ( $conf ->{ "net $i " } && ( my $net = parse_net
( $conf ->{ "net $i " }))) {
2167 my $ifname = "tap${vmid}i $i " ;
2169 # kvm uses TUNSETIFF ioctl, and that limits ifname length
2170 die "interface name ' $ifname ' is too long (max 15 character) \n "
2171 if length ( $ifname ) >= 16 ;
2173 my $device = $net ->{ model
};
2174 my $vhostparam = '' ;
2175 if ( $net ->{ model
} eq 'virtio' ) {
2177 $device = 'virtio-net-pci' ;
2178 $vhostparam = ',vhost=on' if $kernel_has_vhost_net ;
2181 if ( $net ->{ bridge
}) {
2182 push @$cmd, '-netdev' , "type=tap,id=${k},ifname=${ifname},script=/var/lib/qemu-server/pve-bridge $vhostparam " ;
2184 push @$cmd, '-netdev' , "type=user,id=${k},hostname= $vmname " ;
2187 # qemu > 0.15 always try to boot from network - we disable that by
2188 # not loading the pxe rom file
2189 my $extra = ( $bootorder !~ m/n/ ) ?
"romfile=," : '' ;
2190 $pciaddr = print_pci_addr
( "${k}" );
2191 my $tmpstr = " $device,$ {extra}mac= $net ->{macaddr},netdev=${k} $pciaddr " ;
2192 if ( my $bootindex = $bootindex_hash ->{ n
}) {
2193 $tmpstr .= ",bootindex= $bootindex " ;
2194 $bootindex_hash ->{ n
} += 1 ;
2196 push @$cmd, '-device' , $tmpstr ;
2200 push @$cmd, '-net' , 'none' if ! $foundnet ;
2202 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2203 # when the VM uses virtio devices.
2204 if (! $use_virtio && $have_ovz ) {
2206 my $cpuunits = defined ( $conf ->{ cpuunits
}) ?
2207 $conf ->{ cpuunits
} : $defaults ->{ cpuunits
};
2209 push @$cmd, '-cpuunits' , $cpuunits if $cpuunits ;
2211 # fixme: cpulimit is currently ignored
2212 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2216 if ( $conf ->{ args
}) {
2217 my $aa = PVE
:: Tools
:: split_args
( $conf ->{ args
});
2221 return wantarray ?
( $cmd, $vollist ) : $cmd ;
2226 return "${var_run_tmpdir}/ $vmid .vnc" ;
2229 sub monitor_socket
{
2231 return "${var_run_tmpdir}/ $vmid .mon" ;
2236 return "${var_run_tmpdir}/ $vmid .pid" ;
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" ;
2258 sub vm_devices_list
{
2261 my $res = vm_monitor_command
( $vmid, "info pci" );
2263 my @lines = split ( " \n " , $res );
2269 foreach my $line ( @lines ) {
2271 if ( $line =~ m/^Bus (\d+), device (\d+), function (\d+):$/ ) {
2275 if ( $line =~ m/^id "([a-z][a-z_\-]*\d*)"$/ ) {
2277 $devices ->{ $id }->{ bus
}= $bus ;
2278 $devices ->{ $id }->{ addr
}= $addr ;
2286 my ( $storecfg, $conf, $vmid, $deviceid, $device ) = @_ ;
2287 return 1 if ! check_running
( $vmid ) || ! $conf ->{ hotplug
} || $conf ->{ $deviceid };
2289 if ( $deviceid =~ m/^(virtio)(\d+)$/ ) {
2290 return undef if ! qemu_driveadd
( $storecfg, $vmid, $device );
2291 my $devicefull = print_drivedevice_full
( $storecfg, $vmid, $device );
2292 qemu_deviceadd
( $vmid, $devicefull );
2293 if (! qemu_deviceaddverify
( $vmid, $deviceid )) {
2294 qemu_drivedel
( $vmid, $deviceid );
2299 if ( $deviceid =~ m/^(lsi)(\d+)$/ ) {
2300 my $pciaddr = print_pci_addr
( $deviceid );
2301 my $devicefull = "lsi,id= $deviceid$pciaddr " ;
2302 qemu_deviceadd
( $vmid, $devicefull );
2303 return undef if (! qemu_deviceaddverify
( $vmid, $deviceid ));
2306 if ( $deviceid =~ m/^(scsi)(\d+)$/ ) {
2307 return undef if ! qemu_findorcreatelsi
( $storecfg,$conf, $vmid, $device );
2308 return undef if ! qemu_driveadd
( $storecfg, $vmid, $device );
2309 my $devicefull = print_drivedevice_full
( $storecfg, $vmid, $device );
2310 if (! qemu_deviceadd
( $vmid, $devicefull )) {
2311 qemu_drivedel
( $vmid, $deviceid );
2319 sub vm_deviceunplug
{
2320 my ( $vmid, $conf, $deviceid ) = @_ ;
2322 return 1 if ! check_running
( $vmid ) || ! $conf ->{ hotplug
};
2324 die "can't unplug bootdisk" if $conf ->{ bootdisk
} eq $deviceid ;
2326 if ( $deviceid =~ m/^(virtio)(\d+)$/ ) {
2327 return undef if ! qemu_drivedel
( $vmid, $deviceid );
2328 qemu_devicedel
( $vmid, $deviceid );
2329 return undef if ! qemu_devicedelverify
( $vmid, $deviceid );
2332 if ( $deviceid =~ m/^(lsi)(\d+)$/ ) {
2333 return undef if ! qemu_devicedel
( $vmid, $deviceid );
2336 if ( $deviceid =~ m/^(scsi)(\d+)$/ ) {
2337 return undef if ! qemu_devicedel
( $vmid, $deviceid );
2338 return undef if ! qemu_drivedel
( $vmid, $deviceid );
2344 sub qemu_deviceadd
{
2345 my ( $vmid, $devicefull ) = @_ ;
2347 my $ret = vm_monitor_command
( $vmid, "device_add $devicefull " );
2349 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2350 return 1 if $ret eq "" ;
2351 syslog
( "err" , "error on hotplug device : $ret " );
2356 sub qemu_devicedel
{
2357 my ( $vmid, $deviceid ) = @_ ;
2359 my $ret = vm_monitor_command
( $vmid, "device_del $deviceid " );
2361 return 1 if $ret eq "" ;
2362 syslog
( "err" , "detaching device $deviceid failed : $ret " );
2367 my ( $storecfg, $vmid, $device ) = @_ ;
2369 my $drive = print_drive_full
( $storecfg, $vmid, $device );
2370 my $ret = vm_monitor_command
( $vmid, "drive_add auto $drive " );
2371 # If the command succeeds qemu prints: "OK"
2372 if ( $ret !~ m/OK/s ) {
2373 syslog
( "err" , "adding drive failed: $ret " );
2380 my ( $vmid, $deviceid ) = @_ ;
2382 my $ret = vm_monitor_command
( $vmid, "drive_del drive- $deviceid " );
2384 if ( $ret =~ m/Device \'.*?\' not found/s ) {
2385 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2387 elsif ( $ret ne "" ) {
2388 syslog
( "err" , "deleting drive $deviceid failed : $ret " );
2394 sub qemu_deviceaddverify
{
2395 my ( $vmid,$deviceid ) = @_ ;
2397 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2398 my $devices_list = vm_devices_list
( $vmid );
2399 return 1 if defined ( $devices_list ->{ $deviceid });
2402 syslog
( "err" , "error on hotplug device $deviceid " );
2407 sub qemu_devicedelverify
{
2408 my ( $vmid,$deviceid ) = @_ ;
2410 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2411 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2412 my $devices_list = vm_devices_list
( $vmid );
2413 return 1 if ! defined ( $devices_list ->{ $deviceid });
2416 syslog
( "err" , "error on hot-unplugging device $deviceid " );
2420 sub qemu_findorcreatelsi
{
2421 my ( $storecfg, $conf, $vmid, $device ) = @_ ;
2424 my $controller = int ( $device ->{ index } / $maxdev );
2425 my $lsiid = "lsi $controller " ;
2426 my $devices_list = vm_devices_list
( $vmid );
2428 if (! defined ( $devices_list ->{ $lsiid })) {
2429 return undef if ! vm_deviceplug
( $storecfg, $conf, $vmid, $lsiid );
2435 my ( $storecfg, $vmid, $statefile, $skiplock ) = @_ ;
2437 lock_config
( $vmid, sub {
2438 my $conf = load_config
( $vmid );
2440 check_lock
( $conf ) if ! $skiplock ;
2442 die "VM $vmid already running \n " if check_running
( $vmid );
2445 my $migrate_port = 0 ;
2448 if ( $statefile eq 'tcp' ) {
2449 $migrate_port = next_migrate_port
();
2450 $migrate_uri = "tcp:localhost:${migrate_port}" ;
2452 if (- f
$statefile ) {
2453 $migrate_uri = "exec:cat $statefile " ;
2455 warn "state file ' $statefile ' does not exist - doing normal startup \n " ;
2460 my $defaults = load_defaults
();
2462 my ( $cmd, $vollist ) = config_to_command
( $storecfg, $vmid, $conf, $defaults, $migrate_uri );
2464 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
2465 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
2467 my $info = pci_device_info
( "0000: $d ->{pciid}" );
2468 die "IOMMU not present \n " if ! check_iommu_support
();
2469 die "no pci device info for device ' $d ->{pciid}' \n " if ! $info ;
2470 die "can't unbind pci device ' $d ->{pciid}' \n " if ! pci_dev_bind_to_stub
( $info );
2471 die "can't reset pci device ' $d ->{pciid}' \n " if ! pci_dev_reset
( $info );
2474 PVE
:: Storage
:: activate_volumes
( $storecfg, $vollist );
2476 eval { run_command
( $cmd, timeout
=> $migrate_uri ?
undef : 30 ); };
2478 die "start failed: $err " if $err ;
2482 if ( $statefile eq 'tcp' ) {
2483 print "migration listens on port $migrate_port\n " ;
2486 # fixme: send resume - is that necessary ?
2487 eval { vm_monitor_command
( $vmid, "cont" ); };
2491 # always set migrate speed (overwrite kvm default of 32m)
2492 # we set a very hight default of 8192m which is basically unlimited
2493 my $migrate_speed = $defaults ->{ migrate_speed
} || 8192 ;
2494 $migrate_speed = $conf ->{ migrate_speed
} || $migrate_speed ;
2496 my $cmd = "migrate_set_speed ${migrate_speed}m" ;
2497 vm_monitor_command
( $vmid, $cmd );
2500 if ( my $migrate_downtime =
2501 $conf ->{ migrate_downtime
} || $defaults ->{ migrate_downtime
}) {
2502 my $cmd = "migrate_set_downtime ${migrate_downtime}" ;
2503 eval { vm_monitor_command
( $vmid, $cmd ); };
2506 vm_balloonset
( $vmid, $conf ->{ balloon
}) if $conf ->{ balloon
};
2511 my ( $fh, $timeout ) = @_ ;
2513 my $sel = new IO
:: Select
;
2520 while ( scalar ( @ready = $sel -> can_read ( $timeout ))) {
2522 if ( $count = $fh -> sysread ( $buf, 8192 )) {
2523 if ( $buf =~ /^(.*)\(qemu\) $/s ) {
2530 if (! defined ( $count )) {
2537 die "monitor read timeout \n " if ! scalar ( @ready );
2542 sub vm_monitor_command
{
2543 my ( $vmid, $cmdstr, $nocheck ) = @_ ;
2548 die "VM $vmid not running \n " if ! check_running
( $vmid, $nocheck );
2550 my $sname = monitor_socket
( $vmid );
2552 my $sock = IO
:: Socket
:: UNIX-
> new ( Peer
=> $sname ) ||
2553 die "unable to connect to VM $vmid socket - $!\n " ;
2557 # hack: migrate sometime blocks the monitor (when migrate_downtime
2559 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2560 $timeout = 60 * 60 ; # 1 hour
2564 my $data = __read_avail
( $sock, $timeout );
2566 if ( $data !~ m/^QEMU\s+(\S+)\s+monitor\s/ ) {
2567 die "got unexpected qemu monitor banner \n " ;
2570 my $sel = new IO
:: Select
;
2573 if (! scalar ( my @ready = $sel -> can_write ( $timeout ))) {
2574 die "monitor write error - timeout" ;
2577 my $fullcmd = " $cmdstr\r " ;
2580 if (!( $b = $sock -> syswrite ( $fullcmd )) || ( $b != length ( $fullcmd ))) {
2581 die "monitor write error - $! " ;
2584 return if ( $cmdstr eq 'q' ) || ( $cmdstr eq 'quit' );
2588 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2589 $timeout = 60 * 60 ; # 1 hour
2590 } elsif ( $cmdstr =~ m/^(eject|change)/ ) {
2591 $timeout = 60 ; # note: cdrom mount command is slow
2593 if ( $res = __read_avail
( $sock, $timeout )) {
2595 my @lines = split ( " \r ? \n " , $res );
2597 shift @lines if $lines [ 0 ] !~ m/^unknown command/ ; # skip echo
2599 $res = join ( " \n " , @lines );
2607 syslog
( "err" , "VM $vmid monitor command failed - $err " );
2614 sub vm_commandline
{
2615 my ( $storecfg, $vmid ) = @_ ;
2617 my $conf = load_config
( $vmid );
2619 my $defaults = load_defaults
();
2621 my $cmd = config_to_command
( $storecfg, $vmid, $conf, $defaults );
2623 return join ( ' ' , @$cmd );
2627 my ( $vmid, $skiplock ) = @_ ;
2629 lock_config
( $vmid, sub {
2631 my $conf = load_config
( $vmid );
2633 check_lock
( $conf ) if ! $skiplock ;
2635 vm_monitor_command
( $vmid, "system_reset" );
2639 sub get_vm_volumes
{
2643 foreach_drive
( $conf, sub {
2644 my ( $ds, $drive ) = @_ ;
2646 my ( $sid, $volname ) = PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
}, 1 );
2649 my $volid = $drive ->{ file
};
2650 return if ! $volid || $volid =~ m
|^/|;
2652 push @$vollist, $volid ;
2658 sub vm_stop_cleanup
{
2659 my ( $storecfg, $vmid, $conf, $keepActive ) = @_ ;
2662 fairsched_rmnod
( $vmid ); # try to destroy group
2665 my $vollist = get_vm_volumes
( $conf );
2666 PVE
:: Storage
:: deactivate_volumes
( $storecfg, $vollist );
2669 warn $@ if $@ ; # avoid errors - just warn
2672 # Note: use $nockeck to skip tests if VM configuration file exists.
2673 # We need that when migration VMs to other nodes (files already moved)
2674 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
2676 my ( $storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive ) = @_ ;
2678 $timeout = 60 if ! defined ( $timeout );
2680 $force = 1 if ! defined ( $force ) && ! $shutdown ;
2682 lock_config
( $vmid, sub {
2684 my $pid = check_running
( $vmid, $nocheck );
2689 $conf = load_config
( $vmid );
2690 check_lock
( $conf ) if ! $skiplock ;
2695 vm_monitor_command
( $vmid, "system_powerdown" , $nocheck );
2697 vm_monitor_command
( $vmid, "quit" , $nocheck );
2704 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2709 if ( $count >= $timeout ) {
2711 warn "VM still running - terminating now with SIGTERM \n " ;
2714 die "VM quit/powerdown failed - got timeout \n " ;
2717 vm_stop_cleanup
( $storecfg, $vmid, $conf, $keepActive ) if $conf ;
2722 warn "VM quit/powerdown failed - terminating now with SIGTERM \n " ;
2725 die "VM quit/powerdown failed \n " ;
2733 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2738 if ( $count >= $timeout ) {
2739 warn "VM still running - terminating now with SIGKILL \n " ;
2744 vm_stop_cleanup
( $storecfg, $vmid, $conf, $keepActive ) if $conf ;
2749 my ( $vmid, $skiplock ) = @_ ;
2751 lock_config
( $vmid, sub {
2753 my $conf = load_config
( $vmid );
2755 check_lock
( $conf ) if ! $skiplock ;
2757 vm_monitor_command
( $vmid, "stop" );
2762 my ( $vmid, $skiplock ) = @_ ;
2764 lock_config
( $vmid, sub {
2766 my $conf = load_config
( $vmid );
2768 check_lock
( $conf ) if ! $skiplock ;
2770 vm_monitor_command
( $vmid, "cont" );
2775 my ( $vmid, $skiplock, $key ) = @_ ;
2777 lock_config
( $vmid, sub {
2779 my $conf = load_config
( $vmid );
2781 vm_monitor_command
( $vmid, "sendkey $key " );
2786 my ( $storecfg, $vmid, $skiplock ) = @_ ;
2788 lock_config
( $vmid, sub {
2790 my $conf = load_config
( $vmid );
2792 check_lock
( $conf ) if ! $skiplock ;
2794 if (! check_running
( $vmid )) {
2795 fairsched_rmnod
( $vmid ); # try to destroy group
2796 destroy_vm
( $storecfg, $vmid );
2798 die "VM $vmid is running - destroy failed \n " ;
2804 my ( $storecfg, $timeout ) = @_ ;
2806 $timeout = 3 * 60 if ! $timeout ;
2808 my $cleanuphash = {};
2810 my $vzlist = vzlist
();
2812 foreach my $vmid ( keys %$vzlist ) {
2813 next if ! $vzlist ->{ $vmid }->{ pid
};
2815 $cleanuphash ->{ $vmid } = 1 ;
2820 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs \n " ;
2821 syslog
( 'info' , $msg );
2824 foreach my $vmid ( keys %$vzlist ) {
2825 next if ! $vzlist ->{ $vmid }->{ pid
};
2826 eval { vm_monitor_command
( $vmid, "system_powerdown" ); };
2831 my $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2833 while (( $try < $maxtries ) && $count ) {
2839 foreach my $vmid ( keys %$vzlist ) {
2840 next if ! $vzlist ->{ $vmid }->{ pid
};
2848 foreach my $vmid ( keys %$vzlist ) {
2849 next if ! $vzlist ->{ $vmid }->{ pid
};
2851 warn "VM $vmid still running - sending stop now \n " ;
2852 eval { vm_monitor_command
( $vmid, "quit" ); };
2857 $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2859 while (( $try < $maxtries ) && $count ) {
2865 foreach my $vmid ( keys %$vzlist ) {
2866 next if ! $vzlist ->{ $vmid }->{ pid
};
2874 foreach my $vmid ( keys %$vzlist ) {
2875 next if ! $vzlist ->{ $vmid }->{ pid
};
2877 warn "VM $vmid still running - terminating now with SIGTERM \n " ;
2878 kill 15 , $vzlist ->{ $vmid }->{ pid
};
2883 # this is called by system shotdown scripts, so remaining
2884 # processes gets killed anyways (no need to send kill -9 here)
2888 foreach my $vmid ( keys %$cleanuphash ) {
2889 next if $vzlist ->{ $vmid }->{ pid
};
2891 my $conf = load_config
( $vmid );
2892 vm_stop_cleanup
( $storecfg, $vmid, $conf );
2897 $msg = "Qemu Server stopped \n " ;
2898 syslog
( 'info' , $msg );
2905 my ( $filename, $buf ) = @_ ;
2907 my $fh = IO
:: File-
> new ( $filename, "w" );
2908 return undef if ! $fh ;
2910 my $res = print $fh $buf ;
2917 sub pci_device_info
{
2922 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/ ;
2923 my ( $domain, $bus, $slot, $func ) = ( $1, $2, $3, $4 );
2925 my $irq = file_read_firstline
( " $pcisysfs/devices/$name/irq " );
2926 return undef if ! defined ( $irq ) || $irq !~ m/^\d+$/ ;
2928 my $vendor = file_read_firstline
( " $pcisysfs/devices/$name/vendor " );
2929 return undef if ! defined ( $vendor ) || $vendor !~ s/^0x// ;
2931 my $product = file_read_firstline
( " $pcisysfs/devices/$name/device " );
2932 return undef if ! defined ( $product ) || $product !~ s/^0x// ;
2937 product
=> $product,
2943 has_fl_reset
=> - f
" $pcisysfs/devices/$name/reset " || 0 ,
2952 my $name = $dev ->{ name
};
2954 my $fn = " $pcisysfs/devices/$name/reset " ;
2956 return file_write
( $fn, "1" );
2959 sub pci_dev_bind_to_stub
{
2962 my $name = $dev ->{ name
};
2964 my $testdir = " $pcisysfs/drivers/pci -stub/ $name " ;
2965 return 1 if - d
$testdir ;
2967 my $data = " $dev ->{vendor} $dev ->{product}" ;
2968 return undef if ! file_write
( " $pcisysfs/drivers/pci -stub/new_id" , $data );
2970 my $fn = " $pcisysfs/devices/$name/driver/unbind " ;
2971 if (! file_write
( $fn, $name )) {
2972 return undef if - f
$fn ;
2975 $fn = " $pcisysfs/drivers/pci -stub/bind" ;
2976 if (! - d
$testdir ) {
2977 return undef if ! file_write
( $fn, $name );
2983 sub print_pci_addr
{
2988 #addr1 : ide,parallel,serial (motherboard)
2989 #addr2 : first videocard
2990 balloon0
=> { bus
=> 0 , addr
=> 3 },
2991 watchdog
=> { bus
=> 0 , addr
=> 4 },
2992 lsi0
=> { bus
=> 0 , addr
=> 5 },
2993 lsi1
=> { bus
=> 0 , addr
=> 6 },
2994 virtio0
=> { bus
=> 0 , addr
=> 10 },
2995 virtio1
=> { bus
=> 0 , addr
=> 11 },
2996 virtio2
=> { bus
=> 0 , addr
=> 12 },
2997 virtio3
=> { bus
=> 0 , addr
=> 13 },
2998 virtio4
=> { bus
=> 0 , addr
=> 14 },
2999 virtio5
=> { bus
=> 0 , addr
=> 15 },
3000 hostpci0
=> { bus
=> 0 , addr
=> 16 },
3001 hostpci1
=> { bus
=> 0 , addr
=> 17 },
3002 net0
=> { bus
=> 0 , addr
=> 18 },
3003 net1
=> { bus
=> 0 , addr
=> 19 },
3004 net2
=> { bus
=> 0 , addr
=> 20 },
3005 net3
=> { bus
=> 0 , addr
=> 21 },
3006 net4
=> { bus
=> 0 , addr
=> 22 },
3007 net5
=> { bus
=> 0 , addr
=> 23 },
3008 #addr29 : usb-host (pve-usb.cfg)
3011 if ( defined ( $devices ->{ $id }->{ bus
}) && defined ( $devices ->{ $id }->{ addr
})) {
3012 my $addr = sprintf ( "0x %x " , $devices ->{ $id }->{ addr
});
3013 $res = ",bus=pci. $devices ->{ $id }->{bus},addr= $addr " ;
3020 my ( $vmid, $value ) = @_ ;
3022 vm_monitor_command
( $vmid, "balloon $value " );
3025 # vzdump restore implementaion
3027 sub archive_read_firstfile
{
3028 my $archive = shift ;
3030 die "ERROR: file ' $archive ' does not exist \n " if ! - f
$archive ;
3032 # try to detect archive type first
3033 my $pid = open ( TMP
, "tar tf ' $archive '|" ) ||
3034 die "unable to open file ' $archive ' \n " ;
3035 my $firstfile = < TMP
>;
3039 die "ERROR: archive contaions no data \n " if ! $firstfile ;
3045 sub restore_cleanup
{
3046 my $statfile = shift ;
3048 print STDERR
"starting cleanup \n " ;
3050 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
3051 while ( defined ( my $line = < $fd >)) {
3052 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
3055 if ( $volid =~ m
|^/|) {
3056 unlink $volid || die 'unlink failed \n ' ;
3058 my $cfg = cfs_read_file
( 'storage.cfg' );
3059 PVE
:: Storage
:: vdisk_free
( $cfg, $volid );
3061 print STDERR
"temporary volume ' $volid ' sucessfuly removed \n " ;
3063 print STDERR
"unable to cleanup ' $volid ' - $@ " if $@ ;
3065 print STDERR
"unable to parse line in statfile - $line " ;
3072 sub restore_archive
{
3073 my ( $archive, $vmid, $opts ) = @_ ;
3075 if ( $archive ne '-' ) {
3076 my $firstfile = archive_read_firstfile
( $archive );
3077 die "ERROR: file ' $archive ' dos not lock like a QemuServer vzdump backup \n "
3078 if $firstfile ne 'qemu-server.conf' ;
3081 my $tocmd = "/usr/lib/qemu-server/qmextract" ;
3083 $tocmd .= " --storage " . PVE
:: Tools
:: shellquote
( $opts ->{ storage
}) if $opts ->{ storage
};
3084 $tocmd .= ' --prealloc' if $opts ->{ prealloc
};
3085 $tocmd .= ' --info' if $opts ->{ info
};
3087 # tar option "xf" does not autodetect compression when read fron STDIN,
3088 # so we pipe to zcat
3089 my $cmd = "zcat -f|tar xf " . PVE
:: Tools
:: shellquote
( $archive ) . " " .
3090 PVE
:: Tools
:: shellquote
( "--to-command= $tocmd " );
3092 my $tmpdir = "/var/tmp/vzdumptmp $$ " ;
3095 local $ENV { VZDUMP_TMPDIR
} = $tmpdir ;
3096 local $ENV { VZDUMP_VMID
} = $vmid ;
3098 my $conffile = PVE
:: QemuServer
:: config_file
( $vmid );
3099 my $tmpfn = " $conffile . $$ .tmp" ;
3101 # disable interrupts (always do cleanups)
3102 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = sub {
3103 print STDERR
"got interrupt - ignored \n " ;
3108 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = $SIG { PIPE
} = sub {
3109 die "interrupted by signal \n " ;
3112 if ( $archive eq '-' ) {
3113 print "extracting archive from STDIN \n " ;
3114 run_command
( $cmd, input
=> "<&STDIN" );
3116 print "extracting archive ' $archive ' \n " ;
3120 return if $opts ->{ info
};
3124 my $statfile = " $tmpdir/qmrestore .stat" ;
3125 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
3126 while ( defined ( my $line = < $fd >)) {
3127 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
3128 $map ->{ $1 } = $2 if $1 ;
3130 print STDERR
"unable to parse line in statfile - $line\n " ;
3136 my $confsrc = " $tmpdir/qemu -server.conf" ;
3138 my $srcfd = new IO
:: File
( $confsrc, "r" ) ||
3139 die "unable to open file ' $confsrc ' \n " ;
3141 my $outfd = new IO
:: File
( $tmpfn, "w" ) ||
3142 die "unable to write config for VM $vmid\n " ;
3146 while ( defined ( my $line = < $srcfd >)) {
3147 next if $line =~ m/^\#vzdump\#/ ;
3148 next if $line =~ m/^lock:/ ;
3149 next if $line =~ m/^unused\d+:/ ;
3151 if (( $line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/ )) {
3152 # try to convert old 1.X settings
3153 my ( $id, $ind, $ethcfg ) = ( $1, $2, $3 );
3154 foreach my $devconfig ( PVE
:: Tools
:: split_list
( $ethcfg )) {
3155 my ( $model, $macaddr ) = split ( /\=/ , $devconfig );
3156 $macaddr = PVE
:: Tools
:: random_ether_addr
() if ! $macaddr || $opts ->{ unique
};
3159 bridge
=> "vmbr $ind " ,
3160 macaddr
=> $macaddr,
3162 my $netstr = print_net
( $net );
3163 print $outfd "net${netcount}: $netstr\n " ;
3166 } elsif (( $line =~ m/^(net\d+):\s*(\S+)\s*$/ ) && ( $opts ->{ unique
})) {
3167 my ( $id, $netstr ) = ( $1, $2 );
3168 my $net = parse_net
( $netstr );
3169 $net ->{ macaddr
} = PVE
:: Tools
:: random_ether_addr
() if $net ->{ macaddr
};
3170 $netstr = print_net
( $net );
3171 print $outfd " $id : $netstr\n " ;
3172 } elsif ( $line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/ ) {
3175 if ( $line =~ m/backup=no/ ) {
3176 print $outfd "# $line " ;
3177 } elsif ( $virtdev && $map ->{ $virtdev }) {
3178 my $di = PVE
:: QemuServer
:: parse_drive
( $virtdev, $value );
3179 $di ->{ file
} = $map ->{ $virtdev };
3180 $value = PVE
:: QemuServer
:: print_drive
( $vmid, $di );
3181 print $outfd " $virtdev : $value\n " ;
3199 restore_cleanup
( " $tmpdir/qmrestore .stat" ) if ! $opts ->{ info
};
3206 rename $tmpfn, $conffile ||
3207 die "unable to commit configuration file ' $conffile ' \n " ;