]>
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|unsafe] [,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|unsafe] [,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|unsafe] [,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|unsafe)$/ ;
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 my $cpucount = $cpuinfo ->{ cpus
} || 1 ;
1803 foreach my $vmid ( keys %$list ) {
1804 next if $opt_vmid && ( $vmid ne $opt_vmid );
1806 my $cfspath = cfs_config_path
( $vmid );
1807 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath ) || {};
1810 $d ->{ pid
} = $list ->{ $vmid }->{ pid
};
1812 # fixme: better status?
1813 $d ->{ status
} = $list ->{ $vmid }->{ pid
} ?
'running' : 'stopped' ;
1815 my ( $size, $used ) = disksize
( $storecfg, $conf );
1816 if ( defined ( $size ) && defined ( $used )) {
1818 $d ->{ maxdisk
} = $size ;
1824 $d ->{ cpus
} = ( $conf ->{ sockets
} || 1 ) * ( $conf ->{ cores
} || 1 );
1825 $d ->{ cpus
} = $cpucount if $d ->{ cpus
} > $cpucount ;
1827 $d ->{ name
} = $conf ->{ name
} || "VM $vmid " ;
1828 $d ->{ maxmem
} = $conf ->{ memory
} ?
$conf ->{ memory
}*( 1024 * 1024 ) : 0 ;
1838 $d ->{ diskwrite
} = 0 ;
1843 my $netdev = PVE
:: ProcFSTools
:: read_proc_net_dev
();
1844 foreach my $dev ( keys %$netdev ) {
1845 next if $dev !~ m/^tap([1-9]\d*)i/ ;
1847 my $d = $res ->{ $vmid };
1850 $d ->{ netout
} += $netdev ->{ $dev }->{ receive
};
1851 $d ->{ netin
} += $netdev ->{ $dev }->{ transmit
};
1854 my $ctime = gettimeofday
;
1856 foreach my $vmid ( keys %$list ) {
1858 my $d = $res ->{ $vmid };
1859 my $pid = $d ->{ pid
};
1862 if ( my $fh = IO
:: File-
> new ( "/proc/ $pid/io " , "r" )) {
1864 while ( defined ( my $line = < $fh >)) {
1865 if ( $line =~ m/^([rw]char):\s+(\d+)$/ ) {
1870 $d ->{ diskread
} = $data ->{ rchar
} || 0 ;
1871 $d ->{ diskwrite
} = $data ->{ wchar
} || 0 ;
1874 my $pstat = PVE
:: ProcFSTools
:: read_proc_pid_stat
( $pid );
1875 next if ! $pstat ; # not running
1877 my $used = $pstat ->{ utime } + $pstat ->{ stime
};
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 } = {
1895 my $dtime = ( $ctime - $old ->{ time }) * $cpucount * $cpuinfo ->{ user_hz
};
1897 if ( $dtime > 1000 ) {
1898 my $dutime = $used - $old ->{ used
};
1900 $d ->{ cpu
} = (( $dutime/$dtime )* $cpucount ) / $d ->{ cpus
};
1901 $last_proc_pid_stat ->{ $pid } = {
1907 $d ->{ cpu
} = $old ->{ cpu
};
1915 my ( $conf, $func ) = @_ ;
1917 foreach my $ds ( keys %$conf ) {
1918 next if ! valid_drivename
( $ds );
1920 my $drive = parse_drive
( $ds, $conf ->{ $ds });
1923 & $func ( $ds, $drive );
1927 sub config_to_command
{
1928 my ( $storecfg, $vmid, $conf, $defaults, $migrate_uri ) = @_ ;
1932 my $kvmver = kvm_user_version
();
1933 my $vernum = 0 ; # unknown
1934 if ( $kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/ ) {
1935 $vernum = $1*1000000+$2*1000+$3 ;
1938 die "detected old qemu-kvm binary ( $kvmver ) \n " if $vernum < 14000 ;
1940 my $have_ovz = - f
'/proc/vz/vestat' ;
1942 push @$cmd, '/usr/bin/kvm' ;
1944 push @$cmd, '-id' , $vmid ;
1948 my $socket = monitor_socket
( $vmid );
1949 push @$cmd, '-chardev' , "socket,id=monitor,path= $socket,server,nowait " ;
1950 push @$cmd, '-mon' , "chardev=monitor,mode=readline" ;
1952 $socket = vnc_socket
( $vmid );
1953 push @$cmd, '-vnc' , "unix: $socket,x509,password " ;
1955 push @$cmd, '-pidfile' , pidfile_name
( $vmid );
1957 push @$cmd, '-daemonize' ;
1959 push @$cmd, '-incoming' , $migrate_uri if $migrate_uri ;
1961 # include usb device config
1962 push @$cmd, '-readconfig' , '/usr/share/qemu-server/pve-usb.cfg' ;
1964 # enable absolute mouse coordinates (needed by vnc)
1965 my $tablet = defined ( $conf ->{ tablet
}) ?
$conf ->{ tablet
} : $defaults ->{ tablet
};
1966 push @$cmd, '-device' , 'usb-tablet,bus=ehci.0,port=6' if $tablet ;
1969 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
1970 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
1972 $pciaddr = print_pci_addr
( "hostpci $i " );
1973 push @$cmd, '-device' , "pci-assign,host= $d ->{pciid},id=hostpci $i$pciaddr " ;
1977 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1978 my $d = parse_usb_device
( $conf ->{ "usb $i " });
1980 if ( $d ->{ vendorid
} && $d ->{ productid
}) {
1981 push @$cmd, '-device' , "usb-host,vendorid= $d ->{vendorid},productid= $d ->{productid}" ;
1982 } elsif ( defined ( $d ->{ hostbus
}) && defined ( $d ->{ hostport
})) {
1983 push @$cmd, '-device' , "usb-host,hostbus= $d ->{hostbus},hostport= $d ->{hostport}" ;
1988 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
1989 if ( my $path = $conf ->{ "serial $i " }) {
1990 die "no such serial device \n " if ! - c
$path ;
1991 push @$cmd, '-chardev' , "tty,id=serial $i,path = $path " ;
1992 push @$cmd, '-device' , "isa-serial,chardev=serial $i " ;
1997 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
1998 if ( my $path = $conf ->{ "parallel $i " }) {
1999 die "no such parallel device \n " if ! - c
$path ;
2000 push @$cmd, '-chardev' , "parport,id=parallel $i,path = $path " ;
2001 push @$cmd, '-device' , "isa-parallel,chardev=parallel $i " ;
2005 my $vmname = $conf ->{ name
} || "vm $vmid " ;
2007 push @$cmd, '-name' , $vmname ;
2010 $sockets = $conf ->{ smp
} if $conf ->{ smp
}; # old style - no longer iused
2011 $sockets = $conf ->{ sockets
} if $conf ->{ sockets
};
2013 my $cores = $conf ->{ cores
} || 1 ;
2017 push @$cmd, '-smp' , "sockets= $sockets,cores = $cores " ;
2019 push @$cmd, '-cpu' , $conf ->{ cpu
} if $conf ->{ cpu
};
2021 push @$cmd, '-nodefaults' ;
2023 my $bootorder = $conf ->{ boot
} || $confdesc ->{ boot
}->{ default };
2024 push @$cmd, '-boot' , "menu=on,order= $bootorder " ;
2026 push @$cmd, '-no-acpi' if defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 ;
2028 push @$cmd, '-no-reboot' if defined ( $conf ->{ reboot
}) && $conf ->{ reboot
} == 0 ;
2030 my $vga = $conf ->{ vga
};
2032 if ( $conf ->{ ostype
} && ( $conf ->{ ostype
} eq 'win7' || $conf ->{ ostype
} eq 'w2k8' )) {
2039 push @$cmd, '-vga' , $vga if $vga ; # for kvm 77 and later
2042 my $tdf = defined ( $conf ->{ tdf
}) ?
$conf ->{ tdf
} : $defaults ->{ tdf
};
2043 push @$cmd, '-tdf' if $tdf ;
2045 my $nokvm = defined ( $conf ->{ kvm
}) && $conf ->{ kvm
} == 0 ?
1 : 0 ;
2047 if ( my $ost = $conf ->{ ostype
}) {
2048 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2050 if ( $ost =~ m/^w/ ) { # windows
2051 push @$cmd, '-localtime' if ! defined ( $conf ->{ localtime });
2053 # use rtc-td-hack when acpi is enabled
2054 if (!( defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 )) {
2055 push @$cmd, '-rtc-td-hack' ;
2066 push @$cmd, '-no-kvm' ;
2068 die "No accelerator found! \n " if ! $cpuinfo ->{ hvm
};
2071 push @$cmd, '-localtime' if $conf ->{ localtime };
2073 push @$cmd, '-startdate' , $conf ->{ startdate
} if $conf ->{ startdate
};
2075 push @$cmd, '-S' if $conf ->{ freeze
};
2077 # set keyboard layout
2078 my $kb = $conf ->{ keyboard
} || $defaults ->{ keyboard
};
2079 push @$cmd, '-k' , $kb if $kb ;
2082 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2083 #push @$cmd, '-soundhw', 'es1370';
2084 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2085 $pciaddr = print_pci_addr
( "balloon0" );
2086 push @$cmd, '-device' , "virtio-balloon-pci,id=balloon0 $pciaddr " if $conf ->{ balloon
};
2088 if ( $conf ->{ watchdog
}) {
2089 my $wdopts = parse_watchdog
( $conf ->{ watchdog
});
2090 $pciaddr = print_pci_addr
( "watchdog" );
2091 my $watchdog = $wdopts ->{ model
} || 'i6300esb' ;
2092 push @$cmd, '-device' , " $watchdog$pciaddr " ;
2093 push @$cmd, '-watchdog-action' , $wdopts ->{ action
} if $wdopts ->{ action
};
2097 my $scsicontroller = {};
2099 foreach_drive
( $conf, sub {
2100 my ( $ds, $drive ) = @_ ;
2103 PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
});
2104 push @$vollist, $drive ->{ file
};
2107 $use_virtio = 1 if $ds =~ m/^virtio/ ;
2108 if ( $drive ->{ interface
} eq 'scsi' ) {
2110 my $controller = int ( $drive ->{ index } / $maxdev );
2111 $pciaddr = print_pci_addr
( "scsi $controller " );
2112 push @$cmd, '-device' , "lsi,id=scsi $controller$pciaddr " if ! $scsicontroller ->{ $controller };
2113 $scsicontroller ->{ $controller }= 1 ;
2115 my $tmp = print_drive_full
( $storecfg, $vmid, $drive );
2116 $tmp .= ",boot=on" if $conf ->{ bootdisk
} && ( $conf ->{ bootdisk
} eq $ds );
2117 push @$cmd, '-drive' , $tmp ;
2118 push @$cmd, '-device' , print_drivedevice_full
( $storecfg,$vmid, $drive );
2121 push @$cmd, '-m' , $conf ->{ memory
} || $defaults ->{ memory
};
2125 foreach my $k ( sort keys %$conf ) {
2126 next if $k !~ m/^net(\d+)$/ ;
2129 die "got strange net id ' $i ' \n " if $i >= ${ MAX_NETS
};
2131 if ( $conf ->{ "net $i " } && ( my $net = parse_net
( $conf ->{ "net $i " }))) {
2135 my $ifname = "tap${vmid}i $i " ;
2137 # kvm uses TUNSETIFF ioctl, and that limits ifname length
2138 die "interface name ' $ifname ' is too long (max 15 character) \n "
2139 if length ( $ifname ) >= 16 ;
2141 my $device = $net ->{ model
};
2142 my $vhostparam = '' ;
2143 if ( $net ->{ model
} eq 'virtio' ) {
2145 $device = 'virtio-net-pci' ;
2146 $vhostparam = ',vhost=on' if $kernel_has_vhost_net ;
2149 if ( $net ->{ bridge
}) {
2150 push @$cmd, '-netdev' , "type=tap,id=${k},ifname=${ifname},script=/var/lib/qemu-server/pve-bridge $vhostparam " ;
2152 push @$cmd, '-netdev' , "type=user,id=${k},hostname= $vmname " ;
2155 # qemu > 0.15 always try to boot from network - we disable that by
2156 # not loading the pxe rom file
2157 my $extra = (! $conf ->{ boot
} || ( $conf ->{ boot
} !~ m/n/ )) ?
2159 $pciaddr = print_pci_addr
( "${k}" );
2160 push @$cmd, '-device' , " $device,$ {extra}mac= $net ->{macaddr},netdev=${k} $pciaddr " ;
2164 push @$cmd, '-net' , 'none' if ! $foundnet ;
2166 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2167 # when the VM uses virtio devices.
2168 if (! $use_virtio && $have_ovz ) {
2170 my $cpuunits = defined ( $conf ->{ cpuunits
}) ?
2171 $conf ->{ cpuunits
} : $defaults ->{ cpuunits
};
2173 push @$cmd, '-cpuunits' , $cpuunits if $cpuunits ;
2175 # fixme: cpulimit is currently ignored
2176 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2180 if ( $conf ->{ args
}) {
2181 my $aa = PVE
:: Tools
:: split_args
( $conf ->{ args
});
2185 return wantarray ?
( $cmd, $vollist ) : $cmd ;
2190 return "${var_run_tmpdir}/ $vmid .vnc" ;
2193 sub monitor_socket
{
2195 return "${var_run_tmpdir}/ $vmid .mon" ;
2200 return "${var_run_tmpdir}/ $vmid .pid" ;
2203 sub next_migrate_port
{
2205 for ( my $p = 60000 ; $p < 60010 ; $p++ ) {
2207 my $sock = IO
:: Socket
:: INET-
> new ( Listen
=> 5 ,
2208 LocalAddr
=> 'localhost' ,
2219 die "unable to find free migration port" ;
2222 sub vm_devices_list
{
2225 my $res = vm_monitor_command
( $vmid, "info pci" , 1 );
2227 my @lines = split ( " \n " , $res );
2233 foreach my $line ( @lines ) {
2235 if ( $line =~ m/^Bus (\d+), device (\d+), function (\d+):$/ ) {
2239 if ( $line =~ m/^id "([a-z][a-z_\-]*\d*)"$/ ) {
2241 $devices ->{ $id }->{ bus
}= $bus ;
2242 $devices ->{ $id }->{ addr
}= $addr ;
2250 my ( $storecfg, $conf, $vmid, $deviceid, $device ) = @_ ;
2251 return if ! check_running
( $vmid ) || ! $conf ->{ hotplug
} || $conf ->{ $deviceid };
2253 if ( $deviceid =~ m/^(virtio)(\d+)$/ ) {
2255 my $drive = print_drive_full
( $storecfg, $vmid, $device );
2256 my $ret = vm_monitor_command
( $vmid, "drive_add auto $drive " , 1 );
2257 # If the command succeeds qemu prints: "OK"
2258 if ( $ret !~ m/OK/s ) {
2259 die "adding drive failed: $ret " ;
2262 my $devicefull = print_drivedevice_full
( $storecfg, $vmid, $device );
2263 $ret = vm_monitor_command
( $vmid, "device_add $devicefull " , 1 );
2265 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2266 die 'error on hotplug device : $ret ' if $ret ne "" ;
2269 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2270 my $devices_list = vm_devices_list
( $vmid );
2271 return if defined ( $devices_list ->{ $deviceid });
2275 die "error on hotplug device $deviceid " ;
2279 my ( $vmid, $conf, $deviceid ) = @_ ;
2281 return if ! check_running
( $vmid ) || ! $conf ->{ hotplug
};
2283 die "can't unplug bootdisk" if $conf ->{ bootdisk
} eq $deviceid ;
2285 if ( $deviceid =~ m/^(virtio)(\d+)$/ ){
2287 my $ret = vm_monitor_command
( $vmid, "drive_del drive- $deviceid " , 1 );
2289 if ( $ret =~ m/Device \'.*?\' not found/s ) {
2290 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2292 elsif ( $ret ne "" ) {
2293 die "deleting drive $deviceid failed : $ret " ;
2296 $ret = vm_monitor_command
( $vmid, "device_del $deviceid " , 1 );
2298 die 'detaching device $deviceid failed : $ret ' if $ret ne "" ;
2302 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2303 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2304 my $devices_list = vm_devices_list
( $vmid );
2305 return if ! defined ( $devices_list ->{ $deviceid });
2308 die "error on hot-plugging device $deviceid " ;
2314 my ( $storecfg, $vmid, $statefile, $skiplock ) = @_ ;
2316 lock_config
( $vmid, sub {
2317 my $conf = load_config
( $vmid );
2319 check_lock
( $conf ) if ! $skiplock ;
2321 if ( check_running
( $vmid )) {
2322 my $msg = "VM $vmid already running - start failed \n " ;
2323 syslog
( 'err' , $msg );
2326 syslog
( 'info' , "VM $vmid start" );
2330 my $migrate_port = 0 ;
2333 if ( $statefile eq 'tcp' ) {
2334 $migrate_port = next_migrate_port
();
2335 $migrate_uri = "tcp:localhost:${migrate_port}" ;
2337 if (- f
$statefile ) {
2338 $migrate_uri = "exec:cat $statefile " ;
2340 warn "state file ' $statefile ' does not exist - doing normal startup \n " ;
2345 my $defaults = load_defaults
();
2347 my ( $cmd, $vollist ) = config_to_command
( $storecfg, $vmid, $conf, $defaults, $migrate_uri );
2349 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
2350 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
2352 my $info = pci_device_info
( "0000: $d ->{pciid}" );
2353 die "IOMMU not present \n " if ! check_iommu_support
();
2354 die "no pci device info for device ' $d ->{pciid}' \n " if ! $info ;
2355 die "can't unbind pci device ' $d ->{pciid}' \n " if ! pci_dev_bind_to_stub
( $info );
2356 die "can't reset pci device ' $d ->{pciid}' \n " if ! pci_dev_reset
( $info );
2359 PVE
:: Storage
:: activate_volumes
( $storecfg, $vollist );
2361 eval { run_command
( $cmd, timeout
=> $migrate_uri ?
undef : 30 ); };
2366 my $msg = "start failed: $err " ;
2367 syslog
( 'err' , "VM $vmid $msg " );
2373 if ( $statefile eq 'tcp' ) {
2374 print "migration listens on port $migrate_port\n " ;
2377 # fixme: send resume - is that necessary ?
2378 eval { vm_monitor_command
( $vmid, "cont" , 1 ) };
2382 # always set migrate speed (overwrite kvm default of 32m)
2383 # we set a very hight default of 8192m which is basically unlimited
2384 my $migrate_speed = $defaults ->{ migrate_speed
} || 8192 ;
2385 $migrate_speed = $conf ->{ migrate_speed
} || $migrate_speed ;
2387 my $cmd = "migrate_set_speed ${migrate_speed}m" ;
2388 vm_monitor_command
( $vmid, $cmd, 1 );
2391 if ( my $migrate_downtime =
2392 $conf ->{ migrate_downtime
} || $defaults ->{ migrate_downtime
}) {
2393 my $cmd = "migrate_set_downtime ${migrate_downtime}" ;
2394 eval { vm_monitor_command
( $vmid, $cmd, 1 ); };
2397 vm_balloonset
( $vmid, $conf ->{ balloon
}) if $conf ->{ balloon
};
2402 my ( $fh, $timeout ) = @_ ;
2404 my $sel = new IO
:: Select
;
2411 while ( scalar ( @ready = $sel -> can_read ( $timeout ))) {
2413 if ( $count = $fh -> sysread ( $buf, 8192 )) {
2414 if ( $buf =~ /^(.*)\(qemu\) $/s ) {
2421 if (! defined ( $count )) {
2428 die "monitor read timeout \n " if ! scalar ( @ready );
2433 sub vm_monitor_command
{
2434 my ( $vmid, $cmdstr, $nolog, $nocheck ) = @_ ;
2438 syslog
( "info" , "VM $vmid monitor command ' $cmdstr '" ) if ! $nolog ;
2441 die "VM not running \n " if ! check_running
( $vmid, $nocheck );
2443 my $sname = monitor_socket
( $vmid );
2445 my $sock = IO
:: Socket
:: UNIX-
> new ( Peer
=> $sname ) ||
2446 die "unable to connect to VM $vmid socket - $!\n " ;
2450 # hack: migrate sometime blocks the monitor (when migrate_downtime
2452 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2453 $timeout = 60 * 60 ; # 1 hour
2457 my $data = __read_avail
( $sock, $timeout );
2459 if ( $data !~ m/^QEMU\s+(\S+)\s+monitor\s/ ) {
2460 die "got unexpected qemu monitor banner \n " ;
2463 my $sel = new IO
:: Select
;
2466 if (! scalar ( my @ready = $sel -> can_write ( $timeout ))) {
2467 die "monitor write error - timeout" ;
2470 my $fullcmd = " $cmdstr\r " ;
2473 if (!( $b = $sock -> syswrite ( $fullcmd )) || ( $b != length ( $fullcmd ))) {
2474 die "monitor write error - $! " ;
2477 return if ( $cmdstr eq 'q' ) || ( $cmdstr eq 'quit' );
2481 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2482 $timeout = 60 * 60 ; # 1 hour
2483 } elsif ( $cmdstr =~ m/^(eject|change)/ ) {
2484 $timeout = 60 ; # note: cdrom mount command is slow
2486 if ( $res = __read_avail
( $sock, $timeout )) {
2488 my @lines = split ( " \r ? \n " , $res );
2490 shift @lines if $lines [ 0 ] !~ m/^unknown command/ ; # skip echo
2492 $res = join ( " \n " , @lines );
2500 syslog
( "err" , "VM $vmid monitor command failed - $err " );
2507 sub vm_commandline
{
2508 my ( $storecfg, $vmid ) = @_ ;
2510 my $conf = load_config
( $vmid );
2512 my $defaults = load_defaults
();
2514 my $cmd = config_to_command
( $storecfg, $vmid, $conf, $defaults );
2516 return join ( ' ' , @$cmd );
2520 my ( $vmid, $skiplock ) = @_ ;
2522 lock_config
( $vmid, sub {
2524 my $conf = load_config
( $vmid );
2526 check_lock
( $conf ) if ! $skiplock ;
2528 syslog
( "info" , "VM $vmid sending 'reset'" );
2530 vm_monitor_command
( $vmid, "system_reset" , 1 );
2535 my ( $vmid, $skiplock ) = @_ ;
2537 lock_config
( $vmid, sub {
2539 my $conf = load_config
( $vmid );
2541 check_lock
( $conf ) if ! $skiplock ;
2543 syslog
( "info" , "VM $vmid sending 'shutdown'" );
2545 vm_monitor_command
( $vmid, "system_powerdown" , 1 );
2549 # Note: use $nockeck to skip tests if VM configuration file exists.
2550 # We need that when migration VMs to other nodes (files already moved)
2552 my ( $vmid, $skiplock, $nocheck ) = @_ ;
2554 lock_config
( $vmid, sub {
2556 my $pid = check_running
( $vmid, $nocheck );
2559 syslog
( 'info' , "VM $vmid already stopped" );
2564 my $conf = load_config
( $vmid );
2565 check_lock
( $conf ) if ! $skiplock ;
2568 syslog
( "info" , "VM $vmid stopping" );
2570 eval { vm_monitor_command
( $vmid, "quit" , 1 , $nocheck ); };
2576 my $timeout = 50 ; # fixme: how long?
2579 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2584 if ( $count >= $timeout ) {
2585 syslog
( 'info' , "VM $vmid still running - terminating now with SIGTERM" );
2589 syslog
( 'info' , "VM $vmid quit failed - terminating now with SIGTERM" );
2597 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2602 if ( $count >= $timeout ) {
2603 syslog
( 'info' , "VM $vmid still running - terminating now with SIGKILL \n " );
2607 fairsched_rmnod
( $vmid ); # try to destroy group
2612 my ( $vmid, $skiplock ) = @_ ;
2614 lock_config
( $vmid, sub {
2616 my $conf = load_config
( $vmid );
2618 check_lock
( $conf ) if ! $skiplock ;
2620 syslog
( "info" , "VM $vmid suspend" );
2622 vm_monitor_command
( $vmid, "stop" , 1 );
2627 my ( $vmid, $skiplock ) = @_ ;
2629 lock_config
( $vmid, sub {
2631 my $conf = load_config
( $vmid );
2633 check_lock
( $conf ) if ! $skiplock ;
2635 syslog
( "info" , "VM $vmid resume" );
2637 vm_monitor_command
( $vmid, "cont" , 1 );
2642 my ( $vmid, $skiplock, $key ) = @_ ;
2644 lock_config
( $vmid, sub {
2646 my $conf = load_config
( $vmid );
2648 check_lock
( $conf ) if ! $skiplock ;
2650 syslog
( "info" , "VM $vmid sending key $key " );
2652 vm_monitor_command
( $vmid, "sendkey $key " , 1 );
2657 my ( $storecfg, $vmid, $skiplock ) = @_ ;
2659 lock_config
( $vmid, sub {
2661 my $conf = load_config
( $vmid );
2663 check_lock
( $conf ) if ! $skiplock ;
2665 syslog
( "info" , "VM $vmid destroy called (removing all data)" );
2668 if (! check_running
( $vmid )) {
2669 fairsched_rmnod
( $vmid ); # try to destroy group
2670 destroy_vm
( $storecfg, $vmid );
2672 die "VM is running \n " ;
2679 syslog
( "err" , "VM $vmid destroy failed - $err " );
2688 $timeout = 3 * 60 if ! $timeout ;
2690 my $vzlist = vzlist
();
2692 foreach my $vmid ( keys %$vzlist ) {
2693 next if ! $vzlist ->{ $vmid }->{ pid
};
2699 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs \n " ;
2700 syslog
( 'info' , $msg );
2703 foreach my $vmid ( keys %$vzlist ) {
2704 next if ! $vzlist ->{ $vmid }->{ pid
};
2705 eval { vm_shutdown
( $vmid, 1 ); };
2706 print STDERR
$@ if $@ ;
2710 my $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2712 while (( $try < $maxtries ) && $count ) {
2718 foreach my $vmid ( keys %$vzlist ) {
2719 next if ! $vzlist ->{ $vmid }->{ pid
};
2727 foreach my $vmid ( keys %$vzlist ) {
2728 next if ! $vzlist ->{ $vmid }->{ pid
};
2730 $msg = "VM $vmid still running - sending stop now \n " ;
2731 syslog
( 'info' , $msg );
2734 eval { vm_monitor_command
( $vmid, "quit" , 1 ); };
2735 print STDERR
$@ if $@ ;
2740 $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2742 while (( $try < $maxtries ) && $count ) {
2748 foreach my $vmid ( keys %$vzlist ) {
2749 next if ! $vzlist ->{ $vmid }->{ pid
};
2757 foreach my $vmid ( keys %$vzlist ) {
2758 next if ! $vzlist ->{ $vmid }->{ pid
};
2760 $msg = "VM $vmid still running - terminating now with SIGTERM \n " ;
2761 syslog
( 'info' , $msg );
2763 kill 15 , $vzlist ->{ $vmid }->{ pid
};
2766 # this is called by system shotdown scripts, so remaining
2767 # processes gets killed anyways (no need to send kill -9 here)
2769 $msg = "Qemu Server stopped \n " ;
2770 syslog
( 'info' , $msg );
2778 my ( $filename, $buf ) = @_ ;
2780 my $fh = IO
:: File-
> new ( $filename, "w" );
2781 return undef if ! $fh ;
2783 my $res = print $fh $buf ;
2790 sub pci_device_info
{
2795 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/ ;
2796 my ( $domain, $bus, $slot, $func ) = ( $1, $2, $3, $4 );
2798 my $irq = file_read_firstline
( " $pcisysfs/devices/$name/irq " );
2799 return undef if ! defined ( $irq ) || $irq !~ m/^\d+$/ ;
2801 my $vendor = file_read_firstline
( " $pcisysfs/devices/$name/vendor " );
2802 return undef if ! defined ( $vendor ) || $vendor !~ s/^0x// ;
2804 my $product = file_read_firstline
( " $pcisysfs/devices/$name/device " );
2805 return undef if ! defined ( $product ) || $product !~ s/^0x// ;
2810 product
=> $product,
2816 has_fl_reset
=> - f
" $pcisysfs/devices/$name/reset " || 0 ,
2825 my $name = $dev ->{ name
};
2827 my $fn = " $pcisysfs/devices/$name/reset " ;
2829 return file_write
( $fn, "1" );
2832 sub pci_dev_bind_to_stub
{
2835 my $name = $dev ->{ name
};
2837 my $testdir = " $pcisysfs/drivers/pci -stub/ $name " ;
2838 return 1 if - d
$testdir ;
2840 my $data = " $dev ->{vendor} $dev ->{product}" ;
2841 return undef if ! file_write
( " $pcisysfs/drivers/pci -stub/new_id" , $data );
2843 my $fn = " $pcisysfs/devices/$name/driver/unbind " ;
2844 if (! file_write
( $fn, $name )) {
2845 return undef if - f
$fn ;
2848 $fn = " $pcisysfs/drivers/pci -stub/bind" ;
2849 if (! - d
$testdir ) {
2850 return undef if ! file_write
( $fn, $name );
2856 sub print_pci_addr
{
2861 #addr1 : ide,parallel,serial (motherboard)
2862 #addr2 : first videocard
2863 balloon0
=> { bus
=> 0 , addr
=> 3 },
2864 watchdog
=> { bus
=> 0 , addr
=> 4 },
2865 scsi0
=> { bus
=> 0 , addr
=> 5 },
2866 scsi1
=> { bus
=> 0 , addr
=> 6 },
2867 virtio0
=> { bus
=> 0 , addr
=> 10 },
2868 virtio1
=> { bus
=> 0 , addr
=> 11 },
2869 virtio2
=> { bus
=> 0 , addr
=> 12 },
2870 virtio3
=> { bus
=> 0 , addr
=> 13 },
2871 virtio4
=> { bus
=> 0 , addr
=> 14 },
2872 virtio5
=> { bus
=> 0 , addr
=> 15 },
2873 hostpci0
=> { bus
=> 0 , addr
=> 16 },
2874 hostpci1
=> { bus
=> 0 , addr
=> 17 },
2875 net0
=> { bus
=> 0 , addr
=> 18 },
2876 net1
=> { bus
=> 0 , addr
=> 19 },
2877 net2
=> { bus
=> 0 , addr
=> 20 },
2878 net3
=> { bus
=> 0 , addr
=> 21 },
2879 net4
=> { bus
=> 0 , addr
=> 22 },
2880 net5
=> { bus
=> 0 , addr
=> 23 },
2881 #addr29 : usb-host (pve-usb.cfg)
2884 if ( defined ( $devices ->{ $id }->{ bus
}) && defined ( $devices ->{ $id }->{ addr
})) {
2885 my $addr = sprintf ( "0x %x " , $devices ->{ $id }->{ addr
});
2886 $res = ",bus=pci. $devices ->{ $id }->{bus},addr= $addr " ;
2893 my ( $vmid, $value ) = @_ ;
2895 vm_monitor_command
( $vmid, "balloon $value " , 1 );
2898 # vzdump restore implementaion
2900 sub archive_read_firstfile
{
2901 my $archive = shift ;
2903 die "ERROR: file ' $archive ' does not exist \n " if ! - f
$archive ;
2905 # try to detect archive type first
2906 my $pid = open ( TMP
, "tar tf ' $archive '|" ) ||
2907 die "unable to open file ' $archive ' \n " ;
2908 my $firstfile = < TMP
>;
2912 die "ERROR: archive contaions no data \n " if ! $firstfile ;
2918 sub restore_cleanup
{
2919 my $statfile = shift ;
2921 print STDERR
"starting cleanup \n " ;
2923 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
2924 while ( defined ( my $line = < $fd >)) {
2925 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
2928 if ( $volid =~ m
|^/|) {
2929 unlink $volid || die 'unlink failed \n ' ;
2931 my $cfg = cfs_read_file
( 'storage.cfg' );
2932 PVE
:: Storage
:: vdisk_free
( $cfg, $volid );
2934 print STDERR
"temporary volume ' $volid ' sucessfuly removed \n " ;
2936 print STDERR
"unable to cleanup ' $volid ' - $@ " if $@ ;
2938 print STDERR
"unable to parse line in statfile - $line " ;
2945 sub restore_archive
{
2946 my ( $archive, $vmid, $opts ) = @_ ;
2948 if ( $archive ne '-' ) {
2949 my $firstfile = archive_read_firstfile
( $archive );
2950 die "ERROR: file ' $archive ' dos not lock like a QemuServer vzdump backup \n "
2951 if $firstfile ne 'qemu-server.conf' ;
2954 my $tocmd = "/usr/lib/qemu-server/qmextract" ;
2956 $tocmd .= " --storage " . PVE
:: Tools
:: shellquote
( $opts ->{ storage
}) if $opts ->{ storage
};
2957 $tocmd .= ' --prealloc' if $opts ->{ prealloc
};
2958 $tocmd .= ' --info' if $opts ->{ info
};
2960 # tar option "xf" does not autodetect compression when read fron STDIN,
2961 # so we pipe to zcat
2962 my $cmd = "zcat -f|tar xf " . PVE
:: Tools
:: shellquote
( $archive ) . " " .
2963 PVE
:: Tools
:: shellquote
( "--to-command= $tocmd " );
2965 my $tmpdir = "/var/tmp/vzdumptmp $$ " ;
2968 local $ENV { VZDUMP_TMPDIR
} = $tmpdir ;
2969 local $ENV { VZDUMP_VMID
} = $vmid ;
2971 my $conffile = PVE
:: QemuServer
:: config_file
( $vmid );
2972 my $tmpfn = " $conffile . $$ .tmp" ;
2974 # disable interrupts (always do cleanups)
2975 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = sub {
2976 print STDERR
"got interrupt - ignored \n " ;
2981 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = $SIG { PIPE
} = sub {
2982 die "interrupted by signal \n " ;
2985 if ( $archive eq '-' ) {
2986 print "extracting archive from STDIN \n " ;
2987 run_command
( $cmd, input
=> "<&STDIN" );
2989 print "extracting archive ' $archive ' \n " ;
2993 return if $opts ->{ info
};
2997 my $statfile = " $tmpdir/qmrestore .stat" ;
2998 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
2999 while ( defined ( my $line = < $fd >)) {
3000 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
3001 $map ->{ $1 } = $2 if $1 ;
3003 print STDERR
"unable to parse line in statfile - $line\n " ;
3009 my $confsrc = " $tmpdir/qemu -server.conf" ;
3011 my $srcfd = new IO
:: File
( $confsrc, "r" ) ||
3012 die "unable to open file ' $confsrc ' \n " ;
3014 my $outfd = new IO
:: File
( $tmpfn, "w" ) ||
3015 die "unable to write config for VM $vmid\n " ;
3019 while ( defined ( my $line = < $srcfd >)) {
3020 next if $line =~ m/^\#vzdump\#/ ;
3021 next if $line =~ m/^lock:/ ;
3022 next if $line =~ m/^unused\d+:/ ;
3024 if (( $line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/ )) {
3025 # try to convert old 1.X settings
3026 my ( $id, $ind, $ethcfg ) = ( $1, $2, $3 );
3027 foreach my $devconfig ( PVE
:: Tools
:: split_list
( $ethcfg )) {
3028 my ( $model, $macaddr ) = split ( /\=/ , $devconfig );
3029 $macaddr = PVE
:: Tools
:: random_ether_addr
() if ! $macaddr || $opts ->{ unique
};
3032 bridge
=> "vmbr $ind " ,
3033 macaddr
=> $macaddr,
3035 my $netstr = print_net
( $net );
3036 print $outfd "net${netcount}: $netstr\n " ;
3039 } elsif (( $line =~ m/^(net\d+):\s*(\S+)\s*$/ ) && ( $opts ->{ unique
})) {
3040 my ( $id, $netstr ) = ( $1, $2 );
3041 my $net = parse_net
( $netstr );
3042 $net ->{ macaddr
} = PVE
:: Tools
:: random_ether_addr
() if $net ->{ macaddr
};
3043 $netstr = print_net
( $net );
3044 print $outfd " $id : $netstr\n " ;
3045 } elsif ( $line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/ ) {
3048 if ( $line =~ m/backup=no/ ) {
3049 print $outfd "# $line " ;
3050 } elsif ( $virtdev && $map ->{ $virtdev }) {
3051 my $di = PVE
:: QemuServer
:: parse_drive
( $virtdev, $value );
3052 $di ->{ file
} = $map ->{ $virtdev };
3053 $value = PVE
:: QemuServer
:: print_drive
( $vmid, $di );
3054 print $outfd " $virtdev : $value\n " ;
3072 restore_cleanup
( " $tmpdir/qmrestore .stat" ) if ! $opts ->{ info
};
3079 rename $tmpfn, $conffile ||
3080 die "unable to commit configuration file ' $conffile ' \n " ;