[libvirt] [PULL 0/2] Audio 20190828 patches
by Gerd Hoffmann
The following changes since commit 23919ddfd56135cad3cb468a8f54d5a595f024f4:
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20190827' into staging (2019-08-27 15:52:36 +0100)
are available in the Git repository at:
git://git.kraxel.org/qemu tags/audio-20190828-pull-request
for you to fetch changes up to 4b3b7793e18e1e3edb90bbc21112e875f9ff826d:
audio: omitting audiodev= parameter is only deprecated (2019-08-28 11:57:45 +0200)
----------------------------------------------------------------
audio: two little fixes.
----------------------------------------------------------------
Kővágó, Zoltán (2):
audio: fix invalid malloc size in audio_create_pdos
audio: omitting audiodev= parameter is only deprecated
audio/audio.c | 10 +++++-----
qemu-deprecated.texi | 7 +++++++
2 files changed, 12 insertions(+), 5 deletions(-)
--
2.18.1
5 years, 3 months
[libvirt] [PATCH] docs: rewrite hvsupport.html page generator in python
by Daniel P. Berrangé
As part of an goal to eliminate Perl from libvirt build tools,
rewrite the hvsupport.pl tool in Python.
This was a straight conversion, manually going line-by-line to
change the syntax from Perl to Python. Thus the overall structure
of the file and approach is the same.
The new impl generates byte-for-byte identical output to the
old impl.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
docs/Makefile.am | 6 +-
docs/hvsupport.pl | 458 ---------------------------------------------
docs/hvsupport.py | 463 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 466 insertions(+), 461 deletions(-)
delete mode 100755 docs/hvsupport.pl
create mode 100755 docs/hvsupport.py
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 1cdb584b0b..f7aba5499d 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -194,7 +194,7 @@ EXTRA_DIST= \
$(internals_html_in) $(internals_html) $(fonts) \
$(kbase_html_in) $(kbase_html) \
aclperms.htmlinc \
- hvsupport.pl \
+ hvsupport.py \
$(schema_DATA)
acl_generated = aclperms.htmlinc
@@ -230,11 +230,11 @@ web: $(dot_html) $(internals_html) $(kbase_html) \
hvsupport.html: $(srcdir)/hvsupport.html.in
-$(srcdir)/hvsupport.html.in: $(srcdir)/hvsupport.pl $(api_DATA) \
+$(srcdir)/hvsupport.html.in: $(srcdir)/hvsupport.py $(api_DATA) \
$(top_srcdir)/src/libvirt_public.syms \
$(top_srcdir)/src/libvirt_qemu.syms $(top_srcdir)/src/libvirt_lxc.syms \
$(top_srcdir)/src/driver.h
- $(AM_V_GEN)$(PERL) $(srcdir)/hvsupport.pl $(top_srcdir)/src > $@ \
+ $(AM_V_GEN)$(PYTHON) $(srcdir)/hvsupport.py $(top_srcdir)/src > $@ \
|| { rm $@ && exit 1; }
news.html.in: \
diff --git a/docs/hvsupport.pl b/docs/hvsupport.pl
deleted file mode 100755
index 494b8a27ec..0000000000
--- a/docs/hvsupport.pl
+++ /dev/null
@@ -1,458 +0,0 @@
-#!/usr/bin/env perl
-
-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";
-my $symslxc = "$srcdir/libvirt_lxc.syms";
-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",
- );
-
-my %groupheaders = (
- "virHypervisorDriver" => "Hypervisor APIs",
- "virNetworkDriver" => "Virtual Network APIs",
- "virInterfaceDriver" => "Host Interface APIs",
- "virNodeDeviceDriver" => "Host Device APIs",
- "virStorageDriver" => "Storage Pool APIs",
- "virSecretDriver" => "Secret APIs",
- "virNWFilterDriver" => "Network Filter APIs",
- );
-
-
-my @srcs;
-find({
- wanted => sub {
- if (m!$srcdir/.*/\w+_(driver|common|tmpl|monitor|hal|udev)\.c$!) {
- push @srcs, $_ if $_ !~ /vbox_driver\.c/;
- }
- }, no_chdir => 1}, $srcdir);
-
-# 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;
-}
-
-sub parseSymsFile {
- my $apisref = shift;
- my $prefix = shift;
- my $filename = shift;
- my $xmlfilename = shift;
-
- my $line;
- my $vers;
- my $prevvers;
-
- my $filenames = getAPIFilenames($xmlfilename);
-
- open FILE, "<$filename"
- or die "cannot read $filename: $!";
-
- 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;
- $$apisref{$1}->{file} = $$filenames{$1};
- } else {
- die "unexpected data $line\n";
- }
- }
-
- close FILE;
-}
-
-my %apis;
-# Get the list of all public APIs and their corresponding version
-parseSymsFile(\%apis, "LIBVIRT", $symslibvirt, "$srcdir/../docs/libvirt-api.xml");
-
-# And the same for the QEMU specific APIs
-parseSymsFile(\%apis, "LIBVIRT_QEMU", $symsqemu, "$srcdir/../docs/libvirt-qemu-api.xml");
-
-# And the same for the LXC specific APIs
-parseSymsFile(\%apis, "LIBVIRT_LXC", $symslxc, "$srcdir/../docs/libvirt-lxc-api.xml");
-
-
-# Some special things which aren't public APIs,
-# but we want to report
-$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";
-
-
-
-# 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.
-
-my $line;
-
-# Group name -> hash of APIs { fields -> api name }
-my %groups;
-my $ingrp;
-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";
- } elsif ($name =~ /\w+(Open|Close|URIProbe)/) {
- next;
- } else {
- die "driver $name does not have a public API";
- }
- $groups{$ingrp}->{apis}->{$field} = $api;
- } elsif ($line =~ /};/) {
- $ingrp = undef;
- }
- }
- }
-
- close FILE;
-}
-
-
-# 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
- die "cannot read $src: $!";
-
- my $groups_regex = join("|", keys %groups);
- $ingrp = undef;
- my $impl;
- while (defined($line = <FILE>)) {
- if (!$ingrp) {
- # skip non-matching lines early to save time
- next if not $line =~ /$groups_regex/;
-
- 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,;
- }
-
- if ($groups{$ingrp}->{drivers}->{$impl}) {
- die "Group $ingrp already contains $impl";
- }
-
- $groups{$ingrp}->{drivers}->{$impl} = {};
- }
-
- } else {
- if ($line =~ m!\s*\.(\w+)\s*=\s*(\w+)\s*,?\s*(?:/\*\s*(\d+\.\d+\.\d+)\s*(?:-\s*(\d+\.\d+\.\d+))?\s*\*/\s*)?$!) {
- my $api = $1;
- my $meth = $2;
- my $vers = $3;
- my $deleted = $4;
-
- next if $api eq "no" || $api eq "name";
-
- 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";
- }
-
- die "Method $meth in $src is missing version" unless defined $vers || $api eq "connectURIProbe";
-
- if (!exists($groups{$ingrp}->{apis}->{$api})) {
- next if $api =~ /\w(Open|Close|URIProbe)/;
-
- die "Found unexpected method $api in $ingrp\n";
- }
-
- $groups{$ingrp}->{drivers}->{$impl}->{$api} = {};
- $groups{$ingrp}->{drivers}->{$impl}->{$api}->{vers} = $vers;
- $groups{$ingrp}->{drivers}->{$impl}->{$api}->{deleted} = $deleted;
- if ($api eq "domainMigratePrepare" ||
- $api eq "domainMigratePrepare2" ||
- $api eq "domainMigratePrepare3") {
- if (!$groups{$ingrp}->{drivers}->{$impl}->{"domainMigrate"}) {
- $groups{$ingrp}->{drivers}->{$impl}->{"domainMigrate"} = {};
- $groups{$ingrp}->{drivers}->{$impl}->{"domainMigrate"}->{vers} = $vers;
- }
- }
-
- } elsif ($line =~ /}/) {
- $ingrp = undef;
- }
- }
- }
-
- 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
-
-$groups{virHypervisorDriver}->{apis}->{"openAuth"} = "virConnectOpenAuth";
-$groups{virHypervisorDriver}->{apis}->{"openReadOnly"} = "virConnectOpenReadOnly";
-$groups{virHypervisorDriver}->{apis}->{"domainMigrate"} = "virDomainMigrate";
-
-my $openAuthVers = (0 * 1000 * 1000) + (4 * 1000) + 0;
-
-foreach my $drv (keys %{$groups{"virHypervisorDriver"}->{drivers}}) {
- my $openVersStr = $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpen"}->{vers};
- my $openVers;
- if ($openVersStr =~ /(\d+)\.(\d+)\.(\d+)/) {
- $openVers = ($1 * 1000 * 1000) + ($2 * 1000) + $3;
- }
-
- # virConnectOpenReadOnly always matches virConnectOpen version
- $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenReadOnly"} =
- $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpen"};
-
- $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenAuth"} = {};
-
- # 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" ||
- $openVers >= $openAuthVers) {
- $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenAuth"}->{vers} = $openVersStr;
- } else {
- $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenAuth"}->{vers} = "0.4.0";
- }
-}
-
-
-# Another special case for the virDomainCreateLinux which was replaced
-# with virDomainCreateXML
-$groups{virHypervisorDriver}->{apis}->{"domainCreateLinux"} = "virDomainCreateLinux";
-
-my $createAPIVers = (0 * 1000 * 1000) + (0 * 1000) + 3;
-
-foreach my $drv (keys %{$groups{"virHypervisorDriver"}->{drivers}}) {
- my $createVersStr = $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateXML"}->{vers};
- next unless defined $createVersStr;
- my $createVers;
- if ($createVersStr =~ /(\d+)\.(\d+)\.(\d+)/) {
- $createVers = ($1 * 1000 * 1000) + ($2 * 1000) + $3;
- }
-
- $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateLinux"} = {};
-
- # 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" ||
- $createVers >= $createAPIVers) {
- $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateLinux"}->{vers} = $createVersStr;
- } else {
- $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateLinux"}->{vers} = "0.0.3";
- }
-}
-
-
-# Finally we generate the HTML file with the tables
-
-print <<EOF;
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-<body class="hvsupport">
-<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
-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>).
-</p>
-
-EOF
-
- foreach my $grp (sort { $a cmp $b } keys %groups) {
- print "<h2><a id=\"$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}}) {
- print " <th>$drv</th>\n";
- }
-
- print <<EOF;
-</tr>
-</thead>
-<tbody>
-EOF
-
- my $row = 0;
- foreach my $field (sort {
- $groups{$grp}->{apis}->{$a}
- cmp
- $groups{$grp}->{apis}->{$b}
- } keys %{$groups{$grp}->{apis}}) {
- my $api = $groups{$grp}->{apis}->{$field};
- my $vers = $apis{$api}->{vers};
- my $htmlgrp = $apis{$api}->{file};
- print <<EOF;
-<tr>
-<td>
-EOF
-
- if (defined $htmlgrp) {
- print <<EOF;
-<a href=\"html/libvirt-$htmlgrp.html#$api\">$api</a>
-EOF
-
- } else {
- print $api;
- }
- print <<EOF;
-</td>
-<td>$vers</td>
-EOF
-
- foreach my $drv (sort {$a cmp $b } keys %{$groups{$grp}->{drivers}}) {
- print "<td>";
- if (exists $groups{$grp}->{drivers}->{$drv}->{$field}) {
- if ($groups{$grp}->{drivers}->{$drv}->{$field}->{vers}) {
- print $groups{$grp}->{drivers}->{$drv}->{$field}->{vers};
- }
- if ($groups{$grp}->{drivers}->{$drv}->{$field}->{deleted}) {
- print " - <span class=\"removedhv\">", $groups{$grp}->{drivers}->{$drv}->{$field}->{deleted}, "</span>";
- }
- }
- print "</td>\n";
- }
-
- print <<EOF;
-</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}}) {
- print " <th>$drv</th>\n";
- }
-
- print <<EOF;
-</tr>
-EOF
- }
-
- }
-
- print <<EOF;
-</tbody>
-</table>
-EOF
-}
-
-print <<EOF;
-</body>
-</html>
-EOF
diff --git a/docs/hvsupport.py b/docs/hvsupport.py
new file mode 100755
index 0000000000..502389c25f
--- /dev/null
+++ b/docs/hvsupport.py
@@ -0,0 +1,463 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import sys
+import os.path
+import re
+
+if len(sys.argv) != 2:
+ print("syntax: %s SRCDIR\n" % sys.argv[0], fh=sys.stderr)
+
+srcdir = sys.argv[1]
+
+symslibvirt = os.path.join(srcdir, "libvirt_public.syms")
+symsqemu = os.path.join(srcdir, "libvirt_qemu.syms")
+symslxc = os.path.join(srcdir, "libvirt_lxc.syms")
+drivertablefiles = [
+ os.path.join(srcdir, "driver-hypervisor.h"),
+ os.path.join(srcdir, "driver-interface.h"),
+ os.path.join(srcdir, "driver-network.h"),
+ os.path.join(srcdir, "driver-nodedev.h"),
+ os.path.join(srcdir, "driver-nwfilter.h"),
+ os.path.join(srcdir, "driver-secret.h"),
+ os.path.join(srcdir, "driver-state.h"),
+ os.path.join(srcdir, "driver-storage.h"),
+ os.path.join(srcdir, "driver-stream.h"),
+]
+
+groupheaders = {
+ "virHypervisorDriver": "Hypervisor APIs",
+ "virNetworkDriver": "Virtual Network APIs",
+ "virInterfaceDriver": "Host Interface APIs",
+ "virNodeDeviceDriver": "Host Device APIs",
+ "virStorageDriver": "Storage Pool APIs",
+ "virSecretDriver": "Secret APIs",
+ "virNWFilterDriver": "Network Filter APIs",
+}
+
+
+srcs = []
+for root, dirs, files in os.walk(srcdir):
+ for file in files:
+ if ((file.endswith("driver.c") and
+ not file.endswith("vbox_driver.c")) or
+ file.endswith("common.c") or
+ file.endswith("tmpl.c") or
+ file.endswith("monitor.c") or
+ file.endswith("hal.c") or
+ file.endswith("udev.c")):
+ srcs.append(os.path.join(root, file))
+
+
+# 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.
+def getAPIFilenames(filename):
+ files = {}
+
+ with open(filename) as fh:
+ prog = re.compile(r"\s*<function name='([^']+)' file='([^']+)'.*")
+ for line in fh:
+ res = prog.match(line)
+ if res is not None:
+ files[res.group(1)] = res.group(2)
+
+ if len(files) == 0:
+ raise Exception("No functions found in %s. Has the apibuild.py output changed?" % filename)
+
+ return files;
+
+
+def parseSymsFile(apisref, prefix, filename, xmlfilename):
+ vers = None
+ prevvers = None
+
+ filenames = getAPIFilenames(xmlfilename)
+
+ with open(filename) as fh:
+ groupstartprog = re.compile(r"^\s*%s_(\d+\.\d+\.\d+)\s*{\s*$" % prefix)
+ groupendprog1 = re.compile(r"^\s*}\s*;\s*$")
+ groupendprog2 = re.compile(r"^\s*}\s*%s_(\d+\.\d+\.\d+)\s*;\s*$" % prefix)
+ symbolprog = re.compile(r"^\s*(\w+)\s*;\s*$")
+ for line in fh:
+ line = line.strip()
+
+ if line == "":
+ continue
+ if line[0] == '#':
+ continue
+ if line.startswith("global:"):
+ continue
+ if line.startswith("local:"):
+ continue
+
+ groupstartmatch = groupstartprog.match(line)
+ groupendmatch1 = groupendprog1.match(line)
+ groupendmatch2 = groupendprog2.match(line)
+ symbolmatch = symbolprog.match(line)
+ if groupstartmatch is not None:
+ if vers is not None:
+ raise Exception("malformed syms file when starting group")
+
+ vers = groupstartmatch.group(1)
+ elif groupendmatch1 is not None:
+ if prevvers is not None:
+ raise Exception("malformed syms file when ending group")
+
+ prevvers = vers
+ vers = None
+ elif groupendmatch2 is not None:
+ if groupendmatch2.group(1) != prevvers:
+ raise Exception("malformed syms file %s != %s when ending group" % (
+ groupendmatch2.group(1), prevvers))
+
+ prevvers = vers
+ vers = None
+ elif symbolmatch is not None:
+ name = symbolmatch.group(1)
+ apisref[name] = {
+ "vers": vers,
+ "file": filenames.get(name),
+ }
+ else:
+ raise Exception("unexpected data %s" % line)
+
+
+apis = {}
+# Get the list of all public APIs and their corresponding version
+parseSymsFile(apis, "LIBVIRT", symslibvirt, os.path.join(srcdir, "../docs/libvirt-api.xml"))
+
+# And the same for the QEMU specific APIs
+parseSymsFile(apis, "LIBVIRT_QEMU", symsqemu, os.path.join(srcdir, "../docs/libvirt-qemu-api.xml"))
+
+# And the same for the LXC specific APIs
+parseSymsFile(apis, "LIBVIRT_LXC", symslxc, os.path.join(srcdir, "../docs/libvirt-lxc-api.xml"))
+
+
+# Some special things which aren't public APIs,
+# but we want to report
+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"
+}
+
+
+# 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.
+
+# Group name -> hash of APIs { fields -> api name }
+groups = {}
+ingrp = None
+for drivertablefile in drivertablefiles:
+ with open(drivertablefile) as fh:
+ starttableprog = re.compile(r"struct _(vir\w*Driver)")
+ endtableprog = re.compile(r"};")
+ callbackprog = re.compile(r"^\s*vir(?:Drv)(\w+)\s+(\w+);\s*$")
+ ignoreapiprog = re.compile(r"\w+(Open|Close|URIProbe)")
+ for line in fh:
+ starttablematch = starttableprog.match(line)
+ if starttablematch is not None:
+ grp = starttablematch.group(1)
+ if grp != "virStateDriver" and grp != "virStreamDriver":
+ ingrp = grp
+ groups[ingrp] = {
+ "apis": {},
+ "drivers": {}
+ }
+ elif ingrp != None:
+ callbackmatch = callbackprog.match(line)
+ if callbackmatch is not None:
+ name = callbackmatch.group(1)
+ field = callbackmatch.group(2)
+
+ api = "vir" + name
+ if api in apis:
+ groups[ingrp]["apis"][field] = api
+ elif ignoreapiprog.match(api) != None:
+ continue
+ else:
+ raise Exception("driver %s does not have a public API" % name)
+ elif endtableprog.match(line):
+ ingrp = None
+
+
+# Finally, we read all the primary driver files and extract
+# the driver API tables from each one.
+
+for src in srcs:
+ with open(src) as fh:
+ groupsre = "|".join(groups.keys())
+ groupsprog2 = re.compile(r"^\s*(static\s+)?(" + groupsre + r")\s+(\w+)\s*=\s*{")
+ groupsprog3 = re.compile(r"^\s*(static\s+)?(" + groupsre + r")\s+NAME\(\w+\)\s*=\s*{")
+ nodedevimplprog = re.compile(r".*/node_device_(\w+)\.c")
+ miscimplprog = re.compile(r".*/(\w+?)_((\w+)_)?(\w+)\.c")
+ callbackprog = re.compile(r"\s*\.(\w+)\s*=\s*(\w+)\s*,?\s*(?:/\*\s*(\d+\.\d+\.\d+)\s*(?:-\s*(\d+\.\d+\.\d+))?\s*\*/\s*)?$")
+ skipapiprog = re.compile(r"\w+(Open|Close|URIProbe)")
+
+ ingrp = None
+ impl = None
+ for line in fh:
+ if ingrp is None:
+ m = groupsprog2.match(line)
+ if m is None:
+ m = groupsprog3.match(line)
+ if m is not None:
+ ingrp = m.group(2)
+ impl = src
+
+ implmatch = nodedevimplprog.match(impl)
+ if implmatch is None:
+ implmatch = miscimplprog.match(impl)
+ if implmatch is None:
+ raise Exception("Unexpected impl format '%s'" % impl)
+ impl = implmatch.group(1)
+
+ if impl in groups[ingrp]["drivers"]:
+ raise Exception("Group %s already contains %s" % (ingrp, impl))
+
+ groups[ingrp]["drivers"][impl] = {}
+ else:
+ callbackmatch = callbackprog.match(line)
+ if callbackmatch is not None:
+ api = callbackmatch.group(1)
+ meth = callbackmatch.group(2)
+ vers = callbackmatch.group(3)
+ deleted = callbackmatch.group(4)
+
+ if api == "no" or api == "name":
+ continue
+
+ if meth == "NULL" and deleted is None:
+ raise Exception("Method impl for %s is NULL, but no deleted version is provided" % api)
+
+ if meth != "NULL" and deleted is not None:
+ raise Exception("Method impl for %s is non-NULL, but deleted version is provided" % api)
+
+ if vers is None and api != "connectURIProbe":
+ raise Exception("Method %s in %s is missing version" % (meth, src))
+
+ if api not in groups[ingrp]["apis"]:
+ if skipapiprog.match(api):
+ continue
+
+ raise Exception("Found unexpected method %s in %s" % (api, ingrp))
+
+ groups[ingrp]["drivers"][impl][api] = {
+ "vers": vers,
+ "deleted": deleted,
+ }
+
+ if (api == "domainMigratePrepare" or
+ api == "domainMigratePrepare2" or
+ api == "domainMigratePrepare3"):
+ if "domainMigrate" not in groups[ingrp]["drivers"][impl]:
+ groups[ingrp]["drivers"][impl]["domainMigrate"] = {
+ "vers": vers,
+ }
+ elif line.find("}") != -1:
+ ingrp = None
+
+
+# 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
+
+groups["virHypervisorDriver"]["apis"]["openAuth"] = "virConnectOpenAuth"
+groups["virHypervisorDriver"]["apis"]["openReadOnly"] = "virConnectOpenReadOnly"
+groups["virHypervisorDriver"]["apis"]["domainMigrate"] = "virDomainMigrate"
+
+openAuthVers = (0 * 1000 * 1000) + (4 * 1000) + 0;
+
+for drv in groups["virHypervisorDriver"]["drivers"].keys():
+ openVersStr = groups["virHypervisorDriver"]["drivers"][drv]["connectOpen"]["vers"]
+ openVers = 0
+ if openVersStr != "Y":
+ openVersBits = openVersStr.split(".")
+ if len(openVersBits) != 3:
+ raise Exception("Expected 3 digit version for %s" % openVersStr)
+ openVers = (int(openVersBits[0]) * 1000 * 1000) + (int(openVersBits[1]) * 1000) + int(openVersBits[2])
+
+ # virConnectOpenReadOnly always matches virConnectOpen version
+ groups["virHypervisorDriver"]["drivers"][drv]["connectOpenReadOnly"] = \
+ groups["virHypervisorDriver"]["drivers"][drv]["connectOpen"]
+
+ # 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 == "Y" or openVers >= openAuthVers:
+ vers = openVersStr
+ else:
+ vers = "0.4.0"
+ groups["virHypervisorDriver"]["drivers"][drv]["connectOpenAuth"] = {
+ "vers": vers,
+ }
+
+
+# Another special case for the virDomainCreateLinux which was replaced
+# with virDomainCreateXML
+groups["virHypervisorDriver"]["apis"]["domainCreateLinux"] = "virDomainCreateLinux";
+
+createAPIVers = (0 * 1000 * 1000) + (0 * 1000) + 3;
+
+for drv in groups["virHypervisorDriver"]["drivers"].keys():
+ if "domainCreateXML" not in groups["virHypervisorDriver"]["drivers"][drv]:
+ continue
+ createVersStr = groups["virHypervisorDriver"]["drivers"][drv]["domainCreateXML"]["vers"]
+ createVers = 0
+ if createVersStr != "Y":
+ createVersBits = createVersStr.split(".")
+ if len(createVersBits) != 3:
+ raise Exception("Expected 3 digit version for %s" % createVersStr)
+ createVers = (int(createVersBits[0]) * 1000 * 1000) + (int(createVersBits[1]) * 1000) + int(createVersBits[2])
+
+ # 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 == "Y" or createVers >= createAPIVers:
+ vers = createVersStr
+ else:
+ vers = "0.0.3"
+
+ groups["virHypervisorDriver"]["drivers"][drv]["domainCreateLinux"] = {
+ "vers": vers,
+ }
+
+
+# Finally we generate the HTML file with the tables
+
+print('''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<body class="hvsupport">
+<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
+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>).
+</p>
+''')
+
+for grp in sorted(groups.keys()):
+ print("<h2><a id=\"%s\">%s</a></h2>" % (grp, groupheaders[grp]))
+ print('''<table class="top_table">
+<thead>
+<tr>
+<th>API</th>
+<th>Version</th>''')
+
+ for drv in sorted(groups[grp]["drivers"].keys()):
+ print(" <th>%s</th>" % drv)
+
+
+ print('''</tr>
+</thead>
+<tbody>''')
+
+ row = 0
+ def sortkey(field):
+ return groups[grp]["apis"][field]
+ for field in sorted(groups[grp]["apis"].keys(), key=sortkey):
+ api = groups[grp]["apis"][field]
+ vers = apis[api]["vers"]
+ htmlgrp = apis[api].get("file")
+ print("<tr>")
+
+ if htmlgrp is not None:
+ print('''<td>\n<a href=\"html/libvirt-%s.html#%s\">%s</a>\n</td>''' % (htmlgrp, api, api))
+ else:
+ print("<td>\n%s</td>" % api)
+
+ print("<td>%s</td>" % vers)
+
+ for drv in sorted(groups[grp]["drivers"].keys()):
+ info = ""
+ if field in groups[grp]["drivers"][drv]:
+ vers = groups[grp]["drivers"][drv][field]["vers"]
+ if vers is not None:
+ info = info + vers
+
+ deleted = groups[grp]["drivers"][drv][field].get("deleted")
+ if deleted is not None:
+ info = info + (''' - <span class="removedhv">%s</span>''' % deleted)
+
+ print("<td>%s</td>" % info)
+
+ print("</tr>")
+
+ row = row + 1
+ if (row % 15) == 0:
+ print('''<tr>
+<th>API</th>
+<th>Version</th>''')
+
+ for drv in sorted(groups[grp]["drivers"].keys()):
+ print(" <th>%s</th>" % drv)
+
+ print("</tr>")
+
+ print("</tbody>\n</table>")
+
+print("</body>\n</html>")
--
2.21.0
5 years, 3 months
[libvirt] [PATCH] xenconfig: move contents to libxl driver and remove directory
by Jim Fehlig
Signed-off-by: Jim Fehlig <jfehlig(a)suse.com>
---
cfg.mk | 2 +-
configure.ac | 2 --
po/POTFILES | 6 ++---
src/Makefile.am | 1 -
src/libvirt_xenconfig.syms | 12 ----------
src/libxl/Makefile.inc.am | 25 ++++++---------------
src/{xenconfig => libxl}/xen_common.c | 0
src/{xenconfig => libxl}/xen_common.h | 0
src/{xenconfig => libxl}/xen_xl.c | 0
src/{xenconfig => libxl}/xen_xl.h | 0
src/{xenconfig => libxl}/xen_xm.c | 0
src/{xenconfig => libxl}/xen_xm.h | 0
src/{xenconfig => libxl}/xenxs_private.h | 0
src/xenconfig/Makefile.inc.am | 28 ------------------------
tests/xlconfigtest.c | 2 +-
tests/xmconfigtest.c | 2 +-
16 files changed, 13 insertions(+), 67 deletions(-)
diff --git a/cfg.mk b/cfg.mk
index c459ad443f..1f29729949 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -791,7 +791,7 @@ sc_prohibit_cross_inclusion:
access/ | conf/) safe="($$dir|conf|util)";; \
cpu/| network/| node_device/| rpc/| security/| storage/) \
safe="($$dir|util|conf|storage)";; \
- xenapi/ | xenconfig/ ) safe="($$dir|util|conf|xen|cpu)";; \
+ xenapi/) safe="($$dir|util|conf|xen|cpu)";; \
*) safe="($$dir|$(mid_dirs)|util)";; \
esac; \
in_vc_files="^src/$$dir" \
diff --git a/configure.ac b/configure.ac
index a60543072d..890702a89d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -465,8 +465,6 @@ LIBVIRT_DRIVER_CHECK_LIBVIRTD
LIBVIRT_DRIVER_CHECK_NETWORK
LIBVIRT_DRIVER_CHECK_INTERFACE
-AM_CONDITIONAL([WITH_XENCONFIG], [test "$with_libxl" = "yes"])
-
dnl
dnl in case someone want to build static binaries
diff --git a/po/POTFILES b/po/POTFILES
index c62bc32bb2..e466e1bc55 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -88,6 +88,9 @@ src/libxl/libxl_conf.c
src/libxl/libxl_domain.c
src/libxl/libxl_driver.c
src/libxl/libxl_migration.c
+src/libxl/xen_common.c
+src/libxl/xen_xl.c
+src/libxl/xen_xm.c
src/locking/lock_daemon.c
src/locking/lock_daemon_dispatch.c
src/locking/lock_driver_lockd.c
@@ -291,9 +294,6 @@ src/vz/vz_utils.c
src/vz/vz_utils.h
src/xenapi/xenapi_driver.c
src/xenapi/xenapi_utils.c
-src/xenconfig/xen_common.c
-src/xenconfig/xen_xl.c
-src/xenconfig/xen_xm.c
tests/virpolkittest.c
tools/libvirt-guests.sh.in
tools/virsh-checkpoint.c
diff --git a/src/Makefile.am b/src/Makefile.am
index adaf61350a..6626659113 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -118,7 +118,6 @@ include vbox/Makefile.inc.am
include openvz/Makefile.inc.am
include qemu/Makefile.inc.am
include bhyve/Makefile.inc.am
-include xenconfig/Makefile.inc.am
include libxl/Makefile.inc.am
include xenapi/Makefile.inc.am
include vz/Makefile.inc.am
diff --git a/src/libvirt_xenconfig.syms b/src/libvirt_xenconfig.syms
deleted file mode 100644
index 6e2e578b15..0000000000
--- a/src/libvirt_xenconfig.syms
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# These symbols are dependent upon --with-xen via WITH_XEN or --with-libxl via WITH_LIBXL.
-#
-
-# xenconfig/xen_xm.h
-xenFormatXM;
-xenParseXM;
-
-# Let emacs know we want case-insensitive sorting
-# Local Variables:
-# sort-fold-case: t
-# End:
diff --git a/src/libxl/Makefile.inc.am b/src/libxl/Makefile.inc.am
index 1587404586..560b214877 100644
--- a/src/libxl/Makefile.inc.am
+++ b/src/libxl/Makefile.inc.am
@@ -1,6 +1,13 @@
# vim: filetype=automake
LIBXL_DRIVER_SOURCES = \
+ libxl/xenxs_private.h \
+ libxl/xen_common.c \
+ libxl/xen_common.h \
+ libxl/xen_xl.c \
+ libxl/xen_xl.h \
+ libxl/xen_xm.c \
+ libxl/xen_xm.h \
libxl/libxl_conf.c \
libxl/libxl_conf.h \
libxl/libxl_capabilities.c \
@@ -15,29 +22,13 @@ LIBXL_DRIVER_SOURCES = \
libxl/libxl_migration.h \
$(NULL)
-XENCONFIG_LIBXL_SOURCES = \
- $(XENCONFIG_SOURCES) \
- xenconfig/xen_xl.c \
- xenconfig/xen_xl.h \
- $(NULL)
-
DRIVER_SOURCE_FILES += $(LIBXL_DRIVER_SOURCES)
STATEFUL_DRIVER_SOURCE_FILES += $(LIBXL_DRIVER_SOURCES)
EXTRA_DIST += \
$(LIBXL_DRIVER_SOURCES) \
- $(XENCONFIG_LIBXL_SOURCES) \
$(NULL)
if WITH_LIBXL
-noinst_LTLIBRARIES += libvirt_xenconfig_libxl.la
-libvirt_xenconfig_libxl_la_LIBADD = $(LIBXL_LIBS)
-libvirt_xenconfig_libxl_la_CFLAGS = \
- -I$(srcdir)/conf \
- -I$(srcdir)/libxl \
- $(AM_CFLAGS) \
- $(NULL)
-libvirt_xenconfig_libxl_la_SOURCES = $(XENCONFIG_LIBXL_SOURCES)
-
noinst_LTLIBRARIES += libvirt_driver_libxl_impl.la
libvirt_driver_libxl_la_SOURCES =
libvirt_driver_libxl_la_LIBADD = \
@@ -54,14 +45,12 @@ libvirt_driver_libxl_impl_la_CFLAGS = \
-I$(srcdir)/access \
-I$(srcdir)/conf \
-I$(srcdir)/secret \
- -I$(srcdir)/xenconfig \
$(AM_CFLAGS) \
$(NULL)
libvirt_driver_libxl_impl_la_LDFLAGS = $(AM_LDFLAGS)
libvirt_driver_libxl_impl_la_LIBADD = \
$(LIBXL_LIBS) \
$(LIBXML_LIBS) \
- libvirt_xenconfig_libxl.la \
$(NULL)
libvirt_driver_libxl_impl_la_SOURCES = $(LIBXL_DRIVER_SOURCES)
diff --git a/src/xenconfig/xen_common.c b/src/libxl/xen_common.c
similarity index 100%
rename from src/xenconfig/xen_common.c
rename to src/libxl/xen_common.c
diff --git a/src/xenconfig/xen_common.h b/src/libxl/xen_common.h
similarity index 100%
rename from src/xenconfig/xen_common.h
rename to src/libxl/xen_common.h
diff --git a/src/xenconfig/xen_xl.c b/src/libxl/xen_xl.c
similarity index 100%
rename from src/xenconfig/xen_xl.c
rename to src/libxl/xen_xl.c
diff --git a/src/xenconfig/xen_xl.h b/src/libxl/xen_xl.h
similarity index 100%
rename from src/xenconfig/xen_xl.h
rename to src/libxl/xen_xl.h
diff --git a/src/xenconfig/xen_xm.c b/src/libxl/xen_xm.c
similarity index 100%
rename from src/xenconfig/xen_xm.c
rename to src/libxl/xen_xm.c
diff --git a/src/xenconfig/xen_xm.h b/src/libxl/xen_xm.h
similarity index 100%
rename from src/xenconfig/xen_xm.h
rename to src/libxl/xen_xm.h
diff --git a/src/xenconfig/xenxs_private.h b/src/libxl/xenxs_private.h
similarity index 100%
rename from src/xenconfig/xenxs_private.h
rename to src/libxl/xenxs_private.h
diff --git a/src/xenconfig/Makefile.inc.am b/src/xenconfig/Makefile.inc.am
deleted file mode 100644
index 5785b49268..0000000000
--- a/src/xenconfig/Makefile.inc.am
+++ /dev/null
@@ -1,28 +0,0 @@
-# vim: filetype=automake
-
-XENCONFIG_SOURCES = \
- xenconfig/xenxs_private.h \
- xenconfig/xen_common.c \
- xenconfig/xen_common.h \
- xenconfig/xen_xm.c \
- xenconfig/xen_xm.h \
- $(NULL)
-
-EXTRA_DIST += $(XENCONFIG_SOURCES)
-
-if WITH_XENCONFIG
-noinst_LTLIBRARIES += libvirt_xenconfig.la
-libvirt_la_BUILT_LIBADD += libvirt_xenconfig.la
-libvirt_xenconfig_la_CFLAGS = \
- -I$(srcdir)/conf \
- $(AM_CFLAGS) \
- $(NULL)
-libvirt_xenconfig_la_SOURCES = $(XENCONFIG_SOURCES)
-
-endif WITH_XENCONFIG
-
-if WITH_XENCONFIG
-USED_SYM_FILES += $(srcdir)/libvirt_xenconfig.syms
-else ! WITH_XENCONFIG
-SYM_FILES += $(srcdir)/libvirt_xenconfig.syms
-endif ! WITH_XENCONFIG
diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c
index 59171606d1..ae0db71293 100644
--- a/tests/xlconfigtest.c
+++ b/tests/xlconfigtest.c
@@ -27,7 +27,7 @@
#include "internal.h"
#include "datatypes.h"
-#include "xenconfig/xen_xl.h"
+#include "libxl/xen_xl.h"
#include "viralloc.h"
#include "virstring.h"
#include "testutils.h"
diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c
index 1de3c33f69..3137dc564c 100644
--- a/tests/xmconfigtest.c
+++ b/tests/xmconfigtest.c
@@ -25,7 +25,7 @@
#include "internal.h"
#include "datatypes.h"
-#include "xenconfig/xen_xm.h"
+#include "libxl/xen_xm.h"
#include "testutils.h"
#include "testutilsxen.h"
#include "viralloc.h"
--
2.22.0
5 years, 3 months
[libvirt] [RFC] On present using dummy hostdev usb device
by Nikolay Shirokovskiy
Hi, all!
We use an interesting approach when starting/migrating/etc domain with usb
hostdev with startupPolicy=optional. We add qemu usb-host device with
missing hostaddr/hostbus parameters (dummy device). I guess there are
2 reasons why we do it. First without dummy device migration will fail as
described in [1]. Second is an interesting property of dummy device that
qemu starts to monitor for attaching of usb devices and binds the first
attached to node to the dummy device. So one can start a domain with
missing hostdev and attach it later or migrate a domain then detach
hostdev on source and attach it on destination. But as qemu binds the
first attached device this is not reliable, to say the least. And after
all this does not work if domain uses distinct mount namespace which
is default.
So I question does it make sense to use dummy device at all? In case of
migration/resume from suspend/revert to snapshot we can either fix qemu to
ignore incoming missing hostdev data or add dummy device temporarily. The
latter solution is worse as it brings dummy device behaviour even for a short
period of time. However having a temporary dummy device is neccessary step
towards the time when all supported versions of qemu do the mentioned ignoring.
As to handling attaching of missing hostdev device to node it should be done in
libvirt which can do necessary mount namespace actions. (Actually I developing
such patches right now but some peculiarities of dummy device bring me here).
Nikolay
[1] https://www.redhat.com/archives/libvir-list/2012-October/msg00440.html
5 years, 3 months
[libvirt] [rust PATCH] Add list_all_volumes method for storage_pool::StoragePool
by Sage Imel
From: Sage Imel <sage(a)sagenite.net>
Always returns the full list of volumes,
can't just ask it how many volumes are in the pool
Signed-off-by: Sage Imel <sage(a)cat.pdx.edu>
---
src/storage_pool.rs | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/storage_pool.rs b/src/storage_pool.rs
index 38676c2..e8ed21c 100644
--- a/src/storage_pool.rs
+++ b/src/storage_pool.rs
@@ -18,7 +18,7 @@
extern crate libc;
-use std::str;
+use std::{str, ptr};
use connect::sys::virConnectPtr;
use storage_vol::sys::virStorageVolPtr;
@@ -57,6 +57,10 @@ extern "C" {
xml: *const libc::c_char,
flags: libc::c_uint)
-> sys::virStoragePoolPtr;
+ fn virStoragePoolListAllVolumes(ptr: sys::virStoragePoolPtr,
+ vols: *mut *mut virStorageVolPtr,
+ flags:libc::c_uint)
+ -> libc::c_int;
fn virStoragePoolLookupByID(c: virConnectPtr, id: libc::c_int) -> sys::virStoragePoolPtr;
fn virStoragePoolLookupByName(c: virConnectPtr,
id: *const libc::c_char)
@@ -103,6 +107,8 @@ pub const STORAGE_POOL_CREATE_WITH_BUILD: StoragePoolCreateFlags = 1 << 0;
pub const STORAGE_POOL_CREATE_WITH_BUILD_OVERWRITE: StoragePoolCreateFlags = 1 << 1;
pub const STORAGE_POOL_CREATE_WITH_BUILD_NO_OVERWRITE: StoragePoolCreateFlags = 1 << 2;
+pub type VirStoragePoolListAllVolumesFlags = self::libc::c_uint;
+
pub type StoragePoolState = self::libc::c_uint;
pub const VIR_STORAGE_POOL_INACTIVE: StoragePoolState = 0;
pub const VIR_STORAGE_POOL_BUILDING: StoragePoolState = 1;
@@ -201,6 +207,27 @@ impl StoragePool {
}
}
+ pub fn list_all_volumes(&self,
+ flags: VirStoragePoolListAllVolumesFlags)
+ -> Result<Vec<StorageVol>, Error> {
+ unsafe {
+ let mut volumes: *mut virStorageVolPtr = ptr::null_mut();
+ let size =
+ virStoragePoolListAllVolumes(self.as_ptr(), &mut volumes, flags as libc::c_uint);
+ if size == -1 {
+ return Err(Error::new());
+ }
+
+ let mut array: Vec<StorageVol> = Vec::new();
+ for x in 0..size as isize {
+ array.push(StorageVol::new(*volumes.offset(x)));
+ }
+ libc::free(volumes as *mut libc::c_void);
+
+ return Ok(array);
+ }
+ }
+
pub fn lookup_by_id(conn: &Connect, id: u32) -> Result<StoragePool, Error> {
unsafe {
let ptr = virStoragePoolLookupByID(conn.as_ptr(), id as libc::c_int);
--
2.17.1
5 years, 3 months
[libvirt] [glib PATCH 0/2] Add gvir_config_domain_os_get_firmware() + _domain_os_get_machine() test
by Fabiano Fidêncio
This series adds a way to retrive the DomainOs' Firmware set (with
tests) and, while touching that code, also adds one more check for
gvir_config_domain_os_get_machine().
Fabiano Fidêncio (2):
gconfig: Add _domain_os_get_firmware()
tests,test-gconfig: Check _domain_os_get_machine()
libvirt-gconfig/libvirt-gconfig-domain-os.c | 12 ++++++++++++
libvirt-gconfig/libvirt-gconfig-domain-os.h | 1 +
libvirt-gconfig/libvirt-gconfig.sym | 1 +
tests/test-gconfig.c | 3 +++
4 files changed, 17 insertions(+)
--
2.21.0
5 years, 3 months
[libvirt] [PATCH v4 1/4] lib: minor fixes to virDomainGetGuestInfo docs
by Jonathon Jongsma
Due to a typo, some of the field names didn't have closing quotes and
the information about the hostname was omitted.
Signed-off-by: Jonathon Jongsma <jjongsma(a)redhat.com>
---
src/libvirt-domain.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index cea4d2c11b..bc24090e2e 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12237,10 +12237,10 @@ virDomainSetVcpu(virDomainPtr domain,
*
* "user.count" - the number of active users on this domain as an
* unsigned int
- * "user.<num>.name - username of the user as a string
- * "user.<num>.domain - domain of the user as a string (may only be
+ * "user.<num>.name" - username of the user as a string
+ * "user.<num>.domain" - domain of the user as a string (may only be
* present on certain guest types)
- * "user.<num>.login-time - the login time of a user in milliseconds
+ * "user.<num>.login-time" - the login time of a user in milliseconds
* since the epoch as unsigned long long
*
* VIR_DOMAIN_GUEST_INFO_OS:
@@ -12288,6 +12288,12 @@ virDomainSetVcpu(virDomainPtr domain,
* "fs.<num>.disk.<num>.serial" - the serial number of the disk
* "fs.<num>.disk.<num>.device" - the device node of the disk
*
+ * VIR_DOMAIN_GUEST_INFO_HOSTNAME:
+ * Returns information about the hostname of the domain. The typed
+ * parameter keys are in this format:
+ *
+ * "hostname" - the hostname of the domain
+ *
* Using 0 for @types returns all information groups supported by the given
* hypervisor.
*
--
2.21.0
5 years, 3 months
Re: [libvirt] [BUG] When PLUG a bridge interface to an active VM, the generated LIVE and CONFIG mac address are different
by wujing (O)
> On 8/28/19 11:42 AM, wujing (O) wrote:
> >>>>> On 8/22/19 10:43 AM, Xu Yandong (Yandong Xu) wrote:
> >>>> That possibly might be out of scope, but autofilling the mac
> >>>> address as early as virDomainNetDefParseXML also is not ideal.
> >>>
> >>> We have pushed a patch bellow that can restore the situation to an
> >>> older
> >> state.
> >>>
> >>> Subject: [PATCH] qemu: use the same def when attaching device live
> >>> and config
> >>>
> >>> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index
> >>> 617d7d5..eca54d0 100644
> >>> --- a/src/qemu/qemu_driver.c
> >>> +++ b/src/qemu/qemu_driver.c
> >>> @@ -8615,6 +8615,22 @@
> >> qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
> >>> if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
> >>> goto cleanup;
> >>>
> >>> + if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
> >>> + flags & VIR_DOMAIN_AFFECT_LIVE) {
> >>> + /* If we are affecting both CONFIG and LIVE
> >>> + * use the same xml of device preferentially
> >>> + * to make the configuration consistent.
> >>> + */
> >>> + devLive = virDomainDeviceDefParse(xml, vm->def,
> >>
> >> This use of vm->def prefers live XML. This means that for instance
> >> PCI address are assigned based on current PCI layout in live XML
> >> which in general is different to inactive XML.
> >>
> >> And it's not only PCI addresses, we autogenerate some out aspects of
> >> <interface/> (e.g. model) and even more for other devices. Just take
> >> a look at qemuDomainDeviceDefPostParse(). All functions there which
> >> take domain def as an argument do so because they are basing
> >> autogenerated value on domain definition. Plus there's more in parser
> code.
> >>
> >> While your patch might work for your use case, it can break others.
> >>
> >> BTW: have you read the original commit that caused this? I'm failing
> >> to see how we would not re-introduce the problem with your patch. If
> >> you're using live XML to validate/generate device addresses, how can
> >> we generate valid address for inactive XML?
> >>
> >
> > This patch is a little different with the original commit, since we
> > only prefer live XML when using LIVE AND CONFIG flags at the same time.
> Still parse separate device def if attach with only one flag.
> > So this patch is kinda a combination of 1e0534a7702 and 55ce6564634, just
> to narrow down the problem influence.
> >
> > And I verified as the steps in
> https://bugzilla.redhat.com/show_bug.cgi?id=1559867, work as expected.
>
> Well, then try to coldplug <hostdev mode='subsystem' type='scsi'/> (that is
> only to inactive XML), and then try hotplug different <hostdev type'scsi'/> to
> both live and inactive XMLs and the bug will reproduce.
> Problem is, that inactive XML contains a device which is not contained in live
> XML and thus when generating device address based solely on live XML a
> conflicting address is generated.
>
> If we'd prefer inactive XML in your patch then the steps in my reproducer
> need to be swapped. At any rate, the issue is still there.
You are right, but I found a new issue on current solution.
Test as steps below.
1. Having a running vm
## virsh list
Id Name State
---------------------- │~
1 rhel running
2. prepare 2 scsi hostdev xml using the same address
## cat h1.xml
<hostdev mode='subsystem' type='scsi' managed='no'>
<source>
<adapter name='scsi_host2'/>
<address bus='0' target='0' unit='0'/>
</source>
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
</hostdev>
## cat h2.xml
<hostdev mode='subsystem' type='scsi' managed='no'>
<source>
<adapter name='scsi_host3'/>
<address bus='0' target='0' unit='0'/>
</source>
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
</hostdev>
3. attach 2 hostdev to vm with 'attach-device --config'
## virsh attach-device rhel h1.xml --config
Device attached successfully
## virsh attach-device rhel h2.xml --config
Device attached successfully
4. Check the vm's xml with 'dumpxml --inactive'
## virsh dumpxml rhel --inactive
...
<hostdev mode='subsystem' type='scsi' managed='no'>
<source>
<adapter name='scsi_host2'/>
<address bus='0' target='0' unit='0'/>
</source>
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
</hostdev>
<hostdev mode='subsystem' type='scsi' managed='no'>
<source>
<adapter name='scsi_host3'/>
<address bus='0' target='0' unit='0'/>
</source>
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
</hostdev>
...
a) Looks like libvirt can not verify if user configured the same address for different scsi hostdevs.
Because virDomainHostdevDefPostParse only calls virDomainDriveAddressIsUsedByDisk to check
if address is used by other disks, but no check if used by other hostdevs.
And qemuDomainAttachDeviceConfig calls virDomainHostdevFind to check duplicate devices by
src addr and other stuff, not including addr in vm.
Should that be fixed?
b) If we fixed a), then we can get a devConf that both fits to live and config xml by
passing devLive and domainPersistentDef to virDomainDeviceDefCopy.
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 617d7d5..eca54d0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8615,6 +8615,22 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
goto cleanup;
+ if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
+ flags & VIR_DOMAIN_AFFECT_LIVE) {
+ devLive = virDomainDeviceDefParse(xml, vm->def,
+ caps, driver->xmlopt,
+ parse_flags);
+ if (!devLive)
+ goto cleanup;
+ vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
+ if (!vmdef)
+ goto cleanup;
+ /* Use persistent vm def to get a device def copy
+ */
+ devConf = virDomainDeviceDefCopy(devLive, vmdef, caps, driver->xmlopt);
+ if (!devConf)
+ goto cleanup;
+ }
If devLive fits to vmdef, then we get a compatible devConf, or just fail and return.
Wu Jing
5 years, 3 months
[libvirt] [PATCH v3 00/19] Add vhost-user-gpu support
by marcandre.lureau@redhat.com
From: Marc-André Lureau <marcandre.lureau(a)redhat.com>
Hi,
This series adds support for running virtio GPUs in seperate
processes, thanks to vhost-user backend.
The QEMU support landed for 4.1. There are several benefits of running
the GPU/virgl in an external process, since Mesa is rather heavy on
the qemu main loop, and may block for a while, or crash.
The external GPU process is started with one end of a socket pair, the
other end is given to a QEMU chardev attached to a device. The
external process is also added to the cgroup to limit resources usage.
vhost-user is a generic mechanism that allows implementing virtio device
dataplane handling in a separate userspace process. vhost-user-gpu here
notably moves the virgl 3d handling out of the main qemu process. The
external process will be /usr/libexec/vhost-user-gpu, which comes from
qemu.git contrib/vhost-user-gpu code, first released in qemu-4.1.
Part of this series deals with discovering the location on disk of the
vhost-user-gpu binary, and what capabilities it provides. This uses a
similar mechanism to firmware.json, described in qemu
docs/interop/vhost-user.json
https://github.com/qemu/qemu/blob/master/docs/interop/vhost-user.json
qemu 4.1 ships a 50-qemu-gpu.json to match. I believe virtio-fs
will use a similar mechanism when it lands in upstream qemu, as
virtiofsd is a separate process that communicates with qemu over
vhost-user.
For a bit more background on vhost-user-gpu process handling and
the json interop motivation, here's some of the qemu discussion:
https://lists.nongnu.org/archive/html/qemu-devel/2018-08/msg02610.html
https://lists.nongnu.org/archive/html/qemu-devel/2018-09/msg00807.html
For this series, the XML to enable this is:
<video model='virtio'>
<driver name='vhostuser'/>
<acceleration accel3d='yes' rendernode='/path/to/rendernode'/>
</video>
rendernode is optional
qemu_vhost_user.c handles vhost-user.json
qemu_vhost_user_gpu.c handles the process management for
vhost-user-gpu
v3:
- rename qemu_configs -> qemu_interop_config
- replace <model .. vhostuser='yes'/> with <driver name='vhostuser'/>
- move vhost_user_binary to virDomainVideoDriverDef
- some VIR_AUTO usage improvements
- introduce qemuDomainVideoPrivate to store vhost-user fd
- improved selection of -device model
- use DO_TEST_CAPS_LATEST
- allocate a rendernode with virHostGetDRMRenderNode() - but no clear idea how to have a test
- add a patch to ignore EPERM in virDirOpenIfExists()
- better domain checks/validate
- added Ján r-b
- no s-o-b from Cole, per request and commits taken from his git branch
- rebase, indentation/style fixes, update doc, version..
v2:
- rebase to master
- if test file build by dropping LDADDS usage
- syntax-check issues:
* use #pragma once
* if () bracket issues
* jump label indent issues
* error message %s usage
* size_t for loops
Marc-André Lureau (19):
qemu: generalize qemuFetchConfigs
util: ignore EACCESS in virDirOpenIfExists
conf: format/parse/rng/docs for video <driver name='qemu|vhostuser'/>
domain: add rendernode attribute on <accel>
qemu-cgroup: allow accel rendernode access
qemu: add vhost-user-gpu capabilities checks
qemu: check that qemu is vhost-user-vga capable
qemu: validate virtio-gpu with vhost-user
qemu: restrict 'virgl=' option to non-vhostuser video type
qemu: add vhost-user helpers
qemu: add qemuSecurityStartVhostUserGPU helper
conf: add privateData to virDomainVideoDef
qemu: add qemuDomainVideoPrivate
qemu: add vhost-user-gpu helper unit
qemu: prepare domain for vhost-user GPU
qemu: start/stop the vhost-user-gpu external device
qemu: build vhost-user GPU devices
tests: mock execv/execve
tests: add vhost-user-gpu xml2argv tests
docs/formatdomain.html.in | 18 +-
docs/schemas/domaincommon.rng | 13 +
src/conf/domain_conf.c | 87 +++-
src/conf/domain_conf.h | 21 +-
src/qemu/Makefile.inc.am | 6 +
src/qemu/qemu_capabilities.c | 4 +
src/qemu/qemu_capabilities.h | 2 +
src/qemu/qemu_cgroup.c | 24 +
src/qemu/qemu_command.c | 65 ++-
src/qemu/qemu_domain.c | 50 ++-
src/qemu/qemu_domain.h | 14 +-
src/qemu/qemu_extdevice.c | 73 ++-
src/qemu/qemu_extdevice.h | 5 +
src/qemu/qemu_firmware.c | 144 +-----
src/qemu/qemu_interop_config.c | 183 ++++++++
src/qemu/qemu_interop_config.h | 25 ++
src/qemu/qemu_process.c | 61 ++-
src/qemu/qemu_security.c | 40 ++
src/qemu/qemu_security.h | 6 +
src/qemu/qemu_vhost_user.c | 422 ++++++++++++++++++
src/qemu/qemu_vhost_user.h | 48 ++
src/qemu/qemu_vhost_user_gpu.c | 285 ++++++++++++
src/qemu/qemu_vhost_user_gpu.h | 50 +++
src/util/virfile.c | 13 +-
tests/Makefile.am | 9 +
.../caps_4.1.0.x86_64.xml | 2 +
.../etc/qemu/vhost-user/40-gpu.json | 1 +
.../etc/qemu/vhost-user/50-gpu.json | 0
.../qemu/vhost-user/test-vhost-user-gpu | 11 +
.../usr/share/qemu/vhost-user/30-gpu.json | 1 +
.../usr/share/qemu/vhost-user/50-gpu.json | 8 +
.../usr/share/qemu/vhost-user/60-gpu.json | 1 +
tests/qemuvhostusertest.c | 132 ++++++
...host-user-gpu-secondary.x86_64-latest.args | 43 ++
.../vhost-user-gpu-secondary.xml | 46 ++
.../vhost-user-vga.x86_64-latest.args | 40 ++
tests/qemuxml2argvdata/vhost-user-vga.xml | 42 ++
tests/qemuxml2argvdata/virtio-options.args | 5 +-
tests/qemuxml2argvdata/virtio-options.xml | 4 +-
tests/qemuxml2argvtest.c | 15 +-
tests/virfilewrapper.c | 22 +
41 files changed, 1832 insertions(+), 209 deletions(-)
create mode 100644 src/qemu/qemu_interop_config.c
create mode 100644 src/qemu/qemu_interop_config.h
create mode 100644 src/qemu/qemu_vhost_user.c
create mode 100644 src/qemu/qemu_vhost_user.h
create mode 100644 src/qemu/qemu_vhost_user_gpu.c
create mode 100644 src/qemu/qemu_vhost_user_gpu.h
create mode 120000 tests/qemuvhostuserdata/etc/qemu/vhost-user/40-gpu.json
create mode 100644 tests/qemuvhostuserdata/etc/qemu/vhost-user/50-gpu.json
create mode 100755 tests/qemuvhostuserdata/usr/libexec/qemu/vhost-user/test-vhost-user-gpu
create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/30-gpu.json
create mode 100644 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/50-gpu.json
create mode 120000 tests/qemuvhostuserdata/usr/share/qemu/vhost-user/60-gpu.json
create mode 100644 tests/qemuvhostusertest.c
create mode 100644 tests/qemuxml2argvdata/vhost-user-gpu-secondary.x86_64-latest.args
create mode 100644 tests/qemuxml2argvdata/vhost-user-gpu-secondary.xml
create mode 100644 tests/qemuxml2argvdata/vhost-user-vga.x86_64-latest.args
create mode 100644 tests/qemuxml2argvdata/vhost-user-vga.xml
--
2.23.0
5 years, 3 months