2017-09-18 12:35:50 +00:00
|
|
|
|
#!/usr/bin/env perl
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
|
|
use File::Find;
|
|
|
|
|
|
|
|
|
|
die "syntax: $0 SRCDIR\n" unless int(@ARGV) == 1;
|
|
|
|
|
|
|
|
|
|
my $srcdir = shift @ARGV;
|
|
|
|
|
|
|
|
|
|
my $symslibvirt = "$srcdir/libvirt_public.syms";
|
|
|
|
|
my $symsqemu = "$srcdir/libvirt_qemu.syms";
|
Introduce an LXC specific public API & library
This patch introduces support for LXC specific public APIs. In
common with what was done for QEMU, this creates a libvirt_lxc.so
library and libvirt/libvirt-lxc.h header file.
The actual APIs are
int virDomainLxcOpenNamespace(virDomainPtr domain,
int **fdlist,
unsigned int flags);
int virDomainLxcEnterNamespace(virDomainPtr domain,
unsigned int nfdlist,
int *fdlist,
unsigned int *noldfdlist,
int **oldfdlist,
unsigned int flags);
which provide a way to use the setns() system call to move the
calling process into the container's namespace. It is not
practical to write in a generically applicable manner. The
nearest that we could get to such an API would be an API which
allows to pass a command + argv to be executed inside a
container. Even if we had such a generic API, this LXC specific
API is still useful, because it allows the caller to maintain
the current process context, in particular any I/O streams they
have open.
NB the virDomainLxcEnterNamespace() API is special in that it
runs client side, so does not involve the internal driver API.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-12-21 13:15:19 +00:00
|
|
|
|
my $symslxc = "$srcdir/libvirt_lxc.syms";
|
2014-11-11 16:28:26 +00:00
|
|
|
|
my @drivertable = (
|
|
|
|
|
"$srcdir/driver-hypervisor.h",
|
|
|
|
|
"$srcdir/driver-interface.h",
|
|
|
|
|
"$srcdir/driver-network.h",
|
|
|
|
|
"$srcdir/driver-nodedev.h",
|
|
|
|
|
"$srcdir/driver-nwfilter.h",
|
|
|
|
|
"$srcdir/driver-secret.h",
|
|
|
|
|
"$srcdir/driver-state.h",
|
|
|
|
|
"$srcdir/driver-storage.h",
|
|
|
|
|
"$srcdir/driver-stream.h",
|
|
|
|
|
);
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
|
|
|
|
my %groupheaders = (
|
2014-10-16 09:25:59 +00:00
|
|
|
|
"virHypervisorDriver" => "Hypervisor APIs",
|
2011-05-13 10:00:56 +00:00
|
|
|
|
"virNetworkDriver" => "Virtual Network APIs",
|
|
|
|
|
"virInterfaceDriver" => "Host Interface APIs",
|
2013-04-23 10:15:48 +00:00
|
|
|
|
"virNodeDeviceDriver" => "Host Device APIs",
|
2011-05-13 10:00:56 +00:00
|
|
|
|
"virStorageDriver" => "Storage Pool APIs",
|
|
|
|
|
"virSecretDriver" => "Secret APIs",
|
|
|
|
|
"virNWFilterDriver" => "Network Filter APIs",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
my @srcs;
|
|
|
|
|
find({
|
|
|
|
|
wanted => sub {
|
2014-08-20 16:17:07 +00:00
|
|
|
|
if (m!$srcdir/.*/\w+_(driver|common|tmpl|monitor|hal|udev)\.c$!) {
|
2012-07-27 12:51:28 +00:00
|
|
|
|
push @srcs, $_ if $_ !~ /vbox_driver\.c/;
|
|
|
|
|
}
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}, no_chdir => 1}, $srcdir);
|
|
|
|
|
|
2016-06-28 11:28:48 +00:00
|
|
|
|
# Map API functions to the header and documentation files they're in
|
|
|
|
|
# so that we can generate proper hyperlinks to their documentation.
|
|
|
|
|
#
|
|
|
|
|
# The function names are grep'd from the XML output of apibuild.py.
|
|
|
|
|
sub getAPIFilenames {
|
|
|
|
|
my $filename = shift;
|
|
|
|
|
|
|
|
|
|
my %files;
|
|
|
|
|
my $line;
|
|
|
|
|
|
|
|
|
|
open FILE, "<", $filename or die "cannot read $filename: $!";
|
|
|
|
|
|
|
|
|
|
while (defined($line = <FILE>)) {
|
|
|
|
|
if ($line =~ /function name='([^']+)' file='([^']+)'/) {
|
|
|
|
|
$files{$1} = $2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close FILE;
|
|
|
|
|
|
|
|
|
|
if (keys %files == 0) {
|
|
|
|
|
die "No functions found in $filename. Has the apibuild.py output changed?";
|
|
|
|
|
}
|
|
|
|
|
return \%files;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-28 10:37:50 +00:00
|
|
|
|
sub parseSymsFile {
|
|
|
|
|
my $apisref = shift;
|
|
|
|
|
my $prefix = shift;
|
|
|
|
|
my $filename = shift;
|
|
|
|
|
my $xmlfilename = shift;
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
2016-06-28 10:37:50 +00:00
|
|
|
|
my $line;
|
|
|
|
|
my $vers;
|
|
|
|
|
my $prevvers;
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
2016-06-28 11:28:48 +00:00
|
|
|
|
my $filenames = getAPIFilenames($xmlfilename);
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
2016-06-28 10:37:50 +00:00
|
|
|
|
open FILE, "<$filename"
|
|
|
|
|
or die "cannot read $filename: $!";
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
2016-06-28 10:37:50 +00:00
|
|
|
|
while (defined($line = <FILE>)) {
|
|
|
|
|
chomp $line;
|
|
|
|
|
next if $line =~ /^\s*#/;
|
|
|
|
|
next if $line =~ /^\s*$/;
|
|
|
|
|
next if $line =~ /^\s*(global|local):/;
|
|
|
|
|
if ($line =~ /^\s*${prefix}_(\d+\.\d+\.\d+)\s*{\s*$/) {
|
|
|
|
|
if (defined $vers) {
|
|
|
|
|
die "malformed syms file";
|
|
|
|
|
}
|
|
|
|
|
$vers = $1;
|
|
|
|
|
} elsif ($line =~ /\s*}\s*;\s*$/) {
|
|
|
|
|
if (defined $prevvers) {
|
|
|
|
|
die "malformed syms file";
|
|
|
|
|
}
|
|
|
|
|
$prevvers = $vers;
|
|
|
|
|
$vers = undef;
|
|
|
|
|
} elsif ($line =~ /\s*}\s*${prefix}_(\d+\.\d+\.\d+)\s*;\s*$/) {
|
|
|
|
|
if ($1 ne $prevvers) {
|
|
|
|
|
die "malformed syms file $1 != $vers";
|
|
|
|
|
}
|
|
|
|
|
$prevvers = $vers;
|
|
|
|
|
$vers = undef;
|
|
|
|
|
} elsif ($line =~ /\s*(\w+)\s*;\s*$/) {
|
|
|
|
|
$$apisref{$1} = {};
|
|
|
|
|
$$apisref{$1}->{vers} = $vers;
|
2016-06-28 11:28:48 +00:00
|
|
|
|
$$apisref{$1}->{file} = $$filenames{$1};
|
2016-06-28 10:37:50 +00:00
|
|
|
|
} else {
|
|
|
|
|
die "unexpected data $line\n";
|
2012-07-27 12:51:28 +00:00
|
|
|
|
}
|
Introduce an LXC specific public API & library
This patch introduces support for LXC specific public APIs. In
common with what was done for QEMU, this creates a libvirt_lxc.so
library and libvirt/libvirt-lxc.h header file.
The actual APIs are
int virDomainLxcOpenNamespace(virDomainPtr domain,
int **fdlist,
unsigned int flags);
int virDomainLxcEnterNamespace(virDomainPtr domain,
unsigned int nfdlist,
int *fdlist,
unsigned int *noldfdlist,
int **oldfdlist,
unsigned int flags);
which provide a way to use the setns() system call to move the
calling process into the container's namespace. It is not
practical to write in a generically applicable manner. The
nearest that we could get to such an API would be an API which
allows to pass a command + argv to be executed inside a
container. Even if we had such a generic API, this LXC specific
API is still useful, because it allows the caller to maintain
the current process context, in particular any I/O streams they
have open.
NB the virDomainLxcEnterNamespace() API is special in that it
runs client side, so does not involve the internal driver API.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-12-21 13:15:19 +00:00
|
|
|
|
}
|
2016-06-28 10:37:50 +00:00
|
|
|
|
|
|
|
|
|
close FILE;
|
Introduce an LXC specific public API & library
This patch introduces support for LXC specific public APIs. In
common with what was done for QEMU, this creates a libvirt_lxc.so
library and libvirt/libvirt-lxc.h header file.
The actual APIs are
int virDomainLxcOpenNamespace(virDomainPtr domain,
int **fdlist,
unsigned int flags);
int virDomainLxcEnterNamespace(virDomainPtr domain,
unsigned int nfdlist,
int *fdlist,
unsigned int *noldfdlist,
int **oldfdlist,
unsigned int flags);
which provide a way to use the setns() system call to move the
calling process into the container's namespace. It is not
practical to write in a generically applicable manner. The
nearest that we could get to such an API would be an API which
allows to pass a command + argv to be executed inside a
container. Even if we had such a generic API, this LXC specific
API is still useful, because it allows the caller to maintain
the current process context, in particular any I/O streams they
have open.
NB the virDomainLxcEnterNamespace() API is special in that it
runs client side, so does not involve the internal driver API.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-12-21 13:15:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-06-28 10:37:50 +00:00
|
|
|
|
my %apis;
|
|
|
|
|
# Get the list of all public APIs and their corresponding version
|
|
|
|
|
parseSymsFile(\%apis, "LIBVIRT", $symslibvirt, "$srcdir/../docs/libvirt-api.xml");
|
Introduce an LXC specific public API & library
This patch introduces support for LXC specific public APIs. In
common with what was done for QEMU, this creates a libvirt_lxc.so
library and libvirt/libvirt-lxc.h header file.
The actual APIs are
int virDomainLxcOpenNamespace(virDomainPtr domain,
int **fdlist,
unsigned int flags);
int virDomainLxcEnterNamespace(virDomainPtr domain,
unsigned int nfdlist,
int *fdlist,
unsigned int *noldfdlist,
int **oldfdlist,
unsigned int flags);
which provide a way to use the setns() system call to move the
calling process into the container's namespace. It is not
practical to write in a generically applicable manner. The
nearest that we could get to such an API would be an API which
allows to pass a command + argv to be executed inside a
container. Even if we had such a generic API, this LXC specific
API is still useful, because it allows the caller to maintain
the current process context, in particular any I/O streams they
have open.
NB the virDomainLxcEnterNamespace() API is special in that it
runs client side, so does not involve the internal driver API.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-12-21 13:15:19 +00:00
|
|
|
|
|
2016-06-28 10:37:50 +00:00
|
|
|
|
# And the same for the QEMU specific APIs
|
|
|
|
|
parseSymsFile(\%apis, "LIBVIRT_QEMU", $symsqemu, "$srcdir/../docs/libvirt-qemu-api.xml");
|
Introduce an LXC specific public API & library
This patch introduces support for LXC specific public APIs. In
common with what was done for QEMU, this creates a libvirt_lxc.so
library and libvirt/libvirt-lxc.h header file.
The actual APIs are
int virDomainLxcOpenNamespace(virDomainPtr domain,
int **fdlist,
unsigned int flags);
int virDomainLxcEnterNamespace(virDomainPtr domain,
unsigned int nfdlist,
int *fdlist,
unsigned int *noldfdlist,
int **oldfdlist,
unsigned int flags);
which provide a way to use the setns() system call to move the
calling process into the container's namespace. It is not
practical to write in a generically applicable manner. The
nearest that we could get to such an API would be an API which
allows to pass a command + argv to be executed inside a
container. Even if we had such a generic API, this LXC specific
API is still useful, because it allows the caller to maintain
the current process context, in particular any I/O streams they
have open.
NB the virDomainLxcEnterNamespace() API is special in that it
runs client side, so does not involve the internal driver API.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-12-21 13:15:19 +00:00
|
|
|
|
|
|
|
|
|
# And the same for the LXC specific APIs
|
2016-06-28 10:37:50 +00:00
|
|
|
|
parseSymsFile(\%apis, "LIBVIRT_LXC", $symslxc, "$srcdir/../docs/libvirt-lxc-api.xml");
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Some special things which aren't public APIs,
|
|
|
|
|
# but we want to report
|
2014-12-01 13:36:13 +00:00
|
|
|
|
$apis{virConnectSupportsFeature}->{vers} = "0.3.2";
|
|
|
|
|
$apis{virDomainMigratePrepare}->{vers} = "0.3.2";
|
|
|
|
|
$apis{virDomainMigratePerform}->{vers} = "0.3.2";
|
|
|
|
|
$apis{virDomainMigrateFinish}->{vers} = "0.3.2";
|
|
|
|
|
$apis{virDomainMigratePrepare2}->{vers} = "0.5.0";
|
|
|
|
|
$apis{virDomainMigrateFinish2}->{vers} = "0.5.0";
|
|
|
|
|
$apis{virDomainMigratePrepareTunnel}->{vers} = "0.7.2";
|
|
|
|
|
|
|
|
|
|
$apis{virDomainMigrateBegin3}->{vers} = "0.9.2";
|
|
|
|
|
$apis{virDomainMigratePrepare3}->{vers} = "0.9.2";
|
|
|
|
|
$apis{virDomainMigratePrepareTunnel3}->{vers} = "0.9.2";
|
|
|
|
|
$apis{virDomainMigratePerform3}->{vers} = "0.9.2";
|
|
|
|
|
$apis{virDomainMigrateFinish3}->{vers} = "0.9.2";
|
|
|
|
|
$apis{virDomainMigrateConfirm3}->{vers} = "0.9.2";
|
|
|
|
|
|
|
|
|
|
$apis{virDomainMigrateBegin3Params}->{vers} = "1.1.0";
|
|
|
|
|
$apis{virDomainMigratePrepare3Params}->{vers} = "1.1.0";
|
|
|
|
|
$apis{virDomainMigratePrepareTunnel3Params}->{vers} = "1.1.0";
|
|
|
|
|
$apis{virDomainMigratePerform3Params}->{vers} = "1.1.0";
|
|
|
|
|
$apis{virDomainMigrateFinish3Params}->{vers} = "1.1.0";
|
|
|
|
|
$apis{virDomainMigrateConfirm3Params}->{vers} = "1.1.0";
|
2013-05-20 14:59:08 +00:00
|
|
|
|
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Now we want to get the mapping between public APIs
|
|
|
|
|
# and driver struct fields. This lets us later match
|
|
|
|
|
# update the driver impls with the public APis.
|
|
|
|
|
|
2016-06-28 10:37:50 +00:00
|
|
|
|
my $line;
|
|
|
|
|
|
2011-05-13 10:00:56 +00:00
|
|
|
|
# Group name -> hash of APIs { fields -> api name }
|
|
|
|
|
my %groups;
|
|
|
|
|
my $ingrp;
|
2014-11-11 16:28:26 +00:00
|
|
|
|
foreach my $drivertable (@drivertable) {
|
|
|
|
|
open FILE, "<$drivertable"
|
|
|
|
|
or die "cannot read $drivertable: $!";
|
|
|
|
|
|
|
|
|
|
while (defined($line = <FILE>)) {
|
|
|
|
|
if ($line =~ /struct _(vir\w*Driver)/) {
|
|
|
|
|
my $grp = $1;
|
|
|
|
|
if ($grp ne "virStateDriver" &&
|
|
|
|
|
$grp ne "virStreamDriver") {
|
|
|
|
|
$ingrp = $grp;
|
|
|
|
|
$groups{$ingrp} = { apis => {}, drivers => {} };
|
|
|
|
|
}
|
|
|
|
|
} elsif ($ingrp) {
|
|
|
|
|
if ($line =~ /^\s*vir(?:Drv)(\w+)\s+(\w+);\s*$/) {
|
|
|
|
|
my $field = $2;
|
|
|
|
|
my $name = $1;
|
|
|
|
|
|
|
|
|
|
my $api;
|
|
|
|
|
if (exists $apis{"vir$name"}) {
|
|
|
|
|
$api = "vir$name";
|
2018-03-27 16:24:44 +00:00
|
|
|
|
} elsif ($name =~ /\w+(Open|Close|URIProbe)/) {
|
2014-11-11 16:28:26 +00:00
|
|
|
|
next;
|
|
|
|
|
} else {
|
|
|
|
|
die "driver $name does not have a public API";
|
|
|
|
|
}
|
|
|
|
|
$groups{$ingrp}->{apis}->{$field} = $api;
|
|
|
|
|
} elsif ($line =~ /};/) {
|
|
|
|
|
$ingrp = undef;
|
2012-07-27 12:51:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-11-11 16:28:26 +00:00
|
|
|
|
close FILE;
|
|
|
|
|
}
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Finally, we read all the primary driver files and extract
|
|
|
|
|
# the driver API tables from each one.
|
|
|
|
|
|
|
|
|
|
foreach my $src (@srcs) {
|
|
|
|
|
open FILE, "<$src" or
|
2012-07-27 12:51:28 +00:00
|
|
|
|
die "cannot read $src: $!";
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
2016-06-28 13:16:01 +00:00
|
|
|
|
my $groups_regex = join("|", keys %groups);
|
2011-05-13 10:00:56 +00:00
|
|
|
|
$ingrp = undef;
|
|
|
|
|
my $impl;
|
|
|
|
|
while (defined($line = <FILE>)) {
|
2012-07-27 12:51:28 +00:00
|
|
|
|
if (!$ingrp) {
|
2016-06-28 13:23:58 +00:00
|
|
|
|
# skip non-matching lines early to save time
|
|
|
|
|
next if not $line =~ /$groups_regex/;
|
|
|
|
|
|
2016-06-28 13:16:01 +00:00
|
|
|
|
if ($line =~ /^\s*(?:static\s+)?($groups_regex)\s+(\w+)\s*=\s*{/ ||
|
|
|
|
|
$line =~ /^\s*(?:static\s+)?($groups_regex)\s+NAME\(\w+\)\s*=\s*{/) {
|
|
|
|
|
$ingrp = $1;
|
|
|
|
|
$impl = $src;
|
|
|
|
|
|
|
|
|
|
if ($impl =~ m,.*/node_device_(\w+)\.c,) {
|
|
|
|
|
$impl = $1;
|
|
|
|
|
} else {
|
|
|
|
|
$impl =~ s,.*/(\w+?)_((\w+)_)?(\w+)\.c,$1,;
|
2012-07-27 12:51:28 +00:00
|
|
|
|
}
|
2016-06-28 13:16:01 +00:00
|
|
|
|
|
|
|
|
|
if ($groups{$ingrp}->{drivers}->{$impl}) {
|
|
|
|
|
die "Group $ingrp already contains $impl";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$groups{$ingrp}->{drivers}->{$impl} = {};
|
2012-07-27 12:51:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
2019-06-26 15:45:03 +00:00
|
|
|
|
if ($line =~ m!\s*\.(\w+)\s*=\s*(\w+)\s*,?\s*(?:/\*\s*(\d+\.\d+\.\d+)\s*(?:-\s*(\d+\.\d+\.\d+))?\s*\*/\s*)?$!) {
|
2012-07-27 12:51:28 +00:00
|
|
|
|
my $api = $1;
|
|
|
|
|
my $meth = $2;
|
|
|
|
|
my $vers = $3;
|
2019-06-26 15:45:03 +00:00
|
|
|
|
my $deleted = $4;
|
2012-07-27 12:51:28 +00:00
|
|
|
|
|
|
|
|
|
next if $api eq "no" || $api eq "name";
|
|
|
|
|
|
2019-06-26 15:45:03 +00:00
|
|
|
|
if ($meth eq "NULL" && !defined $deleted) {
|
|
|
|
|
die "Method impl for $api is NULL, but no deleted version is provided";
|
|
|
|
|
}
|
|
|
|
|
if ($meth ne "NULL" && defined $deleted) {
|
|
|
|
|
die "Method impl for $api is non-NULL, but deleted version is provided";
|
|
|
|
|
}
|
2012-07-27 12:51:28 +00:00
|
|
|
|
|
2019-06-26 15:45:03 +00:00
|
|
|
|
die "Method $meth in $src is missing version" unless defined $vers || $api eq "connectURIProbe";
|
2012-07-27 12:51:28 +00:00
|
|
|
|
|
|
|
|
|
if (!exists($groups{$ingrp}->{apis}->{$api})) {
|
2018-03-27 16:24:44 +00:00
|
|
|
|
next if $api =~ /\w(Open|Close|URIProbe)/;
|
2013-04-23 12:49:21 +00:00
|
|
|
|
|
2012-07-27 12:51:28 +00:00
|
|
|
|
die "Found unexpected method $api in $ingrp\n";
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-17 11:59:31 +00:00
|
|
|
|
$groups{$ingrp}->{drivers}->{$impl}->{$api} = {};
|
|
|
|
|
$groups{$ingrp}->{drivers}->{$impl}->{$api}->{vers} = $vers;
|
2019-06-26 15:45:03 +00:00
|
|
|
|
$groups{$ingrp}->{drivers}->{$impl}->{$api}->{deleted} = $deleted;
|
2012-07-27 12:51:28 +00:00
|
|
|
|
if ($api eq "domainMigratePrepare" ||
|
|
|
|
|
$api eq "domainMigratePrepare2" ||
|
|
|
|
|
$api eq "domainMigratePrepare3") {
|
2019-06-17 11:59:31 +00:00
|
|
|
|
if (!$groups{$ingrp}->{drivers}->{$impl}->{"domainMigrate"}) {
|
|
|
|
|
$groups{$ingrp}->{drivers}->{$impl}->{"domainMigrate"} = {};
|
|
|
|
|
$groups{$ingrp}->{drivers}->{$impl}->{"domainMigrate"}->{vers} = $vers;
|
|
|
|
|
}
|
2012-07-27 12:51:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} elsif ($line =~ /}/) {
|
|
|
|
|
$ingrp = undef;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close FILE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# The '.open' driver method is used for 3 public APIs, so we
|
|
|
|
|
# have a bit of manual fixup todo with the per-driver versioning
|
|
|
|
|
# and support matrix
|
|
|
|
|
|
2014-11-11 16:28:26 +00:00
|
|
|
|
$groups{virHypervisorDriver}->{apis}->{"openAuth"} = "virConnectOpenAuth";
|
|
|
|
|
$groups{virHypervisorDriver}->{apis}->{"openReadOnly"} = "virConnectOpenReadOnly";
|
|
|
|
|
$groups{virHypervisorDriver}->{apis}->{"domainMigrate"} = "virDomainMigrate";
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
|
|
|
|
my $openAuthVers = (0 * 1000 * 1000) + (4 * 1000) + 0;
|
|
|
|
|
|
2014-11-11 16:28:26 +00:00
|
|
|
|
foreach my $drv (keys %{$groups{"virHypervisorDriver"}->{drivers}}) {
|
2019-06-17 11:59:31 +00:00
|
|
|
|
my $openVersStr = $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpen"}->{vers};
|
2011-05-13 10:00:56 +00:00
|
|
|
|
my $openVers;
|
|
|
|
|
if ($openVersStr =~ /(\d+)\.(\d+)\.(\d+)/) {
|
2012-07-27 12:51:28 +00:00
|
|
|
|
$openVers = ($1 * 1000 * 1000) + ($2 * 1000) + $3;
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# virConnectOpenReadOnly always matches virConnectOpen version
|
2014-11-11 16:28:26 +00:00
|
|
|
|
$groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenReadOnly"} =
|
|
|
|
|
$groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpen"};
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
2019-06-17 11:59:31 +00:00
|
|
|
|
$groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenAuth"} = {};
|
|
|
|
|
|
2011-05-13 10:00:56 +00:00
|
|
|
|
# virConnectOpenAuth is always 0.4.0 if the driver existed
|
|
|
|
|
# before this time, otherwise it matches the version of
|
|
|
|
|
# the driver's virConnectOpen entry
|
|
|
|
|
if ($openVersStr eq "Y" ||
|
2012-07-27 12:51:28 +00:00
|
|
|
|
$openVers >= $openAuthVers) {
|
2019-06-17 11:59:31 +00:00
|
|
|
|
$groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenAuth"}->{vers} = $openVersStr;
|
2011-05-13 10:00:56 +00:00
|
|
|
|
} else {
|
2019-06-17 11:59:31 +00:00
|
|
|
|
$groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenAuth"}->{vers} = "0.4.0";
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Another special case for the virDomainCreateLinux which was replaced
|
|
|
|
|
# with virDomainCreateXML
|
2014-11-11 16:28:26 +00:00
|
|
|
|
$groups{virHypervisorDriver}->{apis}->{"domainCreateLinux"} = "virDomainCreateLinux";
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
|
|
|
|
my $createAPIVers = (0 * 1000 * 1000) + (0 * 1000) + 3;
|
|
|
|
|
|
2014-11-11 16:28:26 +00:00
|
|
|
|
foreach my $drv (keys %{$groups{"virHypervisorDriver"}->{drivers}}) {
|
2019-06-17 11:59:31 +00:00
|
|
|
|
my $createVersStr = $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateXML"}->{vers};
|
2011-05-13 10:00:56 +00:00
|
|
|
|
next unless defined $createVersStr;
|
|
|
|
|
my $createVers;
|
|
|
|
|
if ($createVersStr =~ /(\d+)\.(\d+)\.(\d+)/) {
|
2012-07-27 12:51:28 +00:00
|
|
|
|
$createVers = ($1 * 1000 * 1000) + ($2 * 1000) + $3;
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-06-17 11:59:31 +00:00
|
|
|
|
$groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateLinux"} = {};
|
|
|
|
|
|
2011-05-13 10:00:56 +00:00
|
|
|
|
# virCreateLinux is always 0.0.3 if the driver existed
|
|
|
|
|
# before this time, otherwise it matches the version of
|
|
|
|
|
# the driver's virCreateXML entry
|
|
|
|
|
if ($createVersStr eq "Y" ||
|
2012-07-27 12:51:28 +00:00
|
|
|
|
$createVers >= $createAPIVers) {
|
2019-06-17 11:59:31 +00:00
|
|
|
|
$groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateLinux"}->{vers} = $createVersStr;
|
2011-05-13 10:00:56 +00:00
|
|
|
|
} else {
|
2019-06-17 11:59:31 +00:00
|
|
|
|
$groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateLinux"}->{vers} = "0.0.3";
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Finally we generate the HTML file with the tables
|
|
|
|
|
|
|
|
|
|
print <<EOF;
|
2013-05-07 10:18:10 +00:00
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
2017-07-26 17:01:25 +00:00
|
|
|
|
<!DOCTYPE html>
|
2013-05-07 10:18:10 +00:00
|
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
2016-10-31 11:25:26 +00:00
|
|
|
|
<body class="hvsupport">
|
2011-05-13 10:00:56 +00:00
|
|
|
|
<h1>libvirt API support matrix</h1>
|
|
|
|
|
|
|
|
|
|
<ul id="toc"></ul>
|
|
|
|
|
|
|
|
|
|
<p>
|
|
|
|
|
This page documents which <a href="html/">libvirt calls</a> work on
|
|
|
|
|
which libvirt drivers / hypervisors, and which version the API appeared
|
2019-06-26 15:45:03 +00:00
|
|
|
|
in. If a hypervisor driver later dropped support for the API, the version
|
|
|
|
|
when it was removed is also mentioned (highlighted in
|
|
|
|
|
<span class="removedhv">dark red</span>).
|
2011-05-13 10:00:56 +00:00
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
2014-11-11 16:28:26 +00:00
|
|
|
|
foreach my $grp (sort { $a cmp $b } keys %groups) {
|
2011-05-13 10:00:56 +00:00
|
|
|
|
print "<h2><a name=\"$grp\">", $groupheaders{$grp}, "</a></h2>\n";
|
|
|
|
|
print <<EOF;
|
|
|
|
|
<table class="top_table">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>API</th>
|
|
|
|
|
<th>Version</th>
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
foreach my $drv (sort { $a cmp $b } keys %{$groups{$grp}->{drivers}}) {
|
2012-07-27 12:51:28 +00:00
|
|
|
|
print " <th>$drv</th>\n";
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print <<EOF;
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
my $row = 0;
|
|
|
|
|
foreach my $field (sort {
|
2012-07-27 12:51:28 +00:00
|
|
|
|
$groups{$grp}->{apis}->{$a}
|
|
|
|
|
cmp
|
|
|
|
|
$groups{$grp}->{apis}->{$b}
|
|
|
|
|
} keys %{$groups{$grp}->{apis}}) {
|
|
|
|
|
my $api = $groups{$grp}->{apis}->{$field};
|
2014-12-01 13:36:13 +00:00
|
|
|
|
my $vers = $apis{$api}->{vers};
|
|
|
|
|
my $htmlgrp = $apis{$api}->{file};
|
2012-07-27 12:51:28 +00:00
|
|
|
|
print <<EOF;
|
2011-05-13 10:00:56 +00:00
|
|
|
|
<tr>
|
2014-12-01 13:36:13 +00:00
|
|
|
|
<td>
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
if (defined $htmlgrp) {
|
|
|
|
|
print <<EOF;
|
|
|
|
|
<a href=\"html/libvirt-$htmlgrp.html#$api\">$api</a>
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
print $api;
|
|
|
|
|
}
|
|
|
|
|
print <<EOF;
|
|
|
|
|
</td>
|
2011-05-13 10:00:56 +00:00
|
|
|
|
<td>$vers</td>
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
foreach my $drv (sort {$a cmp $b } keys %{$groups{$grp}->{drivers}}) {
|
2019-06-17 11:59:31 +00:00
|
|
|
|
print "<td>";
|
2012-07-27 12:51:28 +00:00
|
|
|
|
if (exists $groups{$grp}->{drivers}->{$drv}->{$field}) {
|
2019-06-17 11:59:31 +00:00
|
|
|
|
if ($groups{$grp}->{drivers}->{$drv}->{$field}->{vers}) {
|
|
|
|
|
print $groups{$grp}->{drivers}->{$drv}->{$field}->{vers};
|
|
|
|
|
}
|
2019-06-26 15:45:03 +00:00
|
|
|
|
if ($groups{$grp}->{drivers}->{$drv}->{$field}->{deleted}) {
|
|
|
|
|
print " - <span class=\"removedhv\">", $groups{$grp}->{drivers}->{$drv}->{$field}->{deleted}, "</span>";
|
2019-06-17 11:59:31 +00:00
|
|
|
|
}
|
2012-07-27 12:51:28 +00:00
|
|
|
|
}
|
2019-06-17 11:59:31 +00:00
|
|
|
|
print "</td>\n";
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-27 12:51:28 +00:00
|
|
|
|
print <<EOF;
|
2011-05-13 10:00:56 +00:00
|
|
|
|
</tr>
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
$row++;
|
|
|
|
|
if (($row % 15) == 0) {
|
|
|
|
|
print <<EOF;
|
|
|
|
|
<tr>
|
|
|
|
|
<th>API</th>
|
|
|
|
|
<th>Version</th>
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
foreach my $drv (sort { $a cmp $b } keys %{$groups{$grp}->{drivers}}) {
|
2012-07-27 12:51:28 +00:00
|
|
|
|
print " <th>$drv</th>\n";
|
2011-05-13 10:00:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print <<EOF;
|
|
|
|
|
</tr>
|
|
|
|
|
EOF
|
2012-07-27 12:51:28 +00:00
|
|
|
|
}
|
2011-05-13 10:00:56 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print <<EOF;
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
EOF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print <<EOF;
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
EOF
|