[pve-devel] [PATCH v2 qemu-server 03/12] Add CPUConfig file and migrate some CPU helpers
Thomas Lamprecht
t.lamprecht at proxmox.com
Tue Oct 1 18:12:04 CEST 2019
On 9/30/19 12:58 PM, Stefan Reiter wrote:
> The package will be used for custom CPU models as a SectionConfig, hence
> the name. For now we simply move some CPU related helper functions and
> declarations over from QemuServer to reduce clutter there.
Single thing I'm not too sure is how "qemu_machine_feature_enabled" fit's
into the CPUConfig here..
AFAICT, this rather looks like and attempt to avoid a cyclic module
dependency?
Maybe we could also do a Machine module which then includes stuff like:
machine_type_is_q35
get_basic_machine_info
But seems not really worth it... better ideas?
>
> Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
> ---
> PVE/QemuServer.pm | 242 +---------------------------------
> PVE/QemuServer/CPUConfig.pm | 251 ++++++++++++++++++++++++++++++++++++
> PVE/QemuServer/Makefile | 1 +
> 3 files changed, 256 insertions(+), 238 deletions(-)
> create mode 100644 PVE/QemuServer/CPUConfig.pm
>
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index 20c1061..a95006f 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -33,6 +33,7 @@ use PVE::QemuConfig;
> use PVE::QMPClient;
> use PVE::RPCEnvironment;
> use PVE::GuestHelpers;
> +use PVE::QemuServer::CPUConfig qw(qemu_machine_feature_enabled print_cpu_device get_cpu_options);
> use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port);
> use PVE::QemuServer::Memory;
> use PVE::QemuServer::USB qw(parse_usb_device);
> @@ -116,105 +117,6 @@ mkdir $var_run_tmpdir;
> my $lock_dir = "/var/lock/qemu-server";
> mkdir $lock_dir;
>
> -my $cpu_vendor_list = {
> - # Intel CPUs
> - 486 => 'GenuineIntel',
> - pentium => 'GenuineIntel',
> - pentium2 => 'GenuineIntel',
> - pentium3 => 'GenuineIntel',
> - coreduo => 'GenuineIntel',
> - core2duo => 'GenuineIntel',
> - Conroe => 'GenuineIntel',
> - Penryn => 'GenuineIntel',
> - Nehalem => 'GenuineIntel',
> - 'Nehalem-IBRS' => 'GenuineIntel',
> - Westmere => 'GenuineIntel',
> - 'Westmere-IBRS' => 'GenuineIntel',
> - SandyBridge => 'GenuineIntel',
> - 'SandyBridge-IBRS' => 'GenuineIntel',
> - IvyBridge => 'GenuineIntel',
> - 'IvyBridge-IBRS' => 'GenuineIntel',
> - Haswell => 'GenuineIntel',
> - 'Haswell-IBRS' => 'GenuineIntel',
> - 'Haswell-noTSX' => 'GenuineIntel',
> - 'Haswell-noTSX-IBRS' => 'GenuineIntel',
> - Broadwell => 'GenuineIntel',
> - 'Broadwell-IBRS' => 'GenuineIntel',
> - 'Broadwell-noTSX' => 'GenuineIntel',
> - 'Broadwell-noTSX-IBRS' => 'GenuineIntel',
> - 'Skylake-Client' => 'GenuineIntel',
> - 'Skylake-Client-IBRS' => 'GenuineIntel',
> - 'Skylake-Server' => 'GenuineIntel',
> - 'Skylake-Server-IBRS' => 'GenuineIntel',
> -
> - # AMD CPUs
> - athlon => 'AuthenticAMD',
> - phenom => 'AuthenticAMD',
> - Opteron_G1 => 'AuthenticAMD',
> - Opteron_G2 => 'AuthenticAMD',
> - Opteron_G3 => 'AuthenticAMD',
> - Opteron_G4 => 'AuthenticAMD',
> - Opteron_G5 => 'AuthenticAMD',
> - EPYC => 'AuthenticAMD',
> - 'EPYC-IBPB' => 'AuthenticAMD',
> -
> - # generic types, use vendor from host node
> - host => 'default',
> - kvm32 => 'default',
> - kvm64 => 'default',
> - qemu32 => 'default',
> - qemu64 => 'default',
> - max => 'default',
> -};
> -
> -my @supported_cpu_flags = (
> - 'pcid',
> - 'spec-ctrl',
> - 'ibpb',
> - 'ssbd',
> - 'virt-ssbd',
> - 'amd-ssbd',
> - 'amd-no-ssb',
> - 'pdpe1gb',
> - 'md-clear',
> - 'hv-tlbflush',
> - 'hv-evmcs',
> - 'aes'
> -);
> -my $cpu_flag = qr/[+-](@{[join('|', @supported_cpu_flags)]})/;
> -
> -my $cpu_fmt = {
> - cputype => {
> - description => "Emulated CPU type.",
> - type => 'string',
> - enum => [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
> - default => 'kvm64',
> - default_key => 1,
> - },
> - hidden => {
> - description => "Do not identify as a KVM virtual machine.",
> - type => 'boolean',
> - optional => 1,
> - default => 0
> - },
> - 'hv-vendor-id' => {
> - type => 'string',
> - pattern => qr/[a-zA-Z0-9]{1,12}/,
> - format_description => 'vendor-id',
> - description => 'The Hyper-V vendor ID. Some drivers or programs inside Windows guests need a specific ID.',
> - optional => 1,
> - },
> - flags => {
> - description => "List of additional CPU flags separated by ';'."
> - . " Use '+FLAG' to enable, '-FLAG' to disable a flag."
> - . " Currently supported flags: @{[join(', ', @supported_cpu_flags)]}.",
> - format_description => '+FLAG[;-FLAG...]',
> - type => 'string',
> - pattern => qr/$cpu_flag(;$cpu_flag)*/,
> - optional => 1,
> - },
> -};
> -
> my $watchdog_fmt = {
> model => {
> default_key => 1,
> @@ -603,7 +505,7 @@ EODESCR
> optional => 1,
> description => "Emulated CPU type.",
> type => 'string',
> - format => $cpu_fmt,
> + format => $PVE::QemuServer::CPUConfig::cpu_fmt,
> },
> parent => get_standard_option('pve-snapshot-name', {
> optional => 1,
> @@ -2133,26 +2035,6 @@ sub print_netdev_full {
> return $netdev;
> }
>
> -
> -sub print_cpu_device {
> - my ($conf, $id) = @_;
> -
> - my $kvm = $conf->{kvm} // 1;
> - my $cpu = $kvm ? "kvm64" : "qemu64";
> - if (my $cputype = $conf->{cpu}) {
> - my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
> - or die "Cannot parse cpu description: $cputype\n";
> - $cpu = $cpuconf->{cputype};
> - }
> -
> - my $cores = $conf->{cores} || 1;
> -
> - my $current_core = ($id - 1) % $cores;
> - my $current_socket = int(($id - 1 - $current_core)/$cores);
> -
> - return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
> -}
> -
> my $vga_map = {
> 'cirrus' => 'cirrus-vga',
> 'std' => 'VGA',
> @@ -3643,62 +3525,6 @@ sub query_understood_cpu_flags {
> return $flags;
> }
>
> -sub get_cpu_options {
> - my ($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, $gpu_passthrough) = @_;
> -
> - my $cpuFlags = [];
> - my $ostype = $conf->{ostype};
> -
> - my $cpu = $kvm ? "kvm64" : "qemu64";
> - if ($arch eq 'aarch64') {
> - $cpu = 'cortex-a57';
> - }
> - my $hv_vendor_id;
> - if (my $cputype = $conf->{cpu}) {
> - my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
> - or die "Cannot parse cpu description: $cputype\n";
> - $cpu = $cpuconf->{cputype};
> - $kvm_off = 1 if $cpuconf->{hidden};
> - $hv_vendor_id = $cpuconf->{'hv-vendor-id'};
> -
> - if (defined(my $flags = $cpuconf->{flags})) {
> - push @$cpuFlags, split(";", $flags);
> - }
> - }
> -
> - push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64' && $arch eq 'x86_64';
> -
> - push @$cpuFlags , '-x2apic'
> - if $conf->{ostype} && $conf->{ostype} eq 'solaris';
> -
> - push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
> -
> - push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
> -
> - if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3) && $arch eq 'x86_64') {
> -
> - push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
> - push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
> - }
> -
> - add_hyperv_enlightenments($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios}, $gpu_passthrough, $hv_vendor_id) if $kvm;
> -
> - push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm && $arch eq 'x86_64';
> -
> - push @$cpuFlags, 'kvm=off' if $kvm_off;
> -
> - if (my $cpu_vendor = $cpu_vendor_list->{$cpu}) {
> - push @$cpuFlags, "vendor=${cpu_vendor}"
> - if $cpu_vendor ne 'default';
> - } elsif ($arch ne 'aarch64') {
> - die "internal error"; # should not happen
> - }
> -
> - $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
> -
> - return ('-cpu', $cpu);
> -}
> -
> sub config_to_command {
> my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
>
> @@ -4084,7 +3910,8 @@ sub config_to_command {
> push @$rtcFlags, 'base=localtime';
> }
>
> - push @$cmd, get_cpu_options($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, $gpu_passthrough);
> + push @$cmd, get_cpu_options($conf, $arch, $kvm,
> + $machine_type, $kvm_off, $kvmver, $winversion, $gpu_passthrough);
>
> PVE::QemuServer::Memory::config($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
>
> @@ -7319,28 +7146,6 @@ sub get_running_qemu_version {
> return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
> }
>
> -sub qemu_machine_feature_enabled {
> - my ($machine, $kvmver, $version_major, $version_minor) = @_;
> -
> - my $current_major;
> - my $current_minor;
> -
> - if ($machine && $machine =~ m/^((?:pc(-i440fx|-q35)?|virt)-(\d+)\.(\d+))/) {
> -
> - $current_major = $3;
> - $current_minor = $4;
> -
> - } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
> -
> - $current_major = $1;
> - $current_minor = $2;
> - }
> -
> - return 1 if $current_major > $version_major ||
> - ($current_major == $version_major &&
> - $current_minor >= $version_minor);
> -}
> -
> sub qemu_machine_pxe {
> my ($vmid, $conf) = @_;
>
> @@ -7426,45 +7231,6 @@ sub scsihw_infos {
> return ($maxdev, $controller, $controller_prefix);
> }
>
> -sub add_hyperv_enlightenments {
> - my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough, $hv_vendor_id) = @_;
> -
> - return if $winversion < 6;
> - return if $bios && $bios eq 'ovmf' && $winversion < 8;
> -
> - if ($gpu_passthrough || defined($hv_vendor_id)) {
> - $hv_vendor_id //= 'proxmox';
> - push @$cpuFlags , "hv_vendor_id=$hv_vendor_id";
> - }
> -
> - if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
> - push @$cpuFlags , 'hv_spinlocks=0x1fff';
> - push @$cpuFlags , 'hv_vapic';
> - push @$cpuFlags , 'hv_time';
> - } else {
> - push @$cpuFlags , 'hv_spinlocks=0xffff';
> - }
> -
> - if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 6)) {
> - push @$cpuFlags , 'hv_reset';
> - push @$cpuFlags , 'hv_vpindex';
> - push @$cpuFlags , 'hv_runtime';
> - }
> -
> - if ($winversion >= 7) {
> - push @$cpuFlags , 'hv_relaxed';
> -
> - if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 12)) {
> - push @$cpuFlags , 'hv_synic';
> - push @$cpuFlags , 'hv_stimer';
> - }
> -
> - if (qemu_machine_feature_enabled ($machine_type, $kvmver, 3, 1)) {
> - push @$cpuFlags , 'hv_ipi';
> - }
> - }
> -}
> -
> sub windows_version {
> my ($ostype) = @_;
>
> diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
> new file mode 100644
> index 0000000..c994228
> --- /dev/null
> +++ b/PVE/QemuServer/CPUConfig.pm
> @@ -0,0 +1,251 @@
> +package PVE::QemuServer::CPUConfig;
> +
> +use strict;
> +use warnings;
please do a empty newline after above
> +use PVE::JSONSchema;
> +
> +use base 'Exporter';
> +our @EXPORT_OK = qw(
> +print_cpu_device
> +get_cpu_options
> +qemu_machine_feature_enabled
> +);
> +
> +my $cpu_vendor_list = {
> + # Intel CPUs
> + 486 => 'GenuineIntel',
> + pentium => 'GenuineIntel',
> + pentium2 => 'GenuineIntel',
> + pentium3 => 'GenuineIntel',
> + coreduo => 'GenuineIntel',
> + core2duo => 'GenuineIntel',
> + Conroe => 'GenuineIntel',
> + Penryn => 'GenuineIntel',
> + Nehalem => 'GenuineIntel',
> + 'Nehalem-IBRS' => 'GenuineIntel',
> + Westmere => 'GenuineIntel',
> + 'Westmere-IBRS' => 'GenuineIntel',
> + SandyBridge => 'GenuineIntel',
> + 'SandyBridge-IBRS' => 'GenuineIntel',
> + IvyBridge => 'GenuineIntel',
> + 'IvyBridge-IBRS' => 'GenuineIntel',
> + Haswell => 'GenuineIntel',
> + 'Haswell-IBRS' => 'GenuineIntel',
> + 'Haswell-noTSX' => 'GenuineIntel',
> + 'Haswell-noTSX-IBRS' => 'GenuineIntel',
> + Broadwell => 'GenuineIntel',
> + 'Broadwell-IBRS' => 'GenuineIntel',
> + 'Broadwell-noTSX' => 'GenuineIntel',
> + 'Broadwell-noTSX-IBRS' => 'GenuineIntel',
> + 'Skylake-Client' => 'GenuineIntel',
> + 'Skylake-Client-IBRS' => 'GenuineIntel',
> + 'Skylake-Server' => 'GenuineIntel',
> + 'Skylake-Server-IBRS' => 'GenuineIntel',
> +
> + # AMD CPUs
> + athlon => 'AuthenticAMD',
> + phenom => 'AuthenticAMD',
> + Opteron_G1 => 'AuthenticAMD',
> + Opteron_G2 => 'AuthenticAMD',
> + Opteron_G3 => 'AuthenticAMD',
> + Opteron_G4 => 'AuthenticAMD',
> + Opteron_G5 => 'AuthenticAMD',
> + EPYC => 'AuthenticAMD',
> + 'EPYC-IBPB' => 'AuthenticAMD',
> +
> + # generic types, use vendor from host node
> + host => 'default',
> + kvm32 => 'default',
> + kvm64 => 'default',
> + qemu32 => 'default',
> + qemu64 => 'default',
> + max => 'default',
> +};
> +
> +my @supported_cpu_flags = (
> + 'pcid',
> + 'spec-ctrl',
> + 'ibpb',
> + 'ssbd',
> + 'virt-ssbd',
> + 'amd-ssbd',
> + 'amd-no-ssb',
> + 'pdpe1gb',
> + 'md-clear',
> + 'hv-tlbflush',
> + 'hv-evmcs',
> + 'aes'
> +);
> +my $cpu_flag = qr/[+-](@{[join('|', @supported_cpu_flags)]})/;
> +
> +our $cpu_fmt = {
> + cputype => {
> + description => "Emulated CPU type.",
> + type => 'string',
> + enum => [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
> + default => 'kvm64',
> + default_key => 1,
> + },
> + hidden => {
> + description => "Do not identify as a KVM virtual machine.",
> + type => 'boolean',
> + optional => 1,
> + default => 0
> + },
> + 'hv-vendor-id' => {
> + type => 'string',
> + pattern => qr/[a-zA-Z0-9]{1,12}/,
> + format_description => 'vendor-id',
> + description => 'The Hyper-V vendor ID. Some drivers or programs inside Windows guests need a specific ID.',
> + optional => 1,
> + },
> + flags => {
> + description => "List of additional CPU flags separated by ';'."
> + . " Use '+FLAG' to enable, '-FLAG' to disable a flag."
> + . " Currently supported flags: @{[join(', ', @supported_cpu_flags)]}.",
> + format_description => '+FLAG[;-FLAG...]',
> + type => 'string',
> + pattern => qr/$cpu_flag(;$cpu_flag)*/,
> + optional => 1,
> + },
> +};
> +
> +# Print a QEMU device node for a given VM configuration for hotplugging CPUs
> +sub print_cpu_device {
> + my ($conf, $id) = @_;
> +
> + my $kvm = $conf->{kvm} // 1;
> + my $cpu = $kvm ? "kvm64" : "qemu64";
> + if (my $cputype = $conf->{cpu}) {
> + my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
> + or die "Cannot parse cpu description: $cputype\n";
> + $cpu = $cpuconf->{cputype};
> + }
> +
> + my $cores = $conf->{cores} || 1;
> +
> + my $current_core = ($id - 1) % $cores;
> + my $current_socket = int(($id - 1 - $current_core)/$cores);
> +
> + return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
> +}
> +
> +# Calculate QEMU's '-cpu' argument from a given VM configuration
> +sub get_cpu_options {
> + my ($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, $gpu_passthrough) = @_;
> +
> + my $cpuFlags = [];
> + my $ostype = $conf->{ostype};
> +
> + my $cpu = $kvm ? "kvm64" : "qemu64";
> + if ($arch eq 'aarch64') {
> + $cpu = 'cortex-a57';
> + }
> + my $hv_vendor_id;
> + if (my $cputype = $conf->{cpu}) {
> + my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
> + or die "Cannot parse cpu description: $cputype\n";
> + $cpu = $cpuconf->{cputype};
> + $kvm_off = 1 if $cpuconf->{hidden};
> + $hv_vendor_id = $cpuconf->{'hv-vendor-id'};
> +
> + if (defined(my $flags = $cpuconf->{flags})) {
> + push @$cpuFlags, split(";", $flags);
> + }
> + }
> +
> + push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64' && $arch eq 'x86_64';
> +
> + push @$cpuFlags , '-x2apic'
> + if $conf->{ostype} && $conf->{ostype} eq 'solaris';
> +
> + push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
> +
> + push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
> +
> + if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3) && $arch eq 'x86_64') {
> +
> + push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
> + push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
> + }
> +
> + add_hyperv_enlightenments($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios}, $gpu_passthrough, $hv_vendor_id) if $kvm;
> +
> + push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm && $arch eq 'x86_64';
> +
> + push @$cpuFlags, 'kvm=off' if $kvm_off;
> +
> + if (my $cpu_vendor = $cpu_vendor_list->{$cpu}) {
> + push @$cpuFlags, "vendor=${cpu_vendor}"
> + if $cpu_vendor ne 'default';
> + } elsif ($arch ne 'aarch64') {
> + die "internal error"; # should not happen
> + }
> +
> + $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
> +
> + return ('-cpu', $cpu);
> +}
> +
> +sub add_hyperv_enlightenments {
> + my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough, $hv_vendor_id) = @_;
> +
> + return if $winversion < 6;
> + return if $bios && $bios eq 'ovmf' && $winversion < 8;
> +
> + if ($gpu_passthrough || defined($hv_vendor_id)) {
> + $hv_vendor_id //= 'proxmox';
> + push @$cpuFlags , "hv_vendor_id=$hv_vendor_id";
> + }
> +
> + if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
> + push @$cpuFlags , 'hv_spinlocks=0x1fff';
> + push @$cpuFlags , 'hv_vapic';
> + push @$cpuFlags , 'hv_time';
> + } else {
> + push @$cpuFlags , 'hv_spinlocks=0xffff';
> + }
> +
> + if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 6)) {
> + push @$cpuFlags , 'hv_reset';
> + push @$cpuFlags , 'hv_vpindex';
> + push @$cpuFlags , 'hv_runtime';
> + }
> +
> + if ($winversion >= 7) {
> + push @$cpuFlags , 'hv_relaxed';
> +
> + if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 12)) {
> + push @$cpuFlags , 'hv_synic';
> + push @$cpuFlags , 'hv_stimer';
> + }
> +
> + if (qemu_machine_feature_enabled ($machine_type, $kvmver, 3, 1)) {
> + push @$cpuFlags , 'hv_ipi';
> + }
> + }
> +}
> +
> +sub qemu_machine_feature_enabled {
> + my ($machine, $kvmver, $version_major, $version_minor) = @_;
> +
> + my $current_major;
> + my $current_minor;
> +
> + if ($machine && $machine =~ m/^((?:pc(-i440fx|-q35)?|virt)-(\d+)\.(\d+))/) {
> +
> + $current_major = $3;
> + $current_minor = $4;
> +
> + } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
> +
> + $current_major = $1;
> + $current_minor = $2;
> + }
> +
> + return 1 if $current_major > $version_major ||
> + ($current_major == $version_major &&
> + $current_minor >= $version_minor);
> +}
> +
> +1;
> diff --git a/PVE/QemuServer/Makefile b/PVE/QemuServer/Makefile
> index afc39a3..a3054f1 100644
> --- a/PVE/QemuServer/Makefile
> +++ b/PVE/QemuServer/Makefile
> @@ -5,6 +5,7 @@ SOURCES=PCI.pm \
> OVF.pm \
> Cloudinit.pm \
> Agent.pm \
> + CPUConfig.pm \
>
> .PHONY: install
> install: ${SOURCES}
>
More information about the pve-devel
mailing list