[libvirt] [PATCH] lxc: Don't make container's TTY a controlling TTY
by Richard Weinberger
Userspace does not expect that the initial console
is a controlling TTY. systemd can deal with that, others not.
On sysv init distros getty will fail to spawn a controlling on
/dev/console or /dev/tty1. Which will cause to whole container
to reboot upon ctrl-c.
This patch changes the behavior of libvirt to match the kernel
behavior where the initial TTY is also not controlling.
The only user visible change should be that a container with
bash as PID 1 would complain. But this matches exactly the kernel
be behavior with intit=/bin/bash.
To get a controlling TTY for bash just run "setsid /bin/bash".
Signed-off-by: Richard Weinberger <richard(a)nod.at>
---
src/lxc/lxc_container.c | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 11e9514..7d531e2 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -278,18 +278,6 @@ static int lxcContainerSetupFDs(int *ttyfd,
"as the FDs are about to be closed for exec of "
"the container init process");
- if (setsid() < 0) {
- virReportSystemError(errno, "%s",
- _("setsid failed"));
- goto cleanup;
- }
-
- if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0) {
- virReportSystemError(errno, "%s",
- _("ioctl(TIOCSCTTY) failed"));
- goto cleanup;
- }
-
if (dup2(*ttyfd, STDIN_FILENO) < 0) {
virReportSystemError(errno, "%s",
_("dup2(stdin) failed"));
@@ -2210,7 +2198,7 @@ static int lxcContainerChild(void *data)
VIR_DEBUG("Container TTY path: %s", ttyPath);
- ttyfd = open(ttyPath, O_RDWR|O_NOCTTY);
+ ttyfd = open(ttyPath, O_RDWR);
if (ttyfd < 0) {
virReportSystemError(errno,
_("Failed to open tty %s"),
--
2.4.2
9 years
[libvirt] Assert with libvirt + xen hvm
by CloudPatch Staff
We're hitting an assert whenever we try to create an HVM instance under Xen
via libvirtd.
System is running on Gentoo, package information as follows:
app-emulation/xen-4.5.0 USE="api debug flask hvm pam pygrub python qemu
screen"
app-emulation/xen-tools-4.5.0 USE="api debug flask hvm pam pygrub python
qemu screen"
app-emulation/libvirt-1.2.11-r2:0/1.2.11 USE="caps libvirtd lvm macvtap nls
qemu udev vepa virtualbox xen"
The following commands are run in parallel:
vmmachine ~ # libvirtd --listen
2015-01-22 16:33:13.596+0000: 2620: info : libvirt version: 1.2.11
2015-01-22 16:33:13.596+0000: 2620: error : udevGetDMIData:1607 : Failed to
get udev device for syspath '/sys/devices/virtual/dmi/id' or
'/sys/class/dmi/id'
libvirtd: libxl_fork.c:350: sigchld_installhandler_core: Assertion
`((void)"application must negotiate with libxl about SIGCHLD",
!(sigchld_saved_action.sa_flags & 4) &&
(sigchld_saved_action.__sigaction_handler.sa_handler == ((__sighandler_t)
0) || sigchld_saved_action.__sigaction_handler.sa_handler ==
((__sighandler_t) 1)))' failed.
Aborted
vmmachine ~ # VIRSH_DEBUG=0 virsh create xml
create: file(optdata): xml
libvirt: XML-RPC error : End of file while reading data: Input/output error
error: Failed to create domain from xml
error: End of file while reading data: Input/output error
libvirt: Domain Config error : Requested operation is not valid: A
different callback was requested
9 years
[libvirt] [PATCH] maint: Remove control characters from LGPL license file
by Andrea Bolognani
---
COPYING.LESSER | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/COPYING.LESSER b/COPYING.LESSER
index 4362b49..e5ab03e 100644
--- a/COPYING.LESSER
+++ b/COPYING.LESSER
@@ -55,7 +55,7 @@ modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
-
+
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
@@ -111,7 +111,7 @@ modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
-
+
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@@ -158,7 +158,7 @@ Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
-
+
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
@@ -216,7 +216,7 @@ instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
-
+
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
@@ -267,7 +267,7 @@ Library will still fall under Section 6.)
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
-
+
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
@@ -329,7 +329,7 @@ restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
-
+
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
@@ -370,7 +370,7 @@ subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
-
+
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
@@ -422,7 +422,7 @@ conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
-
+
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
@@ -456,7 +456,7 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
-
+
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
--
2.4.2
9 years, 2 months
[libvirt] [libvirt-test-api][PATCH 1/3] add new test case for getMemoryStats
by Luyao Huang
Signed-off-by: Luyao Huang <lhuang(a)redhat.com>
---
cases/test_connection.conf | 4 ++
repos/virconn/connection_getMemoryStats.py | 96 ++++++++++++++++++++++++++++++
2 files changed, 100 insertions(+)
create mode 100644 repos/virconn/connection_getMemoryStats.py
diff --git a/cases/test_connection.conf b/cases/test_connection.conf
index 3c08a95..336b1ad 100644
--- a/cases/test_connection.conf
+++ b/cases/test_connection.conf
@@ -73,3 +73,7 @@ virconn:connection_getCellsFreeMemory
virconn:connection_getMemoryParameters
conn
qemu:///system
+
+virconn:connection_getMemoryStats
+ conn
+ qemu:///system
diff --git a/repos/virconn/connection_getMemoryStats.py b/repos/virconn/connection_getMemoryStats.py
new file mode 100644
index 0000000..fcc146b
--- /dev/null
+++ b/repos/virconn/connection_getMemoryStats.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+import libvirt
+from libvirt import libvirtError
+from utils import utils
+
+required_params = ()
+optional_params = {'conn': ''}
+
+NODE_ONLINE = '/sys/devices/system/node/online'
+MEMINFO = '/proc/meminfo'
+
+def getsysmem(a):
+ return open(a[0]).read().splitlines()[a[1]].split()[a[2]]
+
+def virtgetmem(a):
+ return a[0].getMemoryStats(a[1])[a[2]]
+
+def connection_getMemoryStats(params):
+ """
+ test API for getMemoryStats in class virConnect
+ """
+ logger = params['logger']
+ fail=0
+
+ nodeset = utils.file_read(NODE_ONLINE)
+ logger.info("host exist node is %s" % nodeset)
+
+ node_tuple = utils.param_to_tuple_nolength(nodeset)
+ if not node_tuple:
+ logger.info("error in function param_to_tuple_nolength")
+ return 1
+
+ try:
+ conn = libvirt.open(params['conn'])
+
+ logger.info("get connection cells memory status")
+ for n in range(len(node_tuple)):
+ if not node_tuple[n]:
+ continue
+
+ D = utils.get_standard_deviation(getsysmem, virtgetmem, \
+ ['/sys/devices/system/node/node%d/meminfo' % n,1,3], [conn,n,'free'])
+ logger.info("Standard Deviation for free memory in node %d is %d" % (n, D))
+
+
+ """ expectations 177 is a average collected in a x86_64 low load machine"""
+ if D > 177*5:
+ fail=1
+ logger.info("FAIL: Standard Deviation is too big \
+ (biger than %d) for node %d free memory" % (177*5, n))
+
+ a1 = ['/sys/devices/system/node/node%d/meminfo' % n, 0, 3]
+ a2 = [conn,n,'total']
+ if long(getsysmem(a1)) != long(virtgetmem(a2)):
+ fail=1
+ logger.info("FAIL: Total memory in node %d is not right" % n)
+
+
+ D = utils.get_standard_deviation(getsysmem, virtgetmem, \
+ [MEMINFO, 3, 1], [conn, -1, 'buffers'])
+ logger.info("Standard Deviation for host buffers is %d" % D)
+
+ """ expectations 30 is a average collected in a x86_64 low load machine"""
+ if D > 30*5:
+ fail=1
+ logger.info("FAIL: Standard Deviation is too big \
+ (biger than %d) for host buffers" % 30*5)
+
+ D = utils.get_standard_deviation(getsysmem, virtgetmem, \
+ [MEMINFO,4,1], [conn,-1,'cached'])
+ logger.info("Standard Deviation for host cached is %d" % D)
+
+ """ expectations 32 is a average collected in a x86_64 low load machine"""
+ if D > 32*5:
+ fail=1
+ logger.info("FAIL: Standard Deviation is too big \
+ (biger than %d) for host cached" % 32*5)
+
+ D = utils.get_standard_deviation(getsysmem, virtgetmem, \
+ [MEMINFO,1,1], [conn,-1,'free'])
+ logger.info("Standard Deviation for host free memory is %d" % D)
+
+ """ expectations 177 is a average collected in a x86_64 low load machine"""
+ if D > 177*5:
+ fail=1
+ logger.info("FAIL: Standard Deviation is too big \
+ (biger than %d) for host free memory" % 177*5)
+
+ if long(getsysmem([MEMINFO,0,1])) != long(virtgetmem([conn,-1,'total'])):
+ fail=1
+ logger.info("FAIL: Total memory for host is not right" % n)
+
+ except libvirtError, e:
+ logger.error("API error message: %s" % e.message)
+ fail=1
+ return fail
--
1.8.3.1
9 years, 3 months
[libvirt] Entering freeze for libvirt-1.2.17
by Daniel Veillard
Following discussions on Friday, I applied the patches to deactivate
the subset of Admin APIs and revert from 1.3.0 to 1.2.17. I then tagged
in git and pushed signed tarballs and rpms to the usual place:
ftp://libvirt.org/pub/libvirt/
I didn't run my usual tests on that one, my infra is in flux,
so even more reasons for people to give it a try :-)
I'm likely to make a candidate release 2 on Tuesday and if all goes
well we can push 1.2.17 on Thursday,
thanks,
Daniel
--
Daniel Veillard | Open Source and Standards, Red Hat
veillard(a)redhat.com | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | virtualization library http://libvirt.org/
9 years, 3 months
[libvirt] [PATCH] bootstrap: Don't require python-config
by Michal Privoznik
We've split the python bindings a long time ago. However,
we are still requiring python-config (as an obfuscation to
python-devel). This does not make any sense. The only thing
we need is python, not python-devel.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
bootstrap.conf | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index c06ee4c..783b3a3 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -196,10 +196,7 @@ local_gl_dir=gnulib/local
# Build prerequisites
# Note that some of these programs are only required for 'make dist' to
# succeed from a fresh git checkout; not all of these programs are
-# required to run 'make dist' on a tarball. As a special case, we want
-# to require the equivalent of the Fedora python-devel package, but
-# RHEL 5 lacks the witness python-config package; we hack around that
-# old environment below.
+# required to run 'make dist' on a tarball.
buildreq="\
autoconf 2.59
automake 1.9.6
@@ -212,19 +209,11 @@ patch -
perl 5.5
perl::XML::XPath -
pkg-config -
-python-config -
rpcgen -
tar -
xmllint -
xsltproc -
"
-# Use rpm as a fallback to bypass the bootstrap probe for python-config,
-# for the sake of RHEL 5; without requiring it on newer systems that
-# have python-config to begin with.
-if `(${PYTHON_CONFIG-python-config} --version;
- test $? -lt 126 || rpm -q python-devel) >/dev/null 2>&1`; then
- PYTHON_CONFIG=true
-fi
# Automake requires that ChangeLog and AUTHORS exist.
touch AUTHORS ChangeLog || exit 1
--
2.3.6
9 years, 3 months
[libvirt] [libvirt-php][PATCH v1] snapshot flags
by Vasiliy Tolstov
* add more snapshot flag constants
* add flags support to snapshot functions
Signed-off-by: Vasiliy Tolstov <v.tolstov(a)selfip.ru>
---
src/libvirt-php.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 49 insertions(+), 12 deletions(-)
diff --git a/src/libvirt-php.c b/src/libvirt-php.c
index d13e5b4..a2949f1 100644
--- a/src/libvirt-php.c
+++ b/src/libvirt-php.c
@@ -1240,6 +1240,31 @@ PHP_MINIT_FUNCTION(libvirt)
/* Domain snapshot constants */
REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_DELETE_CHILDREN", VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_DELETE_METADATA_ONLY", VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_DELETE_CHILDREN_ONLY", VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_REDEFINE", VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_CURRENT", VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_NO_METADATA", VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_HALT", VIR_DOMAIN_SNAPSHOT_CREATE_HALT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_DISK_ONLY", VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_REUSE_EXT", VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_QUIESCE", VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_ATOMIC", VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_LIVE", VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_DESCENDANTS", VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_ROOTS", VIR_DOMAIN_SNAPSHOT_LIST_ROOTS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_METADATA", VIR_DOMAIN_SNAPSHOT_LIST_METADATA, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_LEAVES", VIR_DOMAIN_SNAPSHOT_LIST_LEAVES, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_NO_LEAVES", VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_NO_METADATA", VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_INACTIVE", VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_ACTIVE", VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_DISK_ONLY", VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_INTERNAL", VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_EXTERNAL", VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_REVERT_RUNNING", VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_REVERT_PAUSED", VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_REVERT_FORCE", VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, CONST_CS | CONST_PERSISTENT);
/* Memory constants */
REGISTER_LONG_CONSTANT("VIR_MEMORY_VIRTUAL", 1, CONST_CS | CONST_PERSISTENT);
@@ -6568,6 +6593,7 @@ PHP_FUNCTION(libvirt_domain_get_job_info)
* Since version: 0.4.1(-2)
* Description: Function is used to get the information whether domain has the current snapshot
* Arguments: @res [resource]: libvirt domain resource
+ * @flags [int]: libvirt snapshot flags
* Returns: TRUE is domain has the current snapshot, otherwise FALSE (you may need to check for error using libvirt_get_last_error())
*/
PHP_FUNCTION(libvirt_domain_has_current_snapshot)
@@ -6575,10 +6601,11 @@ PHP_FUNCTION(libvirt_domain_has_current_snapshot)
php_libvirt_domain *domain=NULL;
zval *zdomain;
int retval;
+ long flags = 0;
- GET_DOMAIN_FROM_ARGS("r",&zdomain);
+ GET_DOMAIN_FROM_ARGS("r|l",&zdomain, &flags);
- retval=virDomainHasCurrentSnapshot(domain->domain, 0);
+ retval=virDomainHasCurrentSnapshot(domain->domain, flags);
if (retval <= 0) RETURN_FALSE;
RETURN_TRUE;
}
@@ -6589,6 +6616,7 @@ PHP_FUNCTION(libvirt_domain_has_current_snapshot)
* Description: This functions is used to lookup for the snapshot by it's name
* Arguments: @res [resource]: libvirt domain resource
* @name [string]: name of the snapshot to get the resource
+ * @flags [int]: libvirt snapshot flags
* Returns: domain snapshot resource
*/
PHP_FUNCTION(libvirt_domain_snapshot_lookup_by_name)
@@ -6597,13 +6625,14 @@ PHP_FUNCTION(libvirt_domain_snapshot_lookup_by_name)
zval *zdomain;
int name_len;
char *name=NULL;
+ long flags = 0;
php_libvirt_snapshot *res_snapshot;
virDomainSnapshotPtr snapshot = NULL;
- GET_DOMAIN_FROM_ARGS("rs",&zdomain,&name,&name_len);
+ GET_DOMAIN_FROM_ARGS("rs|l",&zdomain,&name,&name_len,&flags);
if ( (name == NULL) || (name_len<1)) RETURN_FALSE;
- snapshot=virDomainSnapshotLookupByName(domain->domain, name, 0);
+ snapshot=virDomainSnapshotLookupByName(domain->domain, name, flags);
if (snapshot==NULL) RETURN_FALSE;
res_snapshot = (php_libvirt_snapshot *)emalloc(sizeof(php_libvirt_snapshot));
@@ -6620,6 +6649,7 @@ PHP_FUNCTION(libvirt_domain_snapshot_lookup_by_name)
* Since version: 0.4.1(-2)
* Description: This function creates the domain snapshot for the domain identified by it's resource
* Arguments: @res [resource]: libvirt domain resource
+ * @flags [int]: libvirt snapshot flags
* Returns: domain snapshot resource
*/
PHP_FUNCTION(libvirt_domain_snapshot_create)
@@ -6628,10 +6658,11 @@ PHP_FUNCTION(libvirt_domain_snapshot_create)
php_libvirt_snapshot *res_snapshot;
zval *zdomain;
virDomainSnapshotPtr snapshot = NULL;
+ long flags = 0;
- GET_DOMAIN_FROM_ARGS("r",&zdomain);
+ GET_DOMAIN_FROM_ARGS("r|l",&zdomain, &flags);
- snapshot=virDomainSnapshotCreateXML(domain->domain, "<domainsnapshot/>", 0);
+ snapshot=virDomainSnapshotCreateXML(domain->domain, "<domainsnapshot/>", flags);
DPRINTF("%s: virDomainSnapshotCreateXML(%p, <xml>) returned %p\n", PHPFUNC, domain->domain, snapshot);
if (snapshot == NULL) RETURN_FALSE;
@@ -6649,6 +6680,7 @@ PHP_FUNCTION(libvirt_domain_snapshot_create)
* Since version: 0.4.1(-2)
* Description: Function is used to get the XML description of the snapshot identified by it's resource
* Arguments: @res [resource]: libvirt snapshot resource
+ * @flags [int]: libvirt snapshot flags
* Returns: XML description string for the snapshot
*/
PHP_FUNCTION(libvirt_domain_snapshot_get_xml)
@@ -6657,10 +6689,11 @@ PHP_FUNCTION(libvirt_domain_snapshot_get_xml)
char *xml_out;
zval *zsnapshot;
php_libvirt_snapshot *snapshot;
+ long flags = 0;
- GET_SNAPSHOT_FROM_ARGS("r",&zsnapshot);
+ GET_SNAPSHOT_FROM_ARGS("r|l",&zsnapshot, &flags);
- xml = virDomainSnapshotGetXMLDesc(snapshot->snapshot, 0);
+ xml = virDomainSnapshotGetXMLDesc(snapshot->snapshot, flags);
if (xml==NULL) RETURN_FALSE;
RECREATE_STRING_WITH_E(xml_out,xml);
@@ -6673,6 +6706,7 @@ PHP_FUNCTION(libvirt_domain_snapshot_get_xml)
* Since version: 0.4.1(-2)
* Description: Function is used to revert the domain state to the state identified by the snapshot
* Arguments: @res [resource]: libvirt snapshot resource
+ * @flags [int]: libvirt snapshot flags
* Returns: TRUE on success, FALSE on error
*/
PHP_FUNCTION(libvirt_domain_snapshot_revert)
@@ -6680,10 +6714,11 @@ PHP_FUNCTION(libvirt_domain_snapshot_revert)
zval *zsnapshot;
php_libvirt_snapshot *snapshot;
int ret;
+ long flags = 0;
- GET_SNAPSHOT_FROM_ARGS("r",&zsnapshot);
+ GET_SNAPSHOT_FROM_ARGS("r|l",&zsnapshot, &flags);
- ret = virDomainRevertToSnapshot(snapshot->snapshot, 0);
+ ret = virDomainRevertToSnapshot(snapshot->snapshot, flags);
DPRINTF("%s: virDomainRevertToSnapshot(%p, 0) returned %d\n", PHPFUNC, snapshot->snapshot, ret);
if (ret == -1) RETURN_FALSE;
RETURN_TRUE;
@@ -6717,6 +6752,7 @@ PHP_FUNCTION(libvirt_domain_snapshot_delete)
* Since version: 0.4.1(-2)
* Description: Function is used to list domain snapshots for the domain specified by it's resource
* Arguments: @res [resource]: libvirt domain resource
+ * @flags [int]: libvirt snapshot flags
* Returns: libvirt domain snapshot names array
*/
PHP_FUNCTION(libvirt_list_domain_snapshots)
@@ -6726,11 +6762,12 @@ PHP_FUNCTION(libvirt_list_domain_snapshots)
int count=-1;
int expectedcount=-1;
char **names;
+ long flags = 0;
int i;
- GET_DOMAIN_FROM_ARGS("r",&zdomain);
+ GET_DOMAIN_FROM_ARGS("r|l",&zdomain, &flags);
- expectedcount=virDomainSnapshotNum(domain->domain, 0);
+ expectedcount=virDomainSnapshotNum(domain->domain, flags);
DPRINTF("%s: virDomainSnapshotNum(%p, 0) returned %d\n", PHPFUNC, domain->domain, expectedcount);
if (expectedcount != -1 ) {
--
2.3.3
9 years, 3 months
[libvirt] [PATCH 00/13] Move generic virsh data to a separate module vsh
by Erik Skultety
The idea behind this is that in order to introduce virt-admin client (and later
some commands/APIs), there are lots of methods in virsh that can be easily
reused by other potential clients like command and command argument passing or
error reporting.
!!! IMPORTANT !!!
These patches cannot be compiled separately, the series is split more or
less logically into chunks only to be more readable by the reviewer.
I started this at least 4 times from scratch and still haven't found a way that
splitting virsh could be done with several independent applicable commits, rather
than having one massive commit in the end.
Erik Skultety (13):
tools: Introduce new client generic module vsh
vsh: Remove client specific data, only generic data are kept
tools: apply s/vshX/virshX to all virsh specific data
virsh: remove generic data, only client specific are kept
virsh: Rename client specific methods in virsh.h
vsh: vshControl now includes client private data and client specific
progname
vsh: Make use of introduced private data
vsh: Introduce client hooks
vsh: Make use of newly introduced client side hooks
vsh: Introduce new global initializer
vsh: Make separated generic methods public
virsh: Introduce connection handler
tools: Update makefile to include 'vsh' sources as well
cfg.mk | 2 +-
po/POTFILES.in | 3 +-
tools/Makefile.am | 4 +
tools/virsh-console.c | 13 +-
tools/virsh-console.h | 8 +-
tools/virsh-domain-monitor.c | 201 ++--
tools/virsh-domain-monitor.h | 4 +-
tools/virsh-domain.c | 532 +++++----
tools/virsh-domain.h | 14 +-
tools/virsh-edit.c | 8 +-
tools/virsh-host.c | 131 ++-
tools/virsh-interface.c | 80 +-
tools/virsh-interface.h | 12 +-
tools/virsh-network.c | 72 +-
tools/virsh-network.h | 10 +-
tools/virsh-nodedev.c | 37 +-
tools/virsh-nwfilter.c | 33 +-
tools/virsh-nwfilter.h | 10 +-
tools/virsh-pool.c | 104 +-
tools/virsh-pool.h | 10 +-
tools/virsh-secret.c | 27 +-
tools/virsh-snapshot.c | 75 +-
tools/virsh-volume.c | 103 +-
tools/virsh-volume.h | 14 +-
tools/virsh.c | 2673 ++++--------------------------------------
tools/virsh.h | 481 +-------
tools/vsh.c | 2332 ++++++++++++++++++++++++++++++++++++
tools/vsh.h | 489 ++++++++
28 files changed, 3906 insertions(+), 3576 deletions(-)
create mode 100644 tools/vsh.c
create mode 100644 tools/vsh.h
--
1.9.3
9 years, 3 months
[libvirt] [PATCH] lxc: Add option to inherit namespace from a name container or a pid or a netns
by ik.nitk
lxc / docker containers gives option to inherit the
namespaces. Example lxc-start has option [ --share-[net|ipc|uts] name|pid ]
where --share-net name|pid means Inherit a network namespace from a
name container or a pid.
This patch tries to add the similar option to libvirt lxc. So to inherit namespace from name
container c2.
add this into xml.
<lxc:namespace>
<sharenet type='name' value='c2'/>
</lxc:namespace>
And to inherit namespace from a pid.
add this into xml.
<lxc:namespace>
<sharenet type='pid' value='10245'/>
</lxc:namespace>
And to inherit namespace from a netns.
add this into xml.
<lxc:namespace>
<sharenet type='netns' value='red'/>
</lxc:namespace>
Similar options for ipc/uts.
<shareipc /> , <shareuts />
The reasong lxc xml namespace is added because this feature is very specific to lxc. Therfore wanted to
keep it seperated from actual libvirt xml domain.
So the final vrish xml file would look like
<domain type='lxc' xmlns:lxc='http://libvirt.org/schemas/domain/lxc/1.0'>
<name>cn-03</name>
<memory>327680</memory>
<os>
<type>exe</type>
<init>/sbin/init</init>
</os>
<lxc:namespace>
<sharenet type='netns' value='red'/>
</lxc:namespace>
<vcpu>1</vcpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/lib/libvirt/libvirt_lxc</emulator>
<filesystem type='mount'>
<source dir='/var/lib/lxc/u1/rootfs'/>
<target dir='/'/>
</filesystem>
<console type='pty'/>
</devices>
</domain>
-imran
---
src/Makefile.am | 5 +-
src/lxc/lxc_conf.c | 2 +-
src/lxc/lxc_conf.h | 23 +++++
src/lxc/lxc_container.c | 191 ++++++++++++++++++++++++++++++++++--
src/lxc/lxc_domain.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++-
src/lxc/lxc_domain.h | 1 +
6 files changed, 463 insertions(+), 13 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 579421d..1a78fde 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1293,7 +1293,8 @@ libvirt_driver_lxc_impl_la_CFLAGS = \
-I$(srcdir)/access \
-I$(srcdir)/conf \
$(AM_CFLAGS)
-libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS) $(FUSE_LIBS)
+libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS) $(LIBXML_LIBS) $(FUSE_LIBS)
+libvirt_driver_lxc_impl_la_LDFLAGS = libvirt-lxc.la
if WITH_BLKID
libvirt_driver_lxc_impl_la_CFLAGS += $(BLKID_CFLAGS)
libvirt_driver_lxc_impl_la_LIBADD += $(BLKID_LIBS)
@@ -2652,6 +2653,8 @@ libvirt_lxc_LDADD = \
libvirt-net-rpc.la \
libvirt_security_manager.la \
libvirt_conf.la \
+ libvirt.la \
+ libvirt-lxc.la \
libvirt_util.la \
../gnulib/lib/libgnu.la
if WITH_DTRACE_PROBES
diff --git a/src/lxc/lxc_conf.c b/src/lxc/lxc_conf.c
index c393cb5..96a0f47 100644
--- a/src/lxc/lxc_conf.c
+++ b/src/lxc/lxc_conf.c
@@ -213,7 +213,7 @@ lxcDomainXMLConfInit(void)
{
return virDomainXMLOptionNew(&virLXCDriverDomainDefParserConfig,
&virLXCDriverPrivateDataCallbacks,
- NULL);
+ &virLXCDriverDomainXMLNamespace);
}
diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
index 8340b1f..59002e5 100644
--- a/src/lxc/lxc_conf.h
+++ b/src/lxc/lxc_conf.h
@@ -67,6 +67,29 @@ struct _virLXCDriverConfig {
bool securityRequireConfined;
};
+
+typedef enum {
+ VIR_DOMAIN_NAMESPACE_SHARENET = 0,
+ VIR_DOMAIN_NAMESPACE_SHAREIPC,
+ VIR_DOMAIN_NAMESPACE_SHAREUTS,
+ VIR_DOMAIN_NAMESPACE_LAST,
+} virDomainNamespace;
+
+struct ns_info {
+ const char *proc_name;
+ int clone_flag;
+};
+
+extern const struct ns_info ns_info[VIR_DOMAIN_NAMESPACE_LAST];
+
+typedef struct _lxcDomainDef lxcDomainDef;
+typedef lxcDomainDef *lxcDomainDefPtr;
+struct _lxcDomainDef {
+ int ns_inherit_fd[VIR_DOMAIN_NAMESPACE_LAST];
+ char *ns_type[VIR_DOMAIN_NAMESPACE_LAST];
+ char *ns_val[VIR_DOMAIN_NAMESPACE_LAST];
+};
+
struct _virLXCDriver {
virMutex lock;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 9a9ae5c..a9a7ba0 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -25,8 +25,8 @@
*/
#include <config.h>
-
#include <fcntl.h>
+#include <sched.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
@@ -38,7 +38,6 @@
#include <mntent.h>
#include <sys/reboot.h>
#include <linux/reboot.h>
-
/* Yes, we want linux private one, for _syscall2() macro */
#include <linux/unistd.h>
@@ -99,6 +98,50 @@ VIR_LOG_INIT("lxc.lxc_container");
typedef char lxc_message_t;
#define LXC_CONTINUE_MSG 'c'
+#ifdef __linux__
+/*
+ * Workaround older glibc. While kernel may support the setns
+ * syscall, the glibc wrapper might not exist. If that's the
+ * case, use our own.
+ */
+# ifndef __NR_setns
+# if defined(__x86_64__)
+# define __NR_setns 308
+# elif defined(__i386__)
+# define __NR_setns 346
+# elif defined(__arm__)
+# define __NR_setns 375
+# elif defined(__aarch64__)
+# define __NR_setns 375
+# elif defined(__powerpc__)
+# define __NR_setns 350
+# elif defined(__s390__)
+# define __NR_setns 339
+# endif
+# endif
+
+# ifndef HAVE_SETNS
+# if defined(__NR_setns)
+# include <sys/syscall.h>
+
+static inline int setns(int fd, int nstype)
+{
+ return syscall(__NR_setns, fd, nstype);
+}
+# else /* !__NR_setns */
+# error Please determine the syscall number for setns on your architecture
+# endif
+# endif
+#else /* !__linux__ */
+static inline int setns(int fd ATTRIBUTE_UNUSED, int nstype ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("Namespaces are not supported on this platform."));
+ return -1;
+}
+#endif
+
+
typedef struct __lxc_child_argv lxc_child_argv_t;
struct __lxc_child_argv {
virDomainDefPtr config;
@@ -2233,7 +2276,6 @@ static int lxcContainerChild(void *data)
vmDef->os.init);
goto cleanup;
}
-
/* rename and enable interfaces */
if (lxcContainerRenameAndEnableInterfaces(vmDef,
argv->nveths,
@@ -2321,6 +2363,99 @@ virArch lxcContainerGetAlt32bitArch(virArch arch)
return VIR_ARCH_NONE;
}
+/* Used only for containers,same as the one defined in
+ * domain_conf.c. But used locally
+ */
+static const struct ns_info ns_info_local[VIR_DOMAIN_NAMESPACE_LAST] = {
+ [VIR_DOMAIN_NAMESPACE_SHARENET] = {"net", CLONE_NEWNET},
+ [VIR_DOMAIN_NAMESPACE_SHAREIPC] = {"ipc", CLONE_NEWIPC},
+ [VIR_DOMAIN_NAMESPACE_SHAREUTS] = {"uts", CLONE_NEWUTS}
+};
+
+
+static void close_ns(int ns_fd[VIR_DOMAIN_NAMESPACE_LAST])
+{
+ int i;
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+ if (ns_fd[i] > -1) {
+ if (VIR_CLOSE(ns_fd[i]) < 0)
+ virReportSystemError(errno, "%s", _("failed to close file"));
+ ns_fd[i] = -1;
+ }
+ }
+}
+
+
+/**
+ * lxcPreserve_ns:
+ * @ns_fd: array to store current namespace
+ * @clone_flags: namespaces that need to be preserved
+ */
+static int lxcPreserve_ns(int ns_fd[VIR_DOMAIN_NAMESPACE_LAST], int clone_flags)
+{
+ int i, saved_errno;
+ char *path = NULL;
+
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
+ ns_fd[i] = -1;
+
+ if (access("/proc/self/ns", X_OK)) {
+ virReportSystemError(errno, "%s",
+ _("Kernel does not support attach; preserve_ns ignored"));
+ return 0;
+ }
+
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+ if ((clone_flags & ns_info_local[i].clone_flag) == 0)
+ continue;
+ if (virAsprintf(&path, "/proc/self/ns/%s",
+ ns_info_local[i].proc_name) < 0)
+ goto error;
+ ns_fd[i] = open(path, O_RDONLY | O_CLOEXEC);
+ if (ns_fd[i] < 0)
+ goto error;
+ }
+ VIR_FREE(path);
+ return 0;
+ error:
+ saved_errno = errno;
+ close_ns(ns_fd);
+ errno = saved_errno;
+ VIR_FREE(path);
+ virReportSystemError(errno, _("failed to open '%s'"), path);
+ return -1;
+}
+
+/**
+ * lxcAttach_ns:
+ * @ns_fd: array of namespaces to attach
+ */
+static int lxcAttach_ns(const int ns_fd[VIR_DOMAIN_NAMESPACE_LAST])
+{
+ int i;
+
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+ if (ns_fd[i] < 0)
+ continue;
+ VIR_DEBUG("Setting into namespace\n");
+
+ /* We get EINVAL if new NS is same as the current
+ * NS, or if the fd namespace doesn't match the
+ * type passed to setns()'s second param. Since we
+ * pass 0, we know the EINVAL is harmless
+ */
+ if (setns(ns_fd[i], 0) < 0 &&
+ errno != EINVAL)
+ goto error;
+ }
+ return 0;
+
+ error:
+ virReportSystemError(errno, _("failed to set namespace '%s'")
+ , ns_info_local[i].proc_name);
+ return -1;
+}
+
/**
* lxcContainerStart:
@@ -2346,9 +2481,12 @@ int lxcContainerStart(virDomainDefPtr def,
char **ttyPaths)
{
pid_t pid;
- int cflags;
+ int cflags, i;
int stacksize = getpagesize() * 4;
char *stack, *stacktop;
+ int saved_ns_fd[VIR_DOMAIN_NAMESPACE_LAST];
+ int preserve_mask = 0;
+ lxcDomainDefPtr lxcDef;
lxc_child_argv_t args = {
.config = def,
.securityDriver = securityDriver,
@@ -2368,7 +2506,14 @@ int lxcContainerStart(virDomainDefPtr def,
stacktop = stack + stacksize;
- cflags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|SIGCHLD;
+ lxcDef = def->namespaceData;
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
+ if (lxcDef && lxcDef->ns_inherit_fd[i] != -1)
+ preserve_mask |= ns_info_local[i].clone_flag;
+
+
+
+ cflags = CLONE_NEWPID|CLONE_NEWNS|SIGCHLD;
if (userns_required(def)) {
if (userns_supported()) {
@@ -2381,10 +2526,36 @@ int lxcContainerStart(virDomainDefPtr def,
return -1;
}
}
+ if (!lxcDef || (lxcDef && lxcDef->ns_inherit_fd[VIR_DOMAIN_NAMESPACE_SHARENET] == -1)) {
+ if (lxcNeedNetworkNamespace(def)) {
+ VIR_DEBUG("Enable network namespaces");
+ cflags |= CLONE_NEWNET;
+ }
+ } else {
+ VIR_DEBUG("Inheriting a net namespace");
+ }
- if (lxcNeedNetworkNamespace(def)) {
- VIR_DEBUG("Enable network namespaces");
- cflags |= CLONE_NEWNET;
+ if (!lxcDef || (lxcDef && lxcDef->ns_inherit_fd[VIR_DOMAIN_NAMESPACE_SHAREIPC] == -1)) {
+ cflags |= CLONE_NEWIPC;
+ } else {
+ VIR_DEBUG("Inheriting an IPC namespace");
+ }
+
+ if (!lxcDef || (lxcDef && lxcDef->ns_inherit_fd[VIR_DOMAIN_NAMESPACE_SHAREUTS] == -1)) {
+ cflags |= CLONE_NEWUTS;
+ } else {
+ VIR_DEBUG("Inheriting a UTS namespace");
+ }
+
+ if (lxcDef && lxcPreserve_ns(saved_ns_fd, preserve_mask) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to preserve the namespace"));
+ return -1;
+ }
+ if (lxcDef && lxcAttach_ns(lxcDef->ns_inherit_fd) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to attach the namespace"));
+ return -1;
}
VIR_DEBUG("Cloning container init process");
@@ -2397,6 +2568,10 @@ int lxcContainerStart(virDomainDefPtr def,
_("Failed to run clone container"));
return -1;
}
+ if (lxcDef && lxcAttach_ns(saved_ns_fd)) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to restore saved namespaces"));
+ }
return pid;
}
diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c
index c2180cb..6e4a19a 100644
--- a/src/lxc/lxc_domain.c
+++ b/src/lxc/lxc_domain.c
@@ -20,14 +20,18 @@
*/
#include <config.h>
-
#include "lxc_domain.h"
-
#include "viralloc.h"
#include "virlog.h"
#include "virerror.h"
+#include <fcntl.h>
+#include <libxml/xpathInternals.h>
+#include "virstring.h"
+#include "virutil.h"
+#include "virfile.h"
#define VIR_FROM_THIS VIR_FROM_LXC
+#define LXC_NAMESPACE_HREF "http://libvirt.org/schemas/domain/lxc/1.0"
VIR_LOG_INIT("lxc.lxc_domain");
@@ -41,6 +45,251 @@ static void *virLXCDomainObjPrivateAlloc(void)
return priv;
}
+
+static int open_ns(const char *nnsname_pid, const char *ns_proc_name)
+{
+ int fd = -1;
+ virDomainPtr dom = NULL;
+ virConnectPtr conn = NULL;
+ pid_t pid;
+ int nfdlist;
+ int *fdlist;
+ char *path = NULL;
+ char *eptr;
+ pid = strtol(nnsname_pid, &eptr, 10);
+ if (*eptr != '\0' || pid < 1) {
+ /* check if the domain is running, then set the namespaces
+ * to that container
+ */
+ size_t i = 0;
+ const char *ns[] = { "user", "ipc", "uts", "net", "pid", "mnt" };
+ conn = virConnectOpen("lxc:///");
+ if (!conn)
+ goto cleanup;
+ dom = virDomainLookupByName(conn, nnsname_pid);
+ if (!dom)
+ goto cleanup;
+ if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0)
+ goto cleanup;
+ /* Internally above function calls virProcessGetNamespaces
+ * function which opens ns
+ * in the order { "user", "ipc", "uts", "net", "pid", "mnt" }
+ */
+ for (i = 0; i < ARRAY_CARDINALITY(ns); i++) {
+ if (STREQ(ns[i], ns_proc_name)) {
+ fd = fdlist[i];
+ break;
+ }
+ }
+ if (nfdlist > 0)
+ VIR_FREE(fdlist);
+ } else {
+ if (virAsprintf(&path, "/proc/%d/ns/%s", pid, ns_proc_name) < 0)
+ goto cleanup;
+ fd = open(path, O_RDONLY);
+ }
+cleanup:
+ if (dom)
+ virDomainFree(dom);
+ VIR_FREE(path);
+ (fd < 0)? VIR_ERROR(
+ _("failed to open ns %s"), nnsname_pid):
+ VIR_DEBUG("OPENED NAMESPACE : fd %d\n", fd);
+ return fd;
+}
+
+
+/* Used only for containers */
+const struct ns_info ns_info[VIR_DOMAIN_NAMESPACE_LAST] = {
+ [VIR_DOMAIN_NAMESPACE_SHARENET] = {"net", CLONE_NEWNET},
+ [VIR_DOMAIN_NAMESPACE_SHAREIPC] = {"ipc", CLONE_NEWIPC},
+ [VIR_DOMAIN_NAMESPACE_SHAREUTS] = {"uts", CLONE_NEWUTS}
+};
+
+VIR_ENUM_DECL(virDomainNamespace)
+VIR_ENUM_IMPL(virDomainNamespace, VIR_DOMAIN_NAMESPACE_LAST,
+ N_("sharenet"),
+ N_("shareipc"),
+ N_("shareuts"))
+
+static void
+lxcDomainDefNamespaceFree(void *nsdata)
+{
+ int j;
+ lxcDomainDefPtr lxcDef = nsdata;
+ for (j = 0; j < VIR_DOMAIN_NAMESPACE_LAST; j++) {
+ if (lxcDef->ns_inherit_fd[j] > 0) {
+ VIR_FREE(lxcDef->ns_type);
+ VIR_FREE(lxcDef->ns_val);
+#if 0
+ if (VIR_CLOSE(lxcDef->ns_inherit_fd[j]) < 0)
+ virReportSystemError(errno, "%s", _("failed to close file"));
+#endif
+ }
+ }
+ VIR_FREE(nsdata);
+}
+
+static int
+lxcDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
+ xmlNodePtr root ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt,
+ void **data)
+{
+ lxcDomainDefPtr lxcDef = NULL;
+ xmlNodePtr *nodes = NULL;
+ bool uses_lxc_ns = false;
+ xmlNodePtr node;
+ int feature;
+ int n;
+ char *tmp = NULL;
+ size_t i;
+ pid_t fd = -1;
+
+ if (xmlXPathRegisterNs(ctxt, BAD_CAST "lxc", BAD_CAST LXC_NAMESPACE_HREF) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to register xml namespace '%s'"),
+ LXC_NAMESPACE_HREF);
+ return -1;
+ }
+
+ if (VIR_ALLOC(lxcDef) < 0)
+ return -1;
+
+ /* Init ns_herit_fd for namespaces */
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+ lxcDef->ns_inherit_fd[i] = -1;
+ lxcDef->ns_type[i] = NULL;
+ lxcDef->ns_val[i] = NULL;
+ }
+
+ node = ctxt->node;
+ if ((n = virXPathNodeSet("./lxc:namespace/*", ctxt, &nodes)) < 0)
+ goto error;
+ uses_lxc_ns |= n > 0;
+
+ for (i = 0; i < n; i++) {
+ feature =
+ virDomainNamespaceTypeFromString((const char *) nodes[i]->name);
+ if (feature < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported Namespace feature: %s"),
+ nodes[i]->name);
+ goto error;
+ }
+
+ ctxt->node = nodes[i];
+
+ switch ((virDomainNamespace) feature) {
+ case VIR_DOMAIN_NAMESPACE_SHARENET:
+ case VIR_DOMAIN_NAMESPACE_SHAREIPC:
+ case VIR_DOMAIN_NAMESPACE_SHAREUTS:
+ {
+ tmp = virXMLPropString(nodes[i], "type");
+ if (tmp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("No lxc environment type specified"));
+ goto error;
+ }
+ /* save the tmp so that its needed while writing to xml */
+ lxcDef->ns_type[feature] = tmp;
+ tmp = virXMLPropString(nodes[i], "value");
+ if (tmp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("No lxc environment type specified"));
+ goto error;
+ }
+ lxcDef->ns_val[feature] = tmp;
+ /*netns option is only for VIR_DOMAIN_NAMESPACE_SHARENET*/
+ if (STREQ("netns", lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHARENET])) {
+ char *path = NULL;
+ if (virAsprintf(&path, "/var/run/netns/%s", tmp) < 0)
+ goto error;
+ fd = open(path, O_RDONLY);
+ VIR_FREE(path);
+ } else {
+ fd = open_ns(tmp, ns_info[feature].proc_name);
+ if (fd < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unable to open %s namespace for "
+ "namespace feature '%s'"), tmp,
+ nodes[i]->name);
+ goto error;
+ }
+ }
+ lxcDef->ns_inherit_fd[feature] = fd;
+ }
+ break;
+ case VIR_DOMAIN_NAMESPACE_LAST:
+ break;
+ }
+ }
+ VIR_FREE(nodes);
+ ctxt->node = node;
+ if (uses_lxc_ns)
+ *data = lxcDef;
+ else
+ VIR_FREE(lxcDef);
+ return 0;
+ error:
+ VIR_FREE(nodes);
+ lxcDomainDefNamespaceFree(lxcDef);
+ return -1;
+}
+
+
+static int
+lxcDomainDefNamespaceFormatXML(virBufferPtr buf,
+ void *nsdata)
+{
+ lxcDomainDefPtr lxcDef = nsdata;
+ size_t j;
+
+ if (!lxcDef)
+ return 0;
+
+ virBufferAddLit(buf, "<lxc:namespace>\n");
+ virBufferAdjustIndent(buf, 2);
+
+ for (j = 0; j < VIR_DOMAIN_NAMESPACE_LAST; j++) {
+ switch ((virDomainNamespace) j) {
+ case VIR_DOMAIN_NAMESPACE_SHAREIPC:
+ case VIR_DOMAIN_NAMESPACE_SHAREUTS:
+ case VIR_DOMAIN_NAMESPACE_SHARENET:
+ {
+ if (lxcDef->ns_inherit_fd[j] > 0) {
+ virBufferAsprintf(buf, "<%s type='%s' value='%s'/>\n",
+ virDomainNamespaceTypeToString(j),
+ lxcDef->ns_type[j],
+ lxcDef->ns_val[j]);
+ }
+ }
+ break;
+ case VIR_DOMAIN_NAMESPACE_LAST:
+ break;
+ }
+ }
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</lxc:namespace>\n");
+ return 0;
+}
+
+static const char *
+lxcDomainDefNamespaceHref(void)
+{
+ return "xmlns:lxc='" LXC_NAMESPACE_HREF "'";
+}
+
+
+virDomainXMLNamespace virLXCDriverDomainXMLNamespace = {
+ .parse = lxcDomainDefNamespaceParse,
+ .free = lxcDomainDefNamespaceFree,
+ .format = lxcDomainDefNamespaceFormatXML,
+ .href = lxcDomainDefNamespaceHref,
+};
+
+
static void virLXCDomainObjPrivateFree(void *data)
{
virLXCDomainObjPrivatePtr priv = data;
@@ -73,7 +322,6 @@ static int virLXCDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
} else {
priv->initpid = thepid;
}
-
return 0;
}
diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h
index 751aece..25df999 100644
--- a/src/lxc/lxc_domain.h
+++ b/src/lxc/lxc_domain.h
@@ -41,6 +41,7 @@ struct _virLXCDomainObjPrivate {
virCgroupPtr cgroup;
};
+extern virDomainXMLNamespace virLXCDriverDomainXMLNamespace;
extern virDomainXMLPrivateDataCallbacks virLXCDriverPrivateDataCallbacks;
extern virDomainDefParserConfig virLXCDriverDomainDefParserConfig;
--
1.9.1
9 years, 3 months
[libvirt] [PATCH] rpc: RH1026137: Fix slow volume download (virsh vol-download)
by Ossi Herrala
Use I/O vector (iovec) instead of one huge memory buffer as suggested
in https://bugzilla.redhat.com/show_bug.cgi?id=1026137#c7. This avoids
doing memmove() to big buffers and performance doesn't degrade if
source (virNetClientStreamQueuePacket()) is faster than sink
(virNetClientStreamRecvPacket()).
---
src/rpc/virnetclientstream.c | 134 +++++++++++++++++++++++++----------------
1 files changed, 82 insertions(+), 52 deletions(-)
diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index b428f4b..18c6e8b 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -49,9 +49,9 @@ struct _virNetClientStream {
* time by stopping consuming any incoming data
* off the socket....
*/
- char *incoming;
- size_t incomingOffset;
- size_t incomingLength;
+ struct iovec *incomingVec; /* I/O Vector to hold data */
+ size_t writeVec; /* Vectors produced */
+ size_t readVec; /* Vectors consumed */
bool incomingEOF;
virNetClientStreamEventCallback cb;
@@ -86,9 +86,9 @@ virNetClientStreamEventTimerUpdate(virNetClientStreamPtr st)
if (!st->cb)
return;
- VIR_DEBUG("Check timer offset=%zu %d", st->incomingOffset, st->cbEvents);
+ VIR_DEBUG("Check timer readVec %zu writeVec %zu %d", st->readVec, st->writeVec, st->cbEvents);
- if (((st->incomingOffset || st->incomingEOF) &&
+ if ((((st->readVec < st->writeVec) || st->incomingEOF) &&
(st->cbEvents & VIR_STREAM_EVENT_READABLE)) ||
(st->cbEvents & VIR_STREAM_EVENT_WRITABLE)) {
VIR_DEBUG("Enabling event timer");
@@ -110,13 +110,14 @@ virNetClientStreamEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque)
if (st->cb &&
(st->cbEvents & VIR_STREAM_EVENT_READABLE) &&
- (st->incomingOffset || st->incomingEOF))
+ ((st->readVec < st->writeVec) || st->incomingEOF))
events |= VIR_STREAM_EVENT_READABLE;
if (st->cb &&
(st->cbEvents & VIR_STREAM_EVENT_WRITABLE))
events |= VIR_STREAM_EVENT_WRITABLE;
- VIR_DEBUG("Got Timer dispatch %d %d offset=%zu", events, st->cbEvents, st->incomingOffset);
+ VIR_DEBUG("Got Timer dispatch %d %d readVec %zu writeVec %zu", events, st->cbEvents,
+ st->readVec, st->writeVec);
if (events) {
virNetClientStreamEventCallback cb = st->cb;
void *cbOpaque = st->cbOpaque;
@@ -161,7 +162,7 @@ void virNetClientStreamDispose(void *obj)
virNetClientStreamPtr st = obj;
virResetError(&st->err);
- VIR_FREE(st->incoming);
+ VIR_FREE(st->incomingVec);
virObjectUnref(st->prog);
}
@@ -265,38 +266,49 @@ int virNetClientStreamQueuePacket(virNetClientStreamPtr st,
virNetMessagePtr msg)
{
int ret = -1;
- size_t need;
+ struct iovec iov;
+ char *base;
+ size_t piece, pieces, length, offset = 0, size = 1024*1024;
virObjectLock(st);
- need = msg->bufferLength - msg->bufferOffset;
- if (need) {
- size_t avail = st->incomingLength - st->incomingOffset;
- if (need > avail) {
- size_t extra = need - avail;
- if (VIR_REALLOC_N(st->incoming,
- st->incomingLength + extra) < 0) {
- VIR_DEBUG("Out of memory handling stream data");
- goto cleanup;
- }
- st->incomingLength += extra;
- }
- memcpy(st->incoming + st->incomingOffset,
- msg->buffer + msg->bufferOffset,
- msg->bufferLength - msg->bufferOffset);
- st->incomingOffset += (msg->bufferLength - msg->bufferOffset);
- } else {
+ length = msg->bufferLength - msg->bufferOffset;
+
+ if (length == 0) {
st->incomingEOF = true;
+ goto end;
}
- VIR_DEBUG("Stream incoming data offset %zu length %zu EOF %d",
- st->incomingOffset, st->incomingLength,
- st->incomingEOF);
+ pieces = (length + size - 1) / size;
+ for (piece = 0; piece < pieces; piece++) {
+ if (size > length - offset)
+ size = length - offset;
+
+ if (VIR_ALLOC_N(base, size)) {
+ VIR_DEBUG("Allocation failed");
+ goto cleanup;
+ }
+
+ memcpy(base, msg->buffer + msg->bufferOffset + offset, size);
+ iov.iov_base = base;
+ iov.iov_len = size;
+ offset += size;
+
+ if (VIR_APPEND_ELEMENT(st->incomingVec, st->writeVec, iov) < 0) {
+ VIR_DEBUG("Append failed");
+ VIR_FREE(base);
+ goto cleanup;
+ }
+ VIR_DEBUG("Wrote piece of vector. readVec %zu, writeVec %zu size %zu", st->readVec, st->writeVec, size);
+ }
+
+ end:
virNetClientStreamEventTimerUpdate(st);
-
ret = 0;
cleanup:
+ VIR_DEBUG("Stream incoming data readVec %zu writeVec %zu EOF %d",
+ st->readVec, st->writeVec, st->incomingEOF);
virObjectUnlock(st);
return ret;
}
@@ -361,17 +373,21 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
size_t nbytes,
bool nonblock)
{
- int rv = -1;
+ int ret = -1;
+ size_t partial, offset;
+
+ virObjectLock(st);
+
VIR_DEBUG("st=%p client=%p data=%p nbytes=%zu nonblock=%d",
st, client, data, nbytes, nonblock);
- virObjectLock(st);
- if (!st->incomingOffset && !st->incomingEOF) {
+
+ if ((st->readVec >= st->writeVec) && !st->incomingEOF) {
virNetMessagePtr msg;
- int ret;
+ int rv;
if (nonblock) {
VIR_DEBUG("Non-blocking mode and no data available");
- rv = -2;
+ ret = -2;
goto cleanup;
}
@@ -387,37 +403,51 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
VIR_DEBUG("Dummy packet to wait for stream data");
virObjectUnlock(st);
- ret = virNetClientSendWithReplyStream(client, msg, st);
+ rv = virNetClientSendWithReplyStream(client, msg, st);
virObjectLock(st);
virNetMessageFree(msg);
- if (ret < 0)
+ if (rv < 0)
goto cleanup;
}
- VIR_DEBUG("After IO %zu", st->incomingOffset);
- if (st->incomingOffset) {
- int want = st->incomingOffset;
- if (want > nbytes)
- want = nbytes;
- memcpy(data, st->incoming, want);
- if (want < st->incomingOffset) {
- memmove(st->incoming, st->incoming + want, st->incomingOffset - want);
- st->incomingOffset -= want;
+ offset = 0;
+ partial = nbytes;
+
+ while (st->incomingVec && (st->readVec < st->writeVec)) {
+ struct iovec *iov = st->incomingVec + st->readVec;
+
+ if (!iov || !iov->iov_base) {
+ VIR_DEBUG("NULL pointer");
+ goto cleanup;
+ }
+
+ if (partial < iov->iov_len) {
+ memcpy(data+offset, iov->iov_base, partial);
+ memmove(iov->iov_base, (char*)iov->iov_base+partial, iov->iov_len-partial);
+ iov->iov_len -= partial;
+ offset += partial;
+ VIR_DEBUG("Consumed %zu, left %zu", partial, iov->iov_len);
+ break;
} else {
- VIR_FREE(st->incoming);
- st->incomingOffset = st->incomingLength = 0;
+ memcpy(data+offset, iov->iov_base, iov->iov_len);
+ VIR_DEBUG("Consumed %zu. Moving to next piece", iov->iov_len);
+ partial -= iov->iov_len;
+ offset += iov->iov_len;
+ VIR_FREE(iov->iov_base);
+ iov->iov_len = 0;
+ st->readVec++;
}
- rv = want;
- } else {
- rv = 0;
+
+ VIR_DEBUG("Read piece of vector. read %zu readVec %zu, writeVec %zu", offset, st->readVec, st->writeVec);
}
+ ret = offset;
virNetClientStreamEventTimerUpdate(st);
cleanup:
virObjectUnlock(st);
- return rv;
+ return ret;
}
--
1.7.1
9 years, 3 months