]>
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
=> "Activate hotplug for disk and network device" ,
165 description
=> "Allow reboot. If set to '0' the VM exit on reboot." ,
171 description
=> "Lock/unlock the VM." ,
172 enum
=> [ qw(migrate backup) ],
177 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." ,
184 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." ,
192 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device." ,
199 description
=> "Amount of target RAM for the VM in MB." ,
205 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file." ,
206 enum
=> [ keys %$keymaphash ],
212 description
=> "Set a name for the VM. Only used on the configuration web interface." ,
217 description
=> "Description for the VM. Only used on the configuration web interface." ,
222 enum
=> [ qw(other wxp w2k w2k3 w2k8 wvista win7 l24 l26) ],
223 description
=> <<EODESC,
224 Used to enable special optimization/features for specific
227 other => unspecified OS
228 wxp => Microsoft Windows XP
229 w2k => Microsoft Windows 2000
230 w2k3 => Microsoft Windows 2003
231 w2k8 => Microsoft Windows 2008
232 wvista => Microsoft Windows Vista
233 win7 => Microsoft Windows 7
234 l24 => Linux 2.4 Kernel
235 l26 => Linux 2.6/3.X Kernel
237 other|l24|l26 ... no special behaviour
238 wxp|w2k|w2k3|w2k8|wvista|win7 ... use --localtime switch
244 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)." ,
245 pattern
=> '[acdn]{1,4}' ,
250 type
=> 'string' , format
=> 'pve-qm-bootdisk' ,
251 description
=> "Enable booting from specified disk." ,
252 pattern
=> '(ide|scsi|virtio)\d+' ,
257 description
=> "The number of CPUs. Please use option -sockets instead." ,
264 description
=> "The number of CPU sockets." ,
271 description
=> "The number of cores per socket." ,
278 description
=> "Enable/disable ACPI." ,
284 description
=> "Enable/disable KVM hardware virtualization." ,
290 description
=> "Enable/disable time drift fix." ,
296 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS." ,
301 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution)." ,
306 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" ,
307 enum
=> [ qw(std cirrus vmware) ],
311 type
=> 'string' , format
=> 'pve-qm-watchdog' ,
312 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]' ,
313 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)" ,
318 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)" ,
319 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'." ,
320 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)' ,
326 description
=> <<EODESCR,
327 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
329 args: -no-reboot -no-hpet
336 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." ,
341 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit." ,
345 migrate_downtime
=> {
348 description
=> "Set maximum tolerated downtime (in seconds) for migrations." ,
354 type
=> 'string' , format
=> 'pve-qm-drive' ,
355 typetext
=> 'volume' ,
356 description
=> "This is an alias for option -ide2" ,
360 description
=> "Emulated CPU type." ,
362 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom host) ],
367 # what about other qemu settings ?
369 #machine => 'string',
382 ##soundhw => 'string',
384 while ( my ( $k, $v ) = each %$confdesc ) {
385 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm- $k " , $v );
388 my $MAX_IDE_DISKS = 4 ;
389 my $MAX_SCSI_DISKS = 14 ;
390 my $MAX_VIRTIO_DISKS = 6 ;
391 my $MAX_USB_DEVICES = 5 ;
393 my $MAX_UNUSED_DISKS = 8 ;
394 my $MAX_HOSTPCI_DEVICES = 2 ;
395 my $MAX_SERIAL_PORTS = 4 ;
396 my $MAX_PARALLEL_PORTS = 3 ;
398 my $nic_model_list = [ 'rtl8139' , 'ne2k_pci' , 'e1000' , 'pcnet' , 'virtio' ,
399 'ne2k_isa' , 'i82551' , 'i82557b' , 'i82559er' ];
400 my $nic_model_list_txt = join ( ' ' , sort @$nic_model_list );
405 type
=> 'string' , format
=> 'pve-qm-net' ,
406 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>]" ,
407 description
=> <<EODESCR,
408 Specify network devices.
410 MODEL is one of: $nic_model_list_txt
412 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
413 automatically generated if not specified.
415 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
417 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'.
419 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
425 The DHCP server assign addresses to the guest starting from 10.0.2.15.
429 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-net" , $netdesc );
431 for ( my $i = 0 ; $i < $MAX_NETS ; $i++ ) {
432 $confdesc ->{ "net $i " } = $netdesc ;
439 type
=> 'string' , format
=> 'pve-qm-drive' ,
440 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]' ,
441 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to 3)." ,
443 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-ide" , $idedesc );
447 type
=> 'string' , format
=> 'pve-qm-drive' ,
448 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]' ,
449 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13)." ,
451 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-scsi" , $scsidesc );
455 type
=> 'string' , format
=> 'pve-qm-drive' ,
456 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]' ,
457 description
=> "Use volume as VIRTIO hard disk (n is 0 to 5)." ,
459 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-virtio" , $virtiodesc );
463 type
=> 'string' , format
=> 'pve-qm-usb-device' ,
464 typetext
=> 'host=HOSTUSBDEVICE' ,
465 description
=> <<EODESCR,
466 Configure an USB device (n is 0 to 4). This can be used to
467 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
469 'bus-port(.port)*' (decimal numbers) or
470 'vendor_id:product_id' (hexadeciaml numbers)
472 You can use the 'lsusb -t' command to list existing usb devices.
474 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
478 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-usb" , $usbdesc );
482 type
=> 'string' , format
=> 'pve-qm-hostpci' ,
483 typetext
=> "HOSTPCIDEVICE" ,
484 description
=> <<EODESCR,
485 Map host pci devices. HOSTPCIDEVICE syntax is:
487 'bus:dev.func' (hexadecimal numbers)
489 You can us the 'lspci' command to list existing pci devices.
491 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
493 Experimental: user reported problems with this option.
496 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-hostpci" , $hostpcidesc );
501 pattern
=> '/dev/ttyS\d+' ,
502 description
=> <<EODESCR,
503 Map host serial devices (n is 0 to 3).
505 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
507 Experimental: user reported problems with this option.
514 pattern
=> '/dev/parport\d+' ,
515 description
=> <<EODESCR,
516 Map host parallel devices (n is 0 to 2).
518 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
520 Experimental: user reported problems with this option.
524 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
525 $confdesc ->{ "parallel $i " } = $paralleldesc ;
528 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
529 $confdesc ->{ "serial $i " } = $serialdesc ;
532 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
533 $confdesc ->{ "hostpci $i " } = $hostpcidesc ;
536 for ( my $i = 0 ; $i < $MAX_IDE_DISKS ; $i++ ) {
537 $drivename_hash ->{ "ide $i " } = 1 ;
538 $confdesc ->{ "ide $i " } = $idedesc ;
541 for ( my $i = 0 ; $i < $MAX_SCSI_DISKS ; $i++ ) {
542 $drivename_hash ->{ "scsi $i " } = 1 ;
543 $confdesc ->{ "scsi $i " } = $scsidesc ;
546 for ( my $i = 0 ; $i < $MAX_VIRTIO_DISKS ; $i++ ) {
547 $drivename_hash ->{ "virtio $i " } = 1 ;
548 $confdesc ->{ "virtio $i " } = $virtiodesc ;
551 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
552 $confdesc ->{ "usb $i " } = $usbdesc ;
557 type
=> 'string' , format
=> 'pve-volume-id' ,
558 description
=> "Reference to unused volumes." ,
561 for ( my $i = 0 ; $i < $MAX_UNUSED_DISKS ; $i++ ) {
562 $confdesc ->{ "unused $i " } = $unuseddesc ;
565 my $kvm_api_version = 0 ;
569 return $kvm_api_version if $kvm_api_version ;
571 my $fh = IO
:: File-
> new ( "</dev/kvm" ) ||
574 if ( my $v = $fh -> ioctl ( KVM_GET_API_VERSION
(), 0 )) {
575 $kvm_api_version = $v ;
580 return $kvm_api_version ;
583 my $kvm_user_version ;
585 sub kvm_user_version
{
587 return $kvm_user_version if $kvm_user_version ;
589 $kvm_user_version = 'unknown' ;
591 my $tmp = `kvm -help 2>/dev/null` ;
593 if ( $tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+\.\d+) / ) {
594 $kvm_user_version = $2 ;
597 return $kvm_user_version ;
601 my $kernel_has_vhost_net = - c
'/dev/vhost-net' ;
604 # order is important - used to autoselect boot disk
605 return (( map { "ide $_ " } ( 0 .. ( $MAX_IDE_DISKS - 1 ))),
606 ( map { "scsi $_ " } ( 0 .. ( $MAX_SCSI_DISKS - 1 ))),
607 ( map { "virtio $_ " } ( 0 .. ( $MAX_VIRTIO_DISKS - 1 ))));
610 sub valid_drivename
{
613 return defined ( $drivename_hash ->{ $dev });
618 return defined ( $confdesc ->{ $key });
622 return $nic_model_list ;
625 sub os_list_description
{
630 w2k
=> 'Windows 2000' ,
631 w2k3
=>, 'Windows 2003' ,
632 w2k8
=> 'Windows 2008' ,
633 wvista
=> 'Windows Vista' ,
640 sub disk_devive_info
{
643 die "unknown disk device format ' $dev '" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/ ;
651 } elsif ( $bus eq 'scsi' ) {
655 my $controller = int ( $index / $maxdev );
656 my $unit = $index % $maxdev ;
659 return { bus
=> $bus, desc
=> uc ( $bus ) . " $controller : $unit " ,
660 controller
=> $controller, unit
=> $unit, index => $index };
664 sub qemu_drive_name
{
665 my ( $dev, $media ) = @_ ;
667 my $info = disk_devive_info
( $dev );
670 if (( $info ->{ bus
} eq 'ide' ) || ( $info ->{ bus
} eq 'scsi' )) {
671 $mediastr = ( $media eq 'cdrom' ) ?
"-cd" : "-hd" ;
672 return sprintf ( " %s%i%s%i " , $info ->{ bus
}, $info ->{ controller
},
673 $mediastr, $info ->{ unit
});
675 return sprintf ( " %s%i " , $info ->{ bus
}, $info ->{ index });
683 return $cdrom_path if $cdrom_path ;
685 return $cdrom_path = "/dev/cdrom" if - l
"/dev/cdrom" ;
686 return $cdrom_path = "/dev/cdrom1" if - l
"/dev/cdrom1" ;
687 return $cdrom_path = "/dev/cdrom2" if - l
"/dev/cdrom2" ;
691 my ( $storecfg, $vmid, $cdrom ) = @_ ;
693 if ( $cdrom eq 'cdrom' ) {
694 return get_cdrom_path
();
695 } elsif ( $cdrom eq 'none' ) {
697 } elsif ( $cdrom =~ m
|^/|) {
700 return PVE
:: Storage
:: path
( $storecfg, $cdrom );
704 # try to convert old style file names to volume IDs
705 sub filename_to_volume_id
{
706 my ( $vmid, $file, $media ) = @_ ;
708 if (!( $file eq 'none' || $file eq 'cdrom' ||
709 $file =~ m
|^ /dev/ .+| || $file =~ m/^([^:]+):(.+)$/ )) {
711 return undef if $file =~ m
|/|;
713 if ( $media && $media eq 'cdrom' ) {
714 $file = "local:iso/ $file " ;
716 $file = "local: $vmid/$file " ;
723 sub verify_media_type
{
724 my ( $opt, $vtype, $media ) = @_ ;
729 if ( $media eq 'disk' ) {
731 } elsif ( $media eq 'cdrom' ) {
734 die "internal error" ;
737 return if ( $vtype eq $etype );
739 raise_param_exc
({ $opt => "unexpected media type ( $vtype != $etype )" });
742 sub cleanup_drive_path
{
743 my ( $opt, $storecfg, $drive ) = @_ ;
745 # try to convert filesystem paths to volume IDs
747 if (( $drive ->{ file
} !~ m/^(cdrom|none)$/ ) &&
748 ( $drive ->{ file
} !~ m
|^ /dev/ .+|) &&
749 ( $drive ->{ file
} !~ m/^([^:]+):(.+)$/ ) &&
750 ( $drive ->{ file
} !~ m/^\d+$/ )) {
751 my ( $vtype, $volid ) = PVE
:: Storage
:: path_to_volume_id
( $storecfg, $drive ->{ file
});
752 raise_param_exc
({ $opt => "unable to associate path ' $drive ->{file}' to any storage" }) if ! $vtype ;
753 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $vtype eq 'iso' ;
754 verify_media_type
( $opt, $vtype, $drive ->{ media
});
755 $drive ->{ file
} = $volid ;
758 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $drive ->{ file
} =~ m/^(cdrom|none)$/ ;
761 sub create_conf_nolock
{
762 my ( $vmid, $settings ) = @_ ;
764 my $filename = config_file
( $vmid );
766 die "configuration file ' $filename ' already exists \n " if - f
$filename ;
768 my $defaults = load_defaults
();
770 $settings ->{ name
} = "vm $vmid " if ! $settings ->{ name
};
771 $settings ->{ memory
} = $defaults ->{ memory
} if ! $settings ->{ memory
};
774 foreach my $opt ( keys %$settings ) {
775 next if ! $confdesc ->{ $opt };
777 my $value = $settings ->{ $opt };
780 $data .= " $opt : $value\n " ;
783 PVE
:: Tools
:: file_set_contents
( $filename, $data );
786 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
787 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
788 # [,aio=native|threads]
791 my ( $key, $data ) = @_ ;
795 # $key may be undefined - used to verify JSON parameters
796 if (! defined ( $key )) {
797 $res ->{ interface
} = 'unknown' ; # should not harm when used to verify parameters
799 } elsif ( $key =~ m/^([^\d]+)(\d+)$/ ) {
800 $res ->{ interface
} = $1 ;
806 foreach my $p ( split ( /,/ , $data )) {
807 next if $p =~ m/^\s*$/ ;
809 if ( $p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio)=(.+)$/ ) {
810 my ( $k, $v ) = ( $1, $2 );
812 $k = 'file' if $k eq 'volume' ;
814 return undef if defined $res ->{ $k };
818 if (! $res ->{ file
} && $p !~ m/=/ ) {
826 return undef if ! $res ->{ file
};
828 return undef if $res ->{ cache
} &&
829 $res ->{ cache
} !~ m/^(off|none|writethrough|writeback)$/ ;
830 return undef if $res ->{ snapshot
} && $res ->{ snapshot
} !~ m/^(on|off)$/ ;
831 return undef if $res ->{ cyls
} && $res ->{ cyls
} !~ m/^\d+$/ ;
832 return undef if $res ->{ heads
} && $res ->{ heads
} !~ m/^\d+$/ ;
833 return undef if $res ->{ secs
} && $res ->{ secs
} !~ m/^\d+$/ ;
834 return undef if $res ->{ media
} && $res ->{ media
} !~ m/^(disk|cdrom)$/ ;
835 return undef if $res ->{ trans
} && $res ->{ trans
} !~ m/^(none|lba|auto)$/ ;
836 return undef if $res ->{ format
} && $res ->{ format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/ ;
837 return undef if $res ->{ rerror
} && $res ->{ rerror
} !~ m/^(ignore|report|stop)$/ ;
838 return undef if $res ->{ werror
} && $res ->{ werror
} !~ m/^(enospc|ignore|report|stop)$/ ;
839 return undef if $res ->{ backup
} && $res ->{ backup
} !~ m/^(yes|no)$/ ;
840 return undef if $res ->{ aio
} && $res ->{ aio
} !~ m/^(native|threads)$/ ;
842 if ( $res ->{ media
} && ( $res ->{ media
} eq 'cdrom' )) {
843 return undef if $res ->{ snapshot
} || $res ->{ trans
} || $res ->{ format
};
844 return undef if $res ->{ heads
} || $res ->{ secs
} || $res ->{ cyls
};
845 return undef if $res ->{ interface
} eq 'virtio' ;
848 # rerror does not work with scsi drives
849 if ( $res ->{ rerror
}) {
850 return undef if $res ->{ interface
} eq 'scsi' ;
856 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio) ;
859 my ( $vmid, $drive ) = @_ ;
862 foreach my $o ( @qemu_drive_options, 'backup' ) {
863 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
866 return " $drive ->{file} $opts " ;
869 sub print_drivedevice_full
{
870 my ( $storecfg, $vmid, $drive ) = @_ ;
875 if ( $drive ->{ interface
} eq 'virtio' ) {
876 my $pciaddr = print_pci_addr
( " $drive ->{interface} $drive ->{index}" );
877 $device = "virtio-blk-pci,drive=drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index} $pciaddr " ;
880 elsif ( $drive ->{ interface
} eq 'scsi' ) {
883 my $controller = int ( $drive ->{ index } / $maxdev );
884 my $unit = $drive ->{ index } % $maxdev ;
886 $device = "scsi-disk,bus=scsi $controller .0,scsi-id= $unit,drive =drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index}" ;
889 elsif ( $drive ->{ interface
} eq 'ide' ){
892 my $controller = int ( $drive ->{ index } / $maxdev );
893 my $unit = $drive ->{ index } % $maxdev ;
895 $device = "ide-drive,bus=ide. $controller,unit = $unit,drive =drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index}" ;
898 if ( $drive ->{ interface
} eq 'usb' ){
899 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
905 sub print_drive_full
{
906 my ( $storecfg, $vmid, $drive ) = @_ ;
909 foreach my $o ( @qemu_drive_options ) {
910 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
913 # use linux-aio by default (qemu default is threads)
914 $opts .= ",aio=native" if ! $drive ->{ aio
};
917 my $volid = $drive ->{ file
};
918 if ( drive_is_cdrom
( $drive )) {
919 $path = get_iso_path
( $storecfg, $vmid, $volid );
921 if ( $volid =~ m
|^/|) {
924 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
928 my $pathinfo = $path ?
"file= $path, " : '' ;
930 return "${pathinfo}if=none,id=drive- $drive ->{interface} $drive ->{index} $opts " ;
937 return $drive && $drive ->{ media
} && ( $drive ->{ media
} eq 'cdrom' );
944 return undef if ! $value ;
948 if ( $value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/ ) {
949 $res ->{ pciid
} = $value ;
957 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
963 foreach my $kvp ( split ( /,/ , $data )) {
965 if ( $kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i ) {
967 my $mac = uc ( $3 ) || PVE
:: Tools
:: random_ether_addr
();
968 $res ->{ model
} = $model ;
969 $res ->{ macaddr
} = $mac ;
970 } elsif ( $kvp =~ m/^bridge=(\S+)$/ ) {
972 } elsif ( $kvp =~ m/^rate=(\d+(\.\d+)?)$/ ) {
980 return undef if ! $res ->{ model
};
988 my $res = " $net ->{model}" ;
989 $res .= "= $net ->{macaddr}" if $net ->{ macaddr
};
990 $res .= ",bridge= $net ->{bridge}" if $net ->{ bridge
};
991 $res .= ",rate= $net ->{rate}" if $net ->{ rate
};
996 sub add_random_macs
{
999 foreach my $opt ( keys %$settings ) {
1000 next if $opt !~ m/^net(\d+)$/ ;
1001 my $net = parse_net
( $settings ->{ $opt });
1003 $settings ->{ $opt } = print_net
( $net );
1007 sub add_unused_volume
{
1008 my ( $config, $res, $volid ) = @_ ;
1011 for ( my $ind = $MAX_UNUSED_DISKS - 1 ; $ind >= 0 ; $ind --) {
1012 my $test = "unused $ind " ;
1013 if ( my $vid = $config ->{ $test }) {
1014 return if $vid eq $volid ; # do not add duplicates
1020 die "To many unused volume - please delete them first. \n " if ! $key ;
1022 $res ->{ $key } = $volid ;
1025 # fixme: remove all thos $noerr parameters?
1027 PVE
:: JSONSchema
:: register_format
( 'pve-qm-bootdisk' , \
& verify_bootdisk
);
1028 sub verify_bootdisk
{
1029 my ( $value, $noerr ) = @_ ;
1031 return $value if valid_drivename
( $value );
1033 return undef if $noerr ;
1035 die "invalid boot disk ' $value ' \n " ;
1038 PVE
:: JSONSchema
:: register_format
( 'pve-qm-net' , \
& verify_net
);
1040 my ( $value, $noerr ) = @_ ;
1042 return $value if parse_net
( $value );
1044 return undef if $noerr ;
1046 die "unable to parse network options \n " ;
1049 PVE
:: JSONSchema
:: register_format
( 'pve-qm-drive' , \
& verify_drive
);
1051 my ( $value, $noerr ) = @_ ;
1053 return $value if parse_drive
( undef , $value );
1055 return undef if $noerr ;
1057 die "unable to parse drive options \n " ;
1060 PVE
:: JSONSchema
:: register_format
( 'pve-qm-hostpci' , \
& verify_hostpci
);
1061 sub verify_hostpci
{
1062 my ( $value, $noerr ) = @_ ;
1064 return $value if parse_hostpci
( $value );
1066 return undef if $noerr ;
1068 die "unable to parse pci id \n " ;
1071 PVE
:: JSONSchema
:: register_format
( 'pve-qm-watchdog' , \
& verify_watchdog
);
1072 sub verify_watchdog
{
1073 my ( $value, $noerr ) = @_ ;
1075 return $value if parse_watchdog
( $value );
1077 return undef if $noerr ;
1079 die "unable to parse watchdog options \n " ;
1082 sub parse_watchdog
{
1085 return undef if ! $value ;
1089 foreach my $p ( split ( /,/ , $value )) {
1090 next if $p =~ m/^\s*$/ ;
1092 if ( $p =~ m/^(model=)?(i6300esb|ib700)$/ ) {
1094 } elsif ( $p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/ ) {
1095 $res ->{ action
} = $2 ;
1104 sub parse_usb_device
{
1107 return undef if ! $value ;
1109 my @dl = split ( /,/ , $value );
1113 foreach my $v ( @dl ) {
1114 if ( $v =~ m/^host=([0-9A-Fa-f]{4}):([0-9A-Fa-f]{4})$/ ) {
1116 $res ->{ vendorid
} = $1 ;
1117 $res ->{ productid
} = $2 ;
1118 } elsif ( $v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/ ) {
1120 $res ->{ hostbus
} = $1 ;
1121 $res ->{ hostport
} = $2 ;
1126 return undef if ! $found ;
1131 PVE
:: JSONSchema
:: register_format
( 'pve-qm-usb-device' , \
& verify_usb_device
);
1132 sub verify_usb_device
{
1133 my ( $value, $noerr ) = @_ ;
1135 return $value if parse_usb_device
( $value );
1137 return undef if $noerr ;
1139 die "unable to parse usb device \n " ;
1142 # add JSON properties for create and set function
1143 sub json_config_properties
{
1146 foreach my $opt ( keys %$confdesc ) {
1147 $prop ->{ $opt } = $confdesc ->{ $opt };
1154 my ( $key, $value ) = @_ ;
1156 die "unknown setting ' $key ' \n " if ! $confdesc ->{ $key };
1158 my $type = $confdesc ->{ $key }->{ type
};
1160 if (! defined ( $value )) {
1161 die "got undefined value \n " ;
1164 if ( $value =~ m/[\n\r]/ ) {
1165 die "property contains a line feed \n " ;
1168 if ( $type eq 'boolean' ) {
1169 return 1 if ( $value eq '1' ) || ( $value =~ m/^(on|yes|true)$/i );
1170 return 0 if ( $value eq '0' ) || ( $value =~ m/^(off|no|false)$/i );
1171 die "type check ('boolean') failed - got ' $value ' \n " ;
1172 } elsif ( $type eq 'integer' ) {
1173 return int ( $1 ) if $value =~ m/^(\d+)$/ ;
1174 die "type check ('integer') failed - got ' $value ' \n " ;
1175 } elsif ( $type eq 'string' ) {
1176 if ( my $fmt = $confdesc ->{ $key }->{ format
}) {
1177 if ( $fmt eq 'pve-qm-drive' ) {
1178 # special case - we need to pass $key to parse_drive()
1179 my $drive = parse_drive
( $key, $value );
1180 return $value if $drive ;
1181 die "unable to parse drive options \n " ;
1183 PVE
:: JSONSchema
:: check_format
( $fmt, $value );
1186 $value =~ s/^\"(.*)\"$/$1/ ;
1189 die "internal error"
1194 my ( $vmid, $code, @param ) = @_ ;
1196 my $filename = config_file_lock
( $vmid );
1198 my $res = lock_file
( $filename, 10 , $code, @param );
1205 sub cfs_config_path
{
1206 my ( $vmid, $node ) = @_ ;
1208 $node = $nodename if ! $node ;
1209 return "nodes/ $node/qemu -server/ $vmid .conf" ;
1212 sub check_iommu_support
{
1213 #fixme : need to check IOMMU support
1214 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1222 my ( $vmid, $node ) = @_ ;
1224 my $cfspath = cfs_config_path
( $vmid, $node );
1225 return "/etc/pve/ $cfspath " ;
1228 sub config_file_lock
{
1231 return " $lock_dir/lock - $vmid .conf" ;
1237 my $conf = config_file
( $vmid );
1238 utime undef , undef , $conf ;
1242 my ( $storecfg, $vmid, $settings, $conf, $default_storage ) = @_ ;
1247 foreach_drive
( $settings, sub {
1248 my ( $ds, $disk ) = @_ ;
1250 return if drive_is_cdrom
( $disk );
1252 my $file = $disk ->{ file
};
1254 if ( $file =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/ ) {
1255 my $storeid = $2 || $default_storage ;
1257 my $defformat = PVE
:: Storage
:: storage_default_format
( $storecfg, $storeid );
1258 my $fmt = $disk ->{ format
} || $defformat ;
1259 syslog
( 'info' , "VM $vmid creating new disk - size is $size GB" );
1261 my $volid = PVE
:: Storage
:: vdisk_alloc
( $storecfg, $storeid, $vmid,
1262 $fmt, undef , $size*1024*1024 );
1264 $disk ->{ file
} = $volid ;
1265 delete $disk ->{ format
}; # no longer needed
1266 push @$vollist, $volid ;
1267 $settings ->{ $ds } = PVE
:: QemuServer
:: print_drive
( $vmid, $disk );
1270 if ( $disk ->{ file
} =~ m
|^ /dev/ .+|) {
1271 $path = $disk ->{ file
};
1273 $path = PVE
:: Storage
:: path
( $storecfg, $disk ->{ file
});
1275 if (!(- f
$path || - b
$path )) {
1276 die "image ' $path ' does not exists \n " ;
1279 PVE
:: QemuServer
:: vm_deviceadd
( $storecfg, $conf, $vmid, $ds, $disk ) if defined ( $conf );
1286 syslog
( 'err' , "VM $vmid creating disks failed" );
1287 foreach my $volid ( @$vollist ) {
1288 eval { PVE
:: Storage
:: vdisk_free
( $storecfg, $volid ); };
1298 my ( $storecfg, $vmid, $volid ) = @_ ;
1300 die "reject to unlink absolute path ' $volid '"
1303 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1305 die "reject to unlink ' $volid ' - not owned by this VM"
1306 if ! $owner || ( $owner != $vmid );
1308 syslog
( 'info' , "VM $vmid deleting volume ' $volid '" );
1310 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1312 touch_config
( $vmid );
1316 my ( $storecfg, $vmid, $keep_empty_config ) = @_ ;
1318 my $conffile = config_file
( $vmid );
1320 my $conf = load_config
( $vmid );
1324 # only remove disks owned by this VM
1325 foreach_drive
( $conf, sub {
1326 my ( $ds, $drive ) = @_ ;
1328 return if drive_is_cdrom
( $drive );
1330 my $volid = $drive ->{ file
};
1331 next if ! $volid || $volid =~ m
|^/|;
1333 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1334 next if ! $path || ! $owner || ( $owner != $vmid );
1336 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1339 if ( $keep_empty_config ) {
1340 PVE
:: Tools
:: file_set_contents
( $conffile, "memory: 128 \n " );
1345 # also remove unused disk
1347 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid );
1350 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1351 my ( $volid, $sid, $volname, $d ) = @_ ;
1352 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1362 sub load_diskinfo_old
{
1363 my ( $storecfg, $vmid, $conf ) = @_ ;
1369 foreach_drive
( $conf, sub {
1374 return if drive_is_cdrom
( $di );
1376 if ( $di ->{ file
} =~ m
|^ /dev/ .+|) {
1377 $info ->{ $di ->{ file
}}->{ size
} = PVE
:: Storage
:: file_size_info
( $di ->{ file
});
1379 push @$vollist, $di ->{ file
};
1384 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid, $vollist );
1386 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1387 my ( $volid, $sid, $volname, $d ) = @_ ;
1388 $info ->{ $volid } = $d ;
1393 foreach my $ds ( keys %$res ) {
1394 my $di = $res ->{ $ds };
1396 $res ->{ $ds }->{ disksize
} = $info ->{ $di ->{ file
}} ?
1397 $info ->{ $di ->{ file
}}->{ size
} / ( 1024 * 1024 ) : 0 ;
1406 my $cfspath = cfs_config_path
( $vmid );
1408 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath );
1410 die "no such VM (' $vmid ') \n " if ! defined ( $conf );
1415 sub parse_vm_config
{
1416 my ( $filename, $raw ) = @_ ;
1418 return undef if ! defined ( $raw );
1421 digest
=> Digest
:: SHA1
:: sha1_hex
( $raw ),
1424 $filename =~ m
| /qemu-server/ ( \d
+) \
. conf
$|
1425 || die "got strange filename ' $filename '" ;
1429 while ( $raw && $raw =~ s/^(.*?)(\n|$)// ) {
1432 next if $line =~ m/^\#/ ;
1434 next if $line =~ m/^\s*$/ ;
1436 if ( $line =~ m/^(description):\s*(.*\S)\s*$/ ) {
1438 my $value = PVE
:: Tools
:: decode_text
( $2 );
1439 $res ->{ $key } = $value ;
1440 } elsif ( $line =~ m/^(args):\s*(.*\S)\s*$/ ) {
1443 $res ->{ $key } = $value ;
1444 } elsif ( $line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/ ) {
1447 eval { $value = check_type
( $key, $value ); };
1449 warn "vm $vmid - unable to parse value of ' $key ' - $@ " ;
1451 my $fmt = $confdesc ->{ $key }->{ format
};
1452 if ( $fmt && $fmt eq 'pve-qm-drive' ) {
1453 my $v = parse_drive
( $key, $value );
1454 if ( my $volid = filename_to_volume_id
( $vmid, $v ->{ file
}, $v ->{ media
})) {
1455 $v ->{ file
} = $volid ;
1456 $value = print_drive
( $vmid, $v );
1458 warn "vm $vmid - unable to parse value of ' $key ' \n " ;
1463 if ( $key eq 'cdrom' ) {
1464 $res ->{ ide2
} = $value ;
1466 $res ->{ $key } = $value ;
1472 # convert old smp to sockets
1473 if ( $res ->{ smp
} && ! $res ->{ sockets
}) {
1474 $res ->{ sockets
} = $res ->{ smp
};
1482 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1484 lock_config
( $vmid, & change_config_nolock
, $settings, $unset, $skiplock );
1487 sub change_config_nolock
{
1488 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1492 $unset ->{ ide2
} = $unset ->{ cdrom
} if $unset ->{ cdrom
};
1494 check_lock
( $settings ) if ! $skiplock ;
1496 # we do not use 'smp' any longer
1497 if ( $settings ->{ sockets
}) {
1499 } elsif ( $settings ->{ smp
}) {
1500 $settings ->{ sockets
} = $settings ->{ smp
};
1504 my $new_volids = {};
1506 foreach my $key ( keys %$settings ) {
1507 next if $key eq 'digest' ;
1508 my $value = $settings ->{ $key };
1509 if ( $key eq 'description' ) {
1510 $value = PVE
:: Tools
:: encode_text
( $value );
1512 eval { $value = check_type
( $key, $value ); };
1513 die "unable to parse value of ' $key ' - $@ " if $@ ;
1514 if ( $key eq 'cdrom' ) {
1515 $res ->{ ide2
} = $value ;
1517 $res ->{ $key } = $value ;
1519 if ( valid_drivename
( $key )) {
1520 my $drive = PVE
:: QemuServer
:: parse_drive
( $key, $value );
1521 $new_volids ->{ $drive ->{ file
}} = 1 if $drive && $drive ->{ file
};
1525 my $filename = config_file
( $vmid );
1526 my $tmpfn = " $filename . $$ .tmp" ;
1528 my $fh = new IO
:: File
( $filename, "r" ) ||
1529 die "unable to read config for VM $vmid\n " ;
1531 my $werror = "unable to write config for VM $vmid\n " ;
1533 my $out = new IO
:: File
( $tmpfn, "w" ) || die $werror ;
1539 while ( my $line = < $fh >) {
1541 if (( $line =~ m/^\#/ ) || ( $line =~ m/^\s*$/ )) {
1542 die $werror unless print $out $line ;
1546 if ( $line =~ m/^([a-z][a-z_]*\d*):\s*(.*\S)\s*$/ ) {
1550 # remove 'unusedX' settings if we re-add a volume
1551 next if $key =~ m/^unused/ && $new_volids ->{ $value };
1553 # convert 'smp' to 'sockets'
1554 $key = 'sockets' if $key eq 'smp' ;
1556 next if $done ->{ $key };
1559 if ( defined ( $res ->{ $key })) {
1560 $value = $res ->{ $key };
1561 delete $res ->{ $key };
1563 if (! defined ( $unset ->{ $key })) {
1564 die $werror unless print $out " $key : $value\n " ;
1570 die "unable to parse config file: $line\n " ;
1573 foreach my $key ( keys %$res ) {
1575 if (! defined ( $unset ->{ $key })) {
1576 die $werror unless print $out " $key : $res ->{ $key } \n " ;
1591 if (! $out -> close ()) {
1592 $err = "close failed - $!\n " ;
1597 if (! rename ( $tmpfn, $filename )) {
1598 $err = "rename failed - $!\n " ;
1608 # we use static defaults from our JSON schema configuration
1609 foreach my $key ( keys %$confdesc ) {
1610 if ( defined ( my $default = $confdesc ->{ $key }->{ default })) {
1611 $res ->{ $key } = $default ;
1615 my $conf = PVE
:: Cluster
:: cfs_read_file
( 'datacenter.cfg' );
1616 $res ->{ keyboard
} = $conf ->{ keyboard
} if $conf ->{ keyboard
};
1622 my $vmlist = PVE
:: Cluster
:: get_vmlist
();
1624 return $res if ! $vmlist || ! $vmlist ->{ ids
};
1625 my $ids = $vmlist ->{ ids
};
1627 foreach my $vmid ( keys %$ids ) {
1628 my $d = $ids ->{ $vmid };
1629 next if ! $d ->{ node
} || $d ->{ node
} ne $nodename ;
1630 next if ! $d ->{ type
} || $d ->{ type
} ne 'qemu' ;
1631 $res ->{ $vmid }->{ exists } = 1 ;
1636 # test if VM uses local resources (to prevent migration)
1637 sub check_local_resources
{
1638 my ( $conf, $noerr ) = @_ ;
1642 $loc_res = 1 if $conf ->{ hostusb
}; # old syntax
1643 $loc_res = 1 if $conf ->{ hostpci
}; # old syntax
1645 foreach my $k ( keys %$conf ) {
1646 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/ ;
1649 die "VM uses local resources \n " if $loc_res && ! $noerr ;
1657 die "VM is locked ( $conf ->{lock}) \n " if $conf ->{ lock };
1661 my ( $pidfile, $pid ) = @_ ;
1663 my $fh = IO
:: File-
> new ( "/proc/ $pid/cmdline " , "r" );
1667 return undef if ! $line ;
1668 my @param = split ( /\0/ , $line );
1670 my $cmd = $param [ 0 ];
1671 return if ! $cmd || ( $cmd !~ m
| kvm
$|);
1673 for ( my $i = 0 ; $i < scalar ( @param ); $i++ ) {
1676 if (( $p eq '-pidfile' ) || ( $p eq '--pidfile' )) {
1677 my $p = $param [ $i+1 ];
1678 return 1 if $p && ( $p eq $pidfile );
1687 my ( $vmid, $nocheck ) = @_ ;
1689 my $filename = config_file
( $vmid );
1691 die "unable to find configuration file for VM $vmid - no such machine \n "
1692 if ! $nocheck && ! - f
$filename ;
1694 my $pidfile = pidfile_name
( $vmid );
1696 if ( my $fd = IO
:: File-
> new ( "< $pidfile " )) {
1701 my $mtime = $st -> mtime ;
1702 if ( $mtime > time ()) {
1703 warn "file ' $filename ' modified in future \n " ;
1706 if ( $line =~ m/^(\d+)$/ ) {
1708 if ( check_cmdline
( $pidfile, $pid )) {
1709 if ( my $pinfo = PVE
:: ProcFSTools
:: check_process_running
( $pid )) {
1721 my $vzlist = config_list
();
1723 my $fd = IO
:: Dir-
> new ( $var_run_tmpdir ) || return $vzlist ;
1725 while ( defined ( my $de = $fd -> read )) {
1726 next if $de !~ m/^(\d+)\.pid$/ ;
1728 next if ! defined ( $vzlist ->{ $vmid });
1729 if ( my $pid = check_running
( $vmid )) {
1730 $vzlist ->{ $vmid }->{ pid
} = $pid ;
1737 my $storage_timeout_hash = {};
1740 my ( $storecfg, $conf ) = @_ ;
1742 my $bootdisk = $conf ->{ bootdisk
};
1743 return undef if ! $bootdisk ;
1744 return undef if ! valid_drivename
( $bootdisk );
1746 return undef if ! $conf ->{ $bootdisk };
1748 my $drive = parse_drive
( $bootdisk, $conf ->{ $bootdisk });
1749 return undef if ! defined ( $drive );
1751 return undef if drive_is_cdrom
( $drive );
1753 my $volid = $drive ->{ file
};
1754 return undef if ! $volid ;
1760 if ( $volid =~ m
|^/|) {
1761 $path = $timeoutid = $volid ;
1763 $storeid = $timeoutid = PVE
:: Storage
:: parse_volume_id
( $volid );
1764 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
1767 my $last_timeout = $storage_timeout_hash ->{ $timeoutid };
1768 if ( $last_timeout ) {
1769 if (( time () - $last_timeout ) < 30 ) {
1770 # skip storage with errors
1773 delete $storage_timeout_hash ->{ $timeoutid };
1776 my ( $size, $format, $used );
1778 ( $size, $format, $used ) = PVE
:: Storage
:: file_size_info
( $path, 1 );
1780 if (! defined ( $format )) {
1782 $storage_timeout_hash ->{ $timeoutid } = time ();
1786 return wantarray ?
( $size, $used ) : $size ;
1789 my $last_proc_pid_stat ;
1792 my ( $opt_vmid ) = @_ ;
1796 my $storecfg = PVE
:: Storage
:: config
();
1798 my $list = vzlist
();
1799 my ( $uptime ) = PVE
:: ProcFSTools
:: read_proc_uptime
( 1 );
1801 foreach my $vmid ( keys %$list ) {
1802 next if $opt_vmid && ( $vmid ne $opt_vmid );
1804 my $cfspath = cfs_config_path
( $vmid );
1805 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath ) || {};
1808 $d ->{ pid
} = $list ->{ $vmid }->{ pid
};
1810 # fixme: better status?
1811 $d ->{ status
} = $list ->{ $vmid }->{ pid
} ?
'running' : 'stopped' ;
1813 my ( $size, $used ) = disksize
( $storecfg, $conf );
1814 if ( defined ( $size ) && defined ( $used )) {
1816 $d ->{ maxdisk
} = $size ;
1822 $d ->{ cpus
} = ( $conf ->{ sockets
} || 1 ) * ( $conf ->{ cores
} || 1 );
1823 $d ->{ name
} = $conf ->{ name
} || "VM $vmid " ;
1824 $d ->{ maxmem
} = $conf ->{ memory
} ?
$conf ->{ memory
}*( 1024 * 1024 ) : 0 ;
1835 $d ->{ diskwrite
} = 0 ;
1840 my $netdev = PVE
:: ProcFSTools
:: read_proc_net_dev
();
1841 foreach my $dev ( keys %$netdev ) {
1842 next if $dev !~ m/^tap([1-9]\d*)i/ ;
1844 my $d = $res ->{ $vmid };
1847 $d ->{ netout
} += $netdev ->{ $dev }->{ receive
};
1848 $d ->{ netin
} += $netdev ->{ $dev }->{ transmit
};
1851 my $cpucount = $cpuinfo ->{ cpus
} || 1 ;
1852 my $ctime = gettimeofday
;
1854 foreach my $vmid ( keys %$list ) {
1856 my $d = $res ->{ $vmid };
1857 my $pid = $d ->{ pid
};
1860 if ( my $fh = IO
:: File-
> new ( "/proc/ $pid/io " , "r" )) {
1862 while ( defined ( my $line = < $fh >)) {
1863 if ( $line =~ m/^([rw]char):\s+(\d+)$/ ) {
1868 $d ->{ diskread
} = $data ->{ rchar
} || 0 ;
1869 $d ->{ diskwrite
} = $data ->{ wchar
} || 0 ;
1872 my $pstat = PVE
:: ProcFSTools
:: read_proc_pid_stat
( $pid );
1873 next if ! $pstat ; # not running
1875 my $used = $pstat ->{ utime } + $pstat ->{ stime
};
1877 my $vcpus = $d ->{ cpus
} > $cpucount ?
$cpucount : $d ->{ cpus
};
1879 $d ->{ uptime
} = int (( $uptime - $pstat ->{ starttime
})/ $cpuinfo ->{ user_hz
});
1881 if ( $pstat ->{ vsize
}) {
1882 $d ->{ mem
} = int (( $pstat ->{ rss
}/ $pstat ->{ vsize
})* $d ->{ maxmem
});
1885 my $old = $last_proc_pid_stat ->{ $pid };
1887 $last_proc_pid_stat ->{ $pid } = {
1896 my $dtime = ( $ctime - $old ->{ time }) * $cpucount * $cpuinfo ->{ user_hz
};
1898 if ( $dtime > 1000 ) {
1899 my $dutime = $used - $old ->{ used
};
1901 $d ->{ cpu
} = $dutime/$dtime ;
1902 $d ->{ relcpu
} = ( $d ->{ cpu
} * $cpucount ) / $vcpus ;
1903 $last_proc_pid_stat ->{ $pid } = {
1907 relcpu
=> $d ->{ relcpu
},
1910 $d ->{ cpu
} = $old ->{ cpu
};
1911 $d ->{ relcpu
} = $old ->{ relcpu
};
1919 my ( $conf, $func ) = @_ ;
1921 foreach my $ds ( keys %$conf ) {
1922 next if ! valid_drivename
( $ds );
1924 my $drive = parse_drive
( $ds, $conf ->{ $ds });
1927 & $func ( $ds, $drive );
1931 sub config_to_command
{
1932 my ( $storecfg, $vmid, $conf, $defaults, $migrate_uri ) = @_ ;
1936 my $kvmver = kvm_user_version
();
1937 my $vernum = 0 ; # unknown
1938 if ( $kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/ ) {
1939 $vernum = $1*1000000+$2*1000+$3 ;
1942 die "detected old qemu-kvm binary ( $kvmver ) \n " if $vernum < 14000 ;
1944 my $have_ovz = - f
'/proc/vz/vestat' ;
1946 push @$cmd, '/usr/bin/kvm' ;
1948 push @$cmd, '-id' , $vmid ;
1952 my $socket = monitor_socket
( $vmid );
1953 push @$cmd, '-chardev' , "socket,id=monitor,path= $socket,server,nowait " ;
1954 push @$cmd, '-mon' , "chardev=monitor,mode=readline" ;
1956 $socket = vnc_socket
( $vmid );
1957 push @$cmd, '-vnc' , "unix: $socket,x509,password " ;
1959 push @$cmd, '-pidfile' , pidfile_name
( $vmid );
1961 push @$cmd, '-daemonize' ;
1963 push @$cmd, '-incoming' , $migrate_uri if $migrate_uri ;
1965 # include usb device config
1966 push @$cmd, '-readconfig' , '/usr/share/qemu-server/pve-usb.cfg' ;
1968 # enable absolute mouse coordinates (needed by vnc)
1969 my $tablet = defined ( $conf ->{ tablet
}) ?
$conf ->{ tablet
} : $defaults ->{ tablet
};
1970 push @$cmd, '-device' , 'usb-tablet,bus=ehci.0,port=6' if $tablet ;
1973 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
1974 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
1976 $pciaddr = print_pci_addr
( "hostpci $i " );
1977 push @$cmd, '-device' , "pci-assign,host= $d ->{pciid},id=hostpci $i$pciaddr " ;
1981 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1982 my $d = parse_usb_device
( $conf ->{ "usb $i " });
1984 if ( $d ->{ vendorid
} && $d ->{ productid
}) {
1985 push @$cmd, '-device' , "usb-host,vendorid= $d ->{vendorid},productid= $d ->{productid}" ;
1986 } elsif ( defined ( $d ->{ hostbus
}) && defined ( $d ->{ hostport
})) {
1987 push @$cmd, '-device' , "usb-host,hostbus= $d ->{hostbus},hostport= $d ->{hostport}" ;
1992 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
1993 if ( my $path = $conf ->{ "serial $i " }) {
1994 die "no such serial device \n " if ! - c
$path ;
1995 push @$cmd, '-chardev' , "tty,id=serial $i,path = $path " ;
1996 push @$cmd, '-device' , "isa-serial,chardev=serial $i " ;
2001 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
2002 if ( my $path = $conf ->{ "parallel $i " }) {
2003 die "no such parallel device \n " if ! - c
$path ;
2004 push @$cmd, '-chardev' , "parport,id=parallel $i,path = $path " ;
2005 push @$cmd, '-device' , "isa-parallel,chardev=parallel $i " ;
2009 my $vmname = $conf ->{ name
} || "vm $vmid " ;
2011 push @$cmd, '-name' , $vmname ;
2014 $sockets = $conf ->{ smp
} if $conf ->{ smp
}; # old style - no longer iused
2015 $sockets = $conf ->{ sockets
} if $conf ->{ sockets
};
2017 my $cores = $conf ->{ cores
} || 1 ;
2021 push @$cmd, '-smp' , "sockets= $sockets,cores = $cores " ;
2023 push @$cmd, '-cpu' , $conf ->{ cpu
} if $conf ->{ cpu
};
2025 push @$cmd, '-nodefaults' ;
2027 my $bootorder = $conf ->{ boot
} || $confdesc ->{ boot
}->{ default };
2028 push @$cmd, '-boot' , "menu=on,order= $bootorder " ;
2030 push @$cmd, '-no-acpi' if defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 ;
2032 push @$cmd, '-no-reboot' if defined ( $conf ->{ reboot
}) && $conf ->{ reboot
} == 0 ;
2034 my $vga = $conf ->{ vga
};
2036 if ( $conf ->{ ostype
} && ( $conf ->{ ostype
} eq 'win7' || $conf ->{ ostype
} eq 'w2k8' )) {
2043 push @$cmd, '-vga' , $vga if $vga ; # for kvm 77 and later
2046 my $tdf = defined ( $conf ->{ tdf
}) ?
$conf ->{ tdf
} : $defaults ->{ tdf
};
2047 push @$cmd, '-tdf' if $tdf ;
2049 my $nokvm = defined ( $conf ->{ kvm
}) && $conf ->{ kvm
} == 0 ?
1 : 0 ;
2051 if ( my $ost = $conf ->{ ostype
}) {
2052 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2054 if ( $ost =~ m/^w/ ) { # windows
2055 push @$cmd, '-localtime' if ! defined ( $conf ->{ localtime });
2057 # use rtc-td-hack when acpi is enabled
2058 if (!( defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 )) {
2059 push @$cmd, '-rtc-td-hack' ;
2070 push @$cmd, '-no-kvm' ;
2072 die "No accelerator found! \n " if ! $cpuinfo ->{ hvm
};
2075 push @$cmd, '-localtime' if $conf ->{ localtime };
2077 push @$cmd, '-startdate' , $conf ->{ startdate
} if $conf ->{ startdate
};
2079 push @$cmd, '-S' if $conf ->{ freeze
};
2081 # set keyboard layout
2082 my $kb = $conf ->{ keyboard
} || $defaults ->{ keyboard
};
2083 push @$cmd, '-k' , $kb if $kb ;
2086 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2087 #push @$cmd, '-soundhw', 'es1370';
2088 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2089 $pciaddr = print_pci_addr
( "balloon0" );
2090 push @$cmd, '-device' , "virtio-balloon-pci,id=balloon0 $pciaddr " if $conf ->{ balloon
};
2092 if ( $conf ->{ watchdog
}) {
2093 my $wdopts = parse_watchdog
( $conf ->{ watchdog
});
2094 $pciaddr = print_pci_addr
( "watchdog" );
2095 my $watchdog = $wdopts ->{ model
} || 'i6300esb' ;
2096 push @$cmd, '-device' , " $watchdog$pciaddr " ;
2097 push @$cmd, '-watchdog-action' , $wdopts ->{ action
} if $wdopts ->{ action
};
2101 my $scsicontroller = {};
2103 foreach_drive
( $conf, sub {
2104 my ( $ds, $drive ) = @_ ;
2107 PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
});
2108 push @$vollist, $drive ->{ file
};
2111 $use_virtio = 1 if $ds =~ m/^virtio/ ;
2112 if ( $drive ->{ interface
} eq 'scsi' ) {
2114 my $controller = int ( $drive ->{ index } / $maxdev );
2115 $pciaddr = print_pci_addr
( "scsi $controller " );
2116 push @$cmd, '-device' , "lsi,id=scsi $controller$pciaddr " if ! $scsicontroller ->{ $controller };
2117 $scsicontroller ->{ $controller }= 1 ;
2119 my $tmp = print_drive_full
( $storecfg, $vmid, $drive );
2120 $tmp .= ",boot=on" if $conf ->{ bootdisk
} && ( $conf ->{ bootdisk
} eq $ds );
2121 push @$cmd, '-drive' , $tmp ;
2122 push @$cmd, '-device' , print_drivedevice_full
( $storecfg,$vmid, $drive );
2125 push @$cmd, '-m' , $conf ->{ memory
} || $defaults ->{ memory
};
2129 foreach my $k ( sort keys %$conf ) {
2130 next if $k !~ m/^net(\d+)$/ ;
2133 die "got strange net id ' $i ' \n " if $i >= ${ MAX_NETS
};
2135 if ( $conf ->{ "net $i " } && ( my $net = parse_net
( $conf ->{ "net $i " }))) {
2139 my $ifname = "tap${vmid}i $i " ;
2141 # kvm uses TUNSETIFF ioctl, and that limits ifname length
2142 die "interface name ' $ifname ' is too long (max 15 character) \n "
2143 if length ( $ifname ) >= 16 ;
2145 my $device = $net ->{ model
};
2146 my $vhostparam = '' ;
2147 if ( $net ->{ model
} eq 'virtio' ) {
2149 $device = 'virtio-net-pci' ;
2150 $vhostparam = ',vhost=on' if $kernel_has_vhost_net ;
2153 if ( $net ->{ bridge
}) {
2154 push @$cmd, '-netdev' , "type=tap,id=${k},ifname=${ifname},script=/var/lib/qemu-server/pve-bridge $vhostparam " ;
2156 push @$cmd, '-netdev' , "type=user,id=${k},hostname= $vmname " ;
2159 # qemu > 0.15 always try to boot from network - we disable that by
2160 # not loading the pxe rom file
2161 my $extra = (! $conf ->{ boot
} || ( $conf ->{ boot
} !~ m/n/ )) ?
2163 $pciaddr = print_pci_addr
( "${k}" );
2164 push @$cmd, '-device' , " $device,$ {extra}mac= $net ->{macaddr},netdev=${k} $pciaddr " ;
2168 push @$cmd, '-net' , 'none' if ! $foundnet ;
2170 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2171 # when the VM uses virtio devices.
2172 if (! $use_virtio && $have_ovz ) {
2174 my $cpuunits = defined ( $conf ->{ cpuunits
}) ?
2175 $conf ->{ cpuunits
} : $defaults ->{ cpuunits
};
2177 push @$cmd, '-cpuunits' , $cpuunits if $cpuunits ;
2179 # fixme: cpulimit is currently ignored
2180 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2184 if ( $conf ->{ args
}) {
2185 my $aa = PVE
:: Tools
:: split_args
( $conf ->{ args
});
2189 return wantarray ?
( $cmd, $vollist ) : $cmd ;
2194 return "${var_run_tmpdir}/ $vmid .vnc" ;
2197 sub monitor_socket
{
2199 return "${var_run_tmpdir}/ $vmid .mon" ;
2204 return "${var_run_tmpdir}/ $vmid .pid" ;
2207 sub next_migrate_port
{
2209 for ( my $p = 60000 ; $p < 60010 ; $p++ ) {
2211 my $sock = IO
:: Socket
:: INET-
> new ( Listen
=> 5 ,
2212 LocalAddr
=> 'localhost' ,
2223 die "unable to find free migration port" ;
2226 sub vm_devices_list
{
2229 my $res = vm_monitor_command
( $vmid, "info pci" , 1 );
2231 my @lines = split ( " \n " , $res );
2237 foreach my $line ( @lines ) {
2239 if ( $line =~ m/^Bus (\d+), device (\d+), function (\d+):$/ ) {
2243 if ( $line =~ m/^id "([a-z][a-z_\-]*\d*)"$/ ) {
2245 $devices ->{ $id }->{ bus
}= $bus ;
2246 $devices ->{ $id }->{ addr
}= $addr ;
2254 my ( $storecfg, $conf, $vmid, $deviceid, $device ) = @_ ;
2255 return if ! check_running
( $vmid ) || ! $conf ->{ hotplug
} || $conf ->{ $deviceid };
2257 if ( $deviceid =~ m/^(virtio)(\d+)$/ ) {
2259 my $drive = print_drive_full
( $storecfg, $vmid, $device );
2260 my $ret = vm_monitor_command
( $vmid, "drive_add auto $drive " , 1 );
2261 # If the command succeeds qemu prints: "OK"
2262 if ( $ret !~ m/OK/s ) {
2263 die "adding drive failed: $ret " ;
2266 my $devicefull = print_drivedevice_full
( $storecfg, $vmid, $device );
2267 $ret = vm_monitor_command
( $vmid, "device_add $devicefull " , 1 );
2269 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2270 die 'error on hotplug device : $ret ' if $ret ne "" ;
2273 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2274 my $devices_list = vm_devices_list
( $vmid );
2275 return if defined ( $devices_list ->{ $deviceid });
2279 die "error on hotplug device $deviceid " ;
2283 my ( $vmid, $conf, $deviceid ) = @_ ;
2285 return if ! check_running
( $vmid ) || ! $conf ->{ hotplug
};
2287 die "can't unplug bootdisk" if $conf ->{ bootdisk
} eq $deviceid ;
2289 if ( $deviceid =~ m/^(virtio)(\d+)$/ ){
2291 my $ret = vm_monitor_command
( $vmid, "drive_del drive- $deviceid " , 1 );
2293 if ( $ret =~ m/Device \'.*?\' not found/s ) {
2294 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2296 elsif ( $ret ne "" ) {
2297 die "deleting drive $deviceid failed : $ret " ;
2300 $ret = vm_monitor_command
( $vmid, "device_del $deviceid " , 1 );
2302 die 'detaching device $deviceid failed : $ret ' if $ret ne "" ;
2306 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2307 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2308 my $devices_list = vm_devices_list
( $vmid );
2309 return if ! defined ( $devices_list ->{ $deviceid });
2312 die "error on hot-plugging device $deviceid " ;
2318 my ( $storecfg, $vmid, $statefile, $skiplock ) = @_ ;
2320 lock_config
( $vmid, sub {
2321 my $conf = load_config
( $vmid );
2323 check_lock
( $conf ) if ! $skiplock ;
2325 if ( check_running
( $vmid )) {
2326 my $msg = "VM $vmid already running - start failed \n " ;
2327 syslog
( 'err' , $msg );
2330 syslog
( 'info' , "VM $vmid start" );
2334 my $migrate_port = 0 ;
2337 if ( $statefile eq 'tcp' ) {
2338 $migrate_port = next_migrate_port
();
2339 $migrate_uri = "tcp:localhost:${migrate_port}" ;
2341 if (- f
$statefile ) {
2342 $migrate_uri = "exec:cat $statefile " ;
2344 warn "state file ' $statefile ' does not exist - doing normal startup \n " ;
2349 my $defaults = load_defaults
();
2351 my ( $cmd, $vollist ) = config_to_command
( $storecfg, $vmid, $conf, $defaults, $migrate_uri );
2353 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
2354 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
2356 my $info = pci_device_info
( "0000: $d ->{pciid}" );
2357 die "IOMMU not present \n " if ! check_iommu_support
();
2358 die "no pci device info for device ' $d ->{pciid}' \n " if ! $info ;
2359 die "can't unbind pci device ' $d ->{pciid}' \n " if ! pci_dev_bind_to_stub
( $info );
2360 die "can't reset pci device ' $d ->{pciid}' \n " if ! pci_dev_reset
( $info );
2363 PVE
:: Storage
:: activate_volumes
( $storecfg, $vollist );
2365 eval { run_command
( $cmd, timeout
=> $migrate_uri ?
undef : 30 ); };
2370 my $msg = "start failed: $err " ;
2371 syslog
( 'err' , "VM $vmid $msg " );
2377 if ( $statefile eq 'tcp' ) {
2378 print "migration listens on port $migrate_port\n " ;
2381 # fixme: send resume - is that necessary ?
2382 eval { vm_monitor_command
( $vmid, "cont" , 1 ) };
2386 if ( my $migrate_speed =
2387 $conf ->{ migrate_speed
} || $defaults ->{ migrate_speed
}) {
2388 my $cmd = "migrate_set_speed ${migrate_speed}m" ;
2389 eval { vm_monitor_command
( $vmid, $cmd, 1 ); };
2392 if ( my $migrate_downtime =
2393 $conf ->{ migrate_downtime
} || $defaults ->{ migrate_downtime
}) {
2394 my $cmd = "migrate_set_downtime ${migrate_downtime}" ;
2395 eval { vm_monitor_command
( $vmid, $cmd, 1 ); };
2398 vm_balloonset
( $vmid, $conf ->{ balloon
}) if $conf ->{ balloon
};
2403 my ( $fh, $timeout ) = @_ ;
2405 my $sel = new IO
:: Select
;
2412 while ( scalar ( @ready = $sel -> can_read ( $timeout ))) {
2414 if ( $count = $fh -> sysread ( $buf, 8192 )) {
2415 if ( $buf =~ /^(.*)\(qemu\) $/s ) {
2422 if (! defined ( $count )) {
2429 die "monitor read timeout \n " if ! scalar ( @ready );
2434 sub vm_monitor_command
{
2435 my ( $vmid, $cmdstr, $nolog, $nocheck ) = @_ ;
2439 syslog
( "info" , "VM $vmid monitor command ' $cmdstr '" ) if ! $nolog ;
2442 die "VM not running \n " if ! check_running
( $vmid, $nocheck );
2444 my $sname = monitor_socket
( $vmid );
2446 my $sock = IO
:: Socket
:: UNIX-
> new ( Peer
=> $sname ) ||
2447 die "unable to connect to VM $vmid socket - $!\n " ;
2451 # hack: migrate sometime blocks the monitor (when migrate_downtime
2453 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2454 $timeout = 60 * 60 ; # 1 hour
2458 my $data = __read_avail
( $sock, $timeout );
2460 if ( $data !~ m/^QEMU\s+(\S+)\s+monitor\s/ ) {
2461 die "got unexpected qemu monitor banner \n " ;
2464 my $sel = new IO
:: Select
;
2467 if (! scalar ( my @ready = $sel -> can_write ( $timeout ))) {
2468 die "monitor write error - timeout" ;
2471 my $fullcmd = " $cmdstr\r " ;
2474 if (!( $b = $sock -> syswrite ( $fullcmd )) || ( $b != length ( $fullcmd ))) {
2475 die "monitor write error - $! " ;
2478 return if ( $cmdstr eq 'q' ) || ( $cmdstr eq 'quit' );
2482 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2483 $timeout = 60 * 60 ; # 1 hour
2484 } elsif ( $cmdstr =~ m/^(eject|change)/ ) {
2485 $timeout = 60 ; # note: cdrom mount command is slow
2487 if ( $res = __read_avail
( $sock, $timeout )) {
2489 my @lines = split ( " \r ? \n " , $res );
2491 shift @lines if $lines [ 0 ] !~ m/^unknown command/ ; # skip echo
2493 $res = join ( " \n " , @lines );
2501 syslog
( "err" , "VM $vmid monitor command failed - $err " );
2508 sub vm_commandline
{
2509 my ( $storecfg, $vmid ) = @_ ;
2511 my $conf = load_config
( $vmid );
2513 my $defaults = load_defaults
();
2515 my $cmd = config_to_command
( $storecfg, $vmid, $conf, $defaults );
2517 return join ( ' ' , @$cmd );
2521 my ( $vmid, $skiplock ) = @_ ;
2523 lock_config
( $vmid, sub {
2525 my $conf = load_config
( $vmid );
2527 check_lock
( $conf ) if ! $skiplock ;
2529 syslog
( "info" , "VM $vmid sending 'reset'" );
2531 vm_monitor_command
( $vmid, "system_reset" , 1 );
2536 my ( $vmid, $skiplock ) = @_ ;
2538 lock_config
( $vmid, sub {
2540 my $conf = load_config
( $vmid );
2542 check_lock
( $conf ) if ! $skiplock ;
2544 syslog
( "info" , "VM $vmid sending 'shutdown'" );
2546 vm_monitor_command
( $vmid, "system_powerdown" , 1 );
2550 # Note: use $nockeck to skip tests if VM configuration file exists.
2551 # We need that when migration VMs to other nodes (files already moved)
2553 my ( $vmid, $skiplock, $nocheck ) = @_ ;
2555 lock_config
( $vmid, sub {
2557 my $pid = check_running
( $vmid, $nocheck );
2560 syslog
( 'info' , "VM $vmid already stopped" );
2565 my $conf = load_config
( $vmid );
2566 check_lock
( $conf ) if ! $skiplock ;
2569 syslog
( "info" , "VM $vmid stopping" );
2571 eval { vm_monitor_command
( $vmid, "quit" , 1 , $nocheck ); };
2577 my $timeout = 50 ; # fixme: how long?
2580 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2585 if ( $count >= $timeout ) {
2586 syslog
( 'info' , "VM $vmid still running - terminating now with SIGTERM" );
2590 syslog
( 'info' , "VM $vmid quit failed - terminating now with SIGTERM" );
2598 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2603 if ( $count >= $timeout ) {
2604 syslog
( 'info' , "VM $vmid still running - terminating now with SIGKILL \n " );
2608 fairsched_rmnod
( $vmid ); # try to destroy group
2613 my ( $vmid, $skiplock ) = @_ ;
2615 lock_config
( $vmid, sub {
2617 my $conf = load_config
( $vmid );
2619 check_lock
( $conf ) if ! $skiplock ;
2621 syslog
( "info" , "VM $vmid suspend" );
2623 vm_monitor_command
( $vmid, "stop" , 1 );
2628 my ( $vmid, $skiplock ) = @_ ;
2630 lock_config
( $vmid, sub {
2632 my $conf = load_config
( $vmid );
2634 check_lock
( $conf ) if ! $skiplock ;
2636 syslog
( "info" , "VM $vmid resume" );
2638 vm_monitor_command
( $vmid, "cont" , 1 );
2643 my ( $vmid, $skiplock, $key ) = @_ ;
2645 lock_config
( $vmid, sub {
2647 my $conf = load_config
( $vmid );
2649 check_lock
( $conf ) if ! $skiplock ;
2651 syslog
( "info" , "VM $vmid sending key $key " );
2653 vm_monitor_command
( $vmid, "sendkey $key " , 1 );
2658 my ( $storecfg, $vmid, $skiplock ) = @_ ;
2660 lock_config
( $vmid, sub {
2662 my $conf = load_config
( $vmid );
2664 check_lock
( $conf ) if ! $skiplock ;
2666 syslog
( "info" , "VM $vmid destroy called (removing all data)" );
2669 if (! check_running
( $vmid )) {
2670 fairsched_rmnod
( $vmid ); # try to destroy group
2671 destroy_vm
( $storecfg, $vmid );
2673 die "VM is running \n " ;
2680 syslog
( "err" , "VM $vmid destroy failed - $err " );
2689 $timeout = 3 * 60 if ! $timeout ;
2691 my $vzlist = vzlist
();
2693 foreach my $vmid ( keys %$vzlist ) {
2694 next if ! $vzlist ->{ $vmid }->{ pid
};
2700 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs \n " ;
2701 syslog
( 'info' , $msg );
2704 foreach my $vmid ( keys %$vzlist ) {
2705 next if ! $vzlist ->{ $vmid }->{ pid
};
2706 eval { vm_shutdown
( $vmid, 1 ); };
2707 print STDERR
$@ if $@ ;
2711 my $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2713 while (( $try < $maxtries ) && $count ) {
2719 foreach my $vmid ( keys %$vzlist ) {
2720 next if ! $vzlist ->{ $vmid }->{ pid
};
2728 foreach my $vmid ( keys %$vzlist ) {
2729 next if ! $vzlist ->{ $vmid }->{ pid
};
2731 $msg = "VM $vmid still running - sending stop now \n " ;
2732 syslog
( 'info' , $msg );
2735 eval { vm_monitor_command
( $vmid, "quit" , 1 ); };
2736 print STDERR
$@ if $@ ;
2741 $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2743 while (( $try < $maxtries ) && $count ) {
2749 foreach my $vmid ( keys %$vzlist ) {
2750 next if ! $vzlist ->{ $vmid }->{ pid
};
2758 foreach my $vmid ( keys %$vzlist ) {
2759 next if ! $vzlist ->{ $vmid }->{ pid
};
2761 $msg = "VM $vmid still running - terminating now with SIGTERM \n " ;
2762 syslog
( 'info' , $msg );
2764 kill 15 , $vzlist ->{ $vmid }->{ pid
};
2767 # this is called by system shotdown scripts, so remaining
2768 # processes gets killed anyways (no need to send kill -9 here)
2770 $msg = "Qemu Server stopped \n " ;
2771 syslog
( 'info' , $msg );
2779 my ( $filename, $buf ) = @_ ;
2781 my $fh = IO
:: File-
> new ( $filename, "w" );
2782 return undef if ! $fh ;
2784 my $res = print $fh $buf ;
2791 sub pci_device_info
{
2796 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/ ;
2797 my ( $domain, $bus, $slot, $func ) = ( $1, $2, $3, $4 );
2799 my $irq = file_read_firstline
( " $pcisysfs/devices/$name/irq " );
2800 return undef if ! defined ( $irq ) || $irq !~ m/^\d+$/ ;
2802 my $vendor = file_read_firstline
( " $pcisysfs/devices/$name/vendor " );
2803 return undef if ! defined ( $vendor ) || $vendor !~ s/^0x// ;
2805 my $product = file_read_firstline
( " $pcisysfs/devices/$name/device " );
2806 return undef if ! defined ( $product ) || $product !~ s/^0x// ;
2811 product
=> $product,
2817 has_fl_reset
=> - f
" $pcisysfs/devices/$name/reset " || 0 ,
2826 my $name = $dev ->{ name
};
2828 my $fn = " $pcisysfs/devices/$name/reset " ;
2830 return file_write
( $fn, "1" );
2833 sub pci_dev_bind_to_stub
{
2836 my $name = $dev ->{ name
};
2838 my $testdir = " $pcisysfs/drivers/pci -stub/ $name " ;
2839 return 1 if - d
$testdir ;
2841 my $data = " $dev ->{vendor} $dev ->{product}" ;
2842 return undef if ! file_write
( " $pcisysfs/drivers/pci -stub/new_id" , $data );
2844 my $fn = " $pcisysfs/devices/$name/driver/unbind " ;
2845 if (! file_write
( $fn, $name )) {
2846 return undef if - f
$fn ;
2849 $fn = " $pcisysfs/drivers/pci -stub/bind" ;
2850 if (! - d
$testdir ) {
2851 return undef if ! file_write
( $fn, $name );
2857 sub print_pci_addr
{
2862 #addr1 : ide,parallel,serial (motherboard)
2863 #addr2 : first videocard
2864 balloon0
=> { bus
=> 0 , addr
=> 3 },
2865 watchdog
=> { bus
=> 0 , addr
=> 4 },
2866 scsi0
=> { bus
=> 0 , addr
=> 5 },
2867 scsi1
=> { bus
=> 0 , addr
=> 6 },
2868 virtio0
=> { bus
=> 0 , addr
=> 10 },
2869 virtio1
=> { bus
=> 0 , addr
=> 11 },
2870 virtio2
=> { bus
=> 0 , addr
=> 12 },
2871 virtio3
=> { bus
=> 0 , addr
=> 13 },
2872 virtio4
=> { bus
=> 0 , addr
=> 14 },
2873 virtio5
=> { bus
=> 0 , addr
=> 15 },
2874 hostpci0
=> { bus
=> 0 , addr
=> 16 },
2875 hostpci1
=> { bus
=> 0 , addr
=> 17 },
2876 net0
=> { bus
=> 0 , addr
=> 18 },
2877 net1
=> { bus
=> 0 , addr
=> 19 },
2878 net2
=> { bus
=> 0 , addr
=> 20 },
2879 net3
=> { bus
=> 0 , addr
=> 21 },
2880 net4
=> { bus
=> 0 , addr
=> 22 },
2881 net5
=> { bus
=> 0 , addr
=> 23 },
2882 #addr29 : usb-host (pve-usb.cfg)
2885 if ( defined ( $devices ->{ $id }->{ bus
}) && defined ( $devices ->{ $id }->{ addr
})) {
2886 my $addr = sprintf ( "0x %x " , $devices ->{ $id }->{ addr
});
2887 $res = ",bus=pci. $devices ->{ $id }->{bus},addr= $addr " ;
2894 my ( $vmid, $value ) = @_ ;
2896 vm_monitor_command
( $vmid, "balloon $value " , 1 );
2899 # vzdump restore implementaion
2901 sub archive_read_firstfile
{
2902 my $archive = shift ;
2904 die "ERROR: file ' $archive ' does not exist \n " if ! - f
$archive ;
2906 # try to detect archive type first
2907 my $pid = open ( TMP
, "tar tf ' $archive '|" ) ||
2908 die "unable to open file ' $archive ' \n " ;
2909 my $firstfile = < TMP
>;
2913 die "ERROR: archive contaions no data \n " if ! $firstfile ;
2919 sub restore_cleanup
{
2920 my $statfile = shift ;
2922 print STDERR
"starting cleanup \n " ;
2924 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
2925 while ( defined ( my $line = < $fd >)) {
2926 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
2929 if ( $volid =~ m
|^/|) {
2930 unlink $volid || die 'unlink failed \n ' ;
2932 my $cfg = cfs_read_file
( 'storage.cfg' );
2933 PVE
:: Storage
:: vdisk_free
( $cfg, $volid );
2935 print STDERR
"temporary volume ' $volid ' sucessfuly removed \n " ;
2937 print STDERR
"unable to cleanup ' $volid ' - $@ " if $@ ;
2939 print STDERR
"unable to parse line in statfile - $line " ;
2946 sub restore_archive
{
2947 my ( $archive, $vmid, $opts ) = @_ ;
2949 if ( $archive ne '-' ) {
2950 my $firstfile = archive_read_firstfile
( $archive );
2951 die "ERROR: file ' $archive ' dos not lock like a QemuServer vzdump backup \n "
2952 if $firstfile ne 'qemu-server.conf' ;
2955 my $tocmd = "/usr/lib/qemu-server/qmextract" ;
2957 $tocmd .= " --storage " . PVE
:: Tools
:: shellquote
( $opts ->{ storage
}) if $opts ->{ storage
};
2958 $tocmd .= ' --prealloc' if $opts ->{ prealloc
};
2959 $tocmd .= ' --info' if $opts ->{ info
};
2961 # tar option "xf" does not autodetect compression when read fron STDIN,
2962 # so we pipe to zcat
2963 my $cmd = "zcat -f|tar xf " . PVE
:: Tools
:: shellquote
( $archive ) . " " .
2964 PVE
:: Tools
:: shellquote
( "--to-command= $tocmd " );
2966 my $tmpdir = "/var/tmp/vzdumptmp $$ " ;
2969 local $ENV { VZDUMP_TMPDIR
} = $tmpdir ;
2970 local $ENV { VZDUMP_VMID
} = $vmid ;
2972 my $conffile = PVE
:: QemuServer
:: config_file
( $vmid );
2973 my $tmpfn = " $conffile . $$ .tmp" ;
2975 # disable interrupts (always do cleanups)
2976 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = sub {
2977 print STDERR
"got interrupt - ignored \n " ;
2982 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = $SIG { PIPE
} = sub {
2983 die "interrupted by signal \n " ;
2986 if ( $archive eq '-' ) {
2987 print "extracting archive from STDIN \n " ;
2988 run_command
( $cmd, input
=> "<&STDIN" );
2990 print "extracting archive ' $archive ' \n " ;
2994 return if $opts ->{ info
};
2998 my $statfile = " $tmpdir/qmrestore .stat" ;
2999 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
3000 while ( defined ( my $line = < $fd >)) {
3001 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
3002 $map ->{ $1 } = $2 if $1 ;
3004 print STDERR
"unable to parse line in statfile - $line\n " ;
3010 my $confsrc = " $tmpdir/qemu -server.conf" ;
3012 my $srcfd = new IO
:: File
( $confsrc, "r" ) ||
3013 die "unable to open file ' $confsrc ' \n " ;
3015 my $outfd = new IO
:: File
( $tmpfn, "w" ) ||
3016 die "unable to write config for VM $vmid\n " ;
3020 while ( defined ( my $line = < $srcfd >)) {
3021 next if $line =~ m/^\#vzdump\#/ ;
3022 next if $line =~ m/^lock:/ ;
3023 next if $line =~ m/^unused\d+:/ ;
3025 if (( $line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/ )) {
3026 # try to convert old 1.X settings
3027 my ( $id, $ind, $ethcfg ) = ( $1, $2, $3 );
3028 foreach my $devconfig ( PVE
:: Tools
:: split_list
( $ethcfg )) {
3029 my ( $model, $macaddr ) = split ( /\=/ , $devconfig );
3030 $macaddr = PVE
:: Tools
:: random_ether_addr
() if ! $macaddr || $opts ->{ unique
};
3033 bridge
=> "vmbr $ind " ,
3034 macaddr
=> $macaddr,
3036 my $netstr = print_net
( $net );
3037 print $outfd "net${netcount}: $netstr\n " ;
3040 } elsif (( $line =~ m/^(net\d+):\s*(\S+)\s*$/ ) && ( $opts ->{ unique
})) {
3041 my ( $id, $netstr ) = ( $1, $2 );
3042 my $net = parse_net
( $netstr );
3043 $net ->{ macaddr
} = PVE
:: Tools
:: random_ether_addr
() if $net ->{ macaddr
};
3044 $netstr = print_net
( $net );
3045 print $outfd " $id : $netstr\n " ;
3046 } elsif ( $line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/ ) {
3049 if ( $line =~ m/backup=no/ ) {
3050 print $outfd "# $line " ;
3051 } elsif ( $virtdev && $map ->{ $virtdev }) {
3052 my $di = PVE
:: QemuServer
:: parse_drive
( $virtdev, $value );
3053 $di ->{ file
} = $map ->{ $virtdev };
3054 $value = PVE
:: QemuServer
:: print_drive
( $vmid, $di );
3055 print $outfd " $virtdev : $value\n " ;
3073 restore_cleanup
( " $tmpdir/qmrestore .stat" ) if ! $opts ->{ info
};
3080 rename $tmpfn, $conffile ||
3081 die "unable to commit configuration file ' $conffile ' \n " ;