[libvirt] Intend to add fuse filesystem support for libvirt lxc
by Gao feng
Hi Everyone,
Now I'm working on making the container's system info(such as /proc/meminfo,cpuinfo..) isolate from
the host.
I made a patch which implement showing the /proc/meminfo base on container's memcg,
and sent it to the community.(http://marc.info/?l=linux-mm&m=133826035821338&w=2)
but I found it's difficult to be accepted, because this way is ugly,
and somebody gave me some suggestions.
the first way is making another kernel file(just like memory.limit_in_bytes),and mount it to the container.
I don't like this way,because there will be many redundance information between this new kernel file and
the existing kernel file,some files such as memory.stat already contains memcg information.
the other way is adding fuse filesystem support for libvirt lxc.
with this way,
we can simply collect information from cgroup in fuse_operations.read function,
and mount this file to the container.
we can impletment isolate meminfo in userspace without changing kernel codes.
I have impletment fuse support for libvrit now, and ready to impletement the meminfo isolated.
I want to know if you have any comment or another ideas?
please let me know.
thanks.
12 years, 4 months
[libvirt] [PATCH] build: define WITH_INTERFACE for the driver
by Eric Blake
Our code was mistakenly relying on an undefined macro, WITH_INTERFACE,
for determining whether to load the interface driver which wraps the
netcf library. Clean this situation up by having only one automake
conditional for the driver, and having both WITH_NETCF (library
detected) and WITH_INTERFACE (driver enabled) in C code, in case a
future patch ever adds a network management via means other than
the netcf library.
While at it, output more information at the conclusion of configure
about the various drivers we enabled.
* configure.ac: Enhance with_netcf, and add with_interface.
Improve output to list final decisions. Replace WITH_NETCF with
WITH_INTERFACE.
* src/interface/netcf_driver.c: Rename...
* src/interface/interface_driver.c: ...to this.
* src/interface/interface_driver.h: Likewise.
* daemon/Makefile.am (libvirtd_LDADD): Reflect better naming.
* src/Makefile.am (libvirt_driver_interface_la_*): Likewise.
(INTERFACE_DRIVER_SOURCES): Reflect file moves.
* daemon/libvirtd.c (daemonInitialize): Likewise.
* tools/virsh.c (vshShowVersion): Show both driver and library
decisions.
* libvirt.spec.in (with_interface): Tweak to deal with new usage
as a real switch.
---
I think this addresses the point that Osier raised here:
https://www.redhat.com/archives/libvir-list/2012-June/msg01266.html
but it is complex enough that I'd appreciate a careful review.
configure.ac | 44 ++++++++++++++++----
daemon/Makefile.am | 2 +-
daemon/libvirtd.c | 6 +--
libvirt.spec.in | 10 +++--
src/Makefile.am | 4 +-
.../{netcf_driver.c => interface_driver.c} | 4 +-
.../{netcf_driver.h => interface_driver.h} | 0
tools/virsh.c | 11 +++--
8 files changed, 59 insertions(+), 22 deletions(-)
rename src/interface/{netcf_driver.c => interface_driver.c} (99%)
rename src/interface/{netcf_driver.h => interface_driver.h} (100%)
diff --git a/configure.ac b/configure.ac
index 6436885..a29b3b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1755,6 +1755,7 @@ if test "$with_network" = "yes" ; then
fi
AM_CONDITIONAL([WITH_NETWORK], [test "$with_network" = "yes"])
+dnl check whether helper code is needed for above selections
with_bridge=no
if test "$with_qemu:$with_lxc:$with_network" != "no:no:no"; then
with_bridge=yes
@@ -1762,16 +1763,31 @@ if test "$with_qemu:$with_lxc:$with_network" != "no:no:no"; then
fi
AM_CONDITIONAL([WITH_BRIDGE], [test "$with_bridge" = "yes"])
-dnl netcf library
+dnl check if the interface driver should be compiled
+
+AC_ARG_WITH([interface],
+ AC_HELP_STRING([--with-interface],
+ [with host interface driver @<:@default=check@:>@]),[],
+ [with_interface=check])
+
+dnl there's no use compiling the interface driver without the libvirt daemon
+if test "$with_libvirtd" = "no"; then
+ with_interface=no
+fi
+
+dnl The interface driver depends on the netcf library
AC_ARG_WITH([netcf],
AC_HELP_STRING([--with-netcf], [libnetcf support to configure physical host network interfaces @<:@default=check@:>@]),
[], [with_netcf=check])
NETCF_CFLAGS=
NETCF_LIBS=
-if test "$with_libvirtd" = "no" ; then
+if test "$with_libvirtd" = "no" || test "$with_interface" = "no"; then
with_netcf=no
fi
+if test "$with_interface:$with_netcf" = "yes:check"; then
+ with_netcf=yes
+fi
if test "$with_netcf" = "yes" || test "$with_netcf" = "check"; then
PKG_CHECK_MODULES(NETCF, netcf >= $NETCF_REQUIRED,
[with_netcf=yes], [
@@ -1792,11 +1808,21 @@ if test "$with_netcf" = "yes" || test "$with_netcf" = "check"; then
fi
fi
fi
-AM_CONDITIONAL([WITH_NETCF], [test "$with_netcf" = "yes"])
AC_SUBST([NETCF_CFLAGS])
AC_SUBST([NETCF_LIBS])
+dnl Final decision on the interface driver
+if test "$with_interface" = "check"; then
+ with_interface=$with_netcf
+fi
+
+if test "$with_interface" = "yes" ; then
+ AC_DEFINE_UNQUOTED([WITH_INTERFACE], [1],
+ [whether interface driver is enabled])
+fi
+AM_CONDITIONAL([WITH_INTERFACE], [test "$with_interface" = "yes"])
+dnl Check whether the Secrets driver is needed
AC_ARG_WITH([secrets],
AC_HELP_STRING([--with-secrets], [with local secrets management driver @<:@default=yes@:>@]),[],[with_secrets=yes])
@@ -2807,11 +2833,12 @@ AC_MSG_NOTICE([ ESX: $with_esx])
AC_MSG_NOTICE([ Hyper-V: $with_hyperv])
AC_MSG_NOTICE([ Test: $with_test])
AC_MSG_NOTICE([ Remote: $with_remote])
-AC_MSG_NOTICE([ Network: $with_network])
AC_MSG_NOTICE([Libvirtd: $with_libvirtd])
-AC_MSG_NOTICE([ netcf: $with_netcf])
-AC_MSG_NOTICE([ macvtap: $with_macvtap])
-AC_MSG_NOTICE([virtport: $with_virtualport])
+AC_MSG_NOTICE([ Network: $with_network])
+AC_MSG_NOTICE([ Iface: $with_interface])
+AC_MSG_NOTICE([ Secrets: $with_secrets])
+AC_MSG_NOTICE([ NodeDev: $with_nodedev])
+AC_MSG_NOTICE([NWfilter: $with_nwfilter])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Storage Drivers])
AC_MSG_NOTICE([])
@@ -2977,6 +3004,9 @@ AC_MSG_NOTICE([ Readline: $lv_use_readline])
AC_MSG_NOTICE([ Python: $with_python])
AC_MSG_NOTICE([ DTrace: $with_dtrace])
AC_MSG_NOTICE([ numad: $with_numad])
+AC_MSG_NOTICE([ bridge: $with_bridge])
+AC_MSG_NOTICE([ macvtap: $with_macvtap])
+AC_MSG_NOTICE([ virtport: $with_virtualport])
AC_MSG_NOTICE([ XML Catalog: $XML_CATALOG_FILE])
AC_MSG_NOTICE([ Init script: $with_init_script])
AC_MSG_NOTICE([Console locks: $with_console_lock_files])
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 71e91cd..f0e422e 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -148,7 +148,7 @@ if WITH_NETWORK
libvirtd_LDADD += ../src/libvirt_driver_network.la
endif
-if WITH_NETCF
+if WITH_INTERFACE
libvirtd_LDADD += ../src/libvirt_driver_interface.la
endif
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 9c06344..a4f98cf 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -74,8 +74,8 @@
# ifdef WITH_NETWORK
# include "network/bridge_driver.h"
# endif
-# ifdef WITH_NETCF
-# include "interface/netcf_driver.h"
+# ifdef WITH_INTERFACE
+# include "interface/interface_driver.h"
# endif
# ifdef WITH_STORAGE
# include "storage/storage_driver.h"
@@ -400,7 +400,7 @@ static void daemonInitialize(void)
# ifdef WITH_NETWORK
networkRegister();
# endif
-# ifdef WITH_NETCF
+# ifdef WITH_INTERFACE
interfaceRegister();
# endif
# ifdef WITH_STORAGE
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 896ef51..26ea2d9 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -70,6 +70,7 @@
# Then the secondary host drivers, which run inside libvirtd
%define with_network 0%{!?_without_network:%{server_drivers}}
+%define with_interface 0%{!?_without_interface:%{server_drivers}}
%define with_storage_fs 0%{!?_without_storage_fs:%{server_drivers}}
%define with_storage_lvm 0%{!?_without_storage_lvm:%{server_drivers}}
%define with_storage_iscsi 0%{!?_without_storage_iscsi:%{server_drivers}}
@@ -214,6 +215,7 @@
# The logic is the same as in configure.ac
%if ! %{with_libvirtd}
%define with_network 0
+%define with_interface 0
%define with_qemu 0
%define with_lxc 0
%define with_uml 0
@@ -267,9 +269,7 @@
%define with_nodedev 0
%endif
-%if %{with_netcf}
-%define with_interface 1
-%else
+%if !%{with_netcf}
%define with_interface 0
%endif
@@ -1056,6 +1056,9 @@ of recent versions of Linux (and other OSes).
%define _without_network --without-network
%endif
+%if ! %{with_interface}
+%define _without_interface --without-interface
+%endif
%if ! %{with_storage_fs}
%define _without_storage_fs --without-storage-fs
%endif
@@ -1171,6 +1174,7 @@ autoreconf -if
%{?_without_hyperv} \
%{?_without_vmware} \
%{?_without_network} \
+ %{?_without_interface} \
%{?_with_rhel5_api} \
%{?_without_storage_fs} \
%{?_without_storage_lvm} \
diff --git a/src/Makefile.am b/src/Makefile.am
index 2309984..3cfaf01 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -483,7 +483,7 @@ NETWORK_DRIVER_SOURCES = \
network/bridge_driver.h network/bridge_driver.c
INTERFACE_DRIVER_SOURCES = \
- interface/netcf_driver.h interface/netcf_driver.c
+ interface/interface_driver.h interface/interface_driver.c
SECRET_DRIVER_SOURCES = \
secret/secret_driver.h secret/secret_driver.c
@@ -924,7 +924,7 @@ EXTRA_DIST += network/default.xml
-if WITH_NETCF
+if WITH_INTERFACE
if WITH_DRIVER_MODULES
mod_LTLIBRARIES += libvirt_driver_interface.la
else
diff --git a/src/interface/netcf_driver.c b/src/interface/interface_driver.c
similarity index 99%
rename from src/interface/netcf_driver.c
rename to src/interface/interface_driver.c
index 45e6442..4959c72 100644
--- a/src/interface/netcf_driver.c
+++ b/src/interface/interface_driver.c
@@ -2,7 +2,7 @@
* interface_driver.c: backend driver methods to handle physical
* interface configuration using the netcf library.
*
- * Copyright (C) 2006-2011 Red Hat, Inc.
+ * Copyright (C) 2006-2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,7 +27,7 @@
#include "virterror_internal.h"
#include "datatypes.h"
-#include "netcf_driver.h"
+#include "interface_driver.h"
#include "interface_conf.h"
#include "memory.h"
diff --git a/src/interface/netcf_driver.h b/src/interface/interface_driver.h
similarity index 100%
rename from src/interface/netcf_driver.h
rename to src/interface/interface_driver.h
diff --git a/tools/virsh.c b/tools/virsh.c
index 53d1825..c1e7010 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -20832,15 +20832,18 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
#ifdef WITH_NETWORK
vshPrint(ctl, " Network");
#endif
-#ifdef WITH_BRIDGE
- vshPrint(ctl, " Bridging");
-#endif
-#ifdef WITH_NETCF
+#ifdef WITH_INTERFACE
vshPrint(ctl, " Interface");
#endif
#ifdef WITH_NWFILTER
vshPrint(ctl, " Nwfilter");
#endif
+#ifdef WITH_BRIDGE
+ vshPrint(ctl, " Bridging");
+#endif
+#ifdef WITH_NETCF
+ vshPrint(ctl, " Netcf");
+#endif
#ifdef WITH_VIRTUALPORT
vshPrint(ctl, " VirtualPort");
#endif
--
1.7.10.4
12 years, 4 months
[libvirt] [PATCH] esx_storage_driver: Add API to upload volumes (virStorageVolUpload for ESX storage driver)
by Ata Bohra
Patch to add API to upload Volume contents using ESX driver. As stream driver is not supported for ESX, I have used libcurl to transfer the volume, second, using flags here to pass
file descriptor of the source file.
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 9b64891..0519efc 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -1643,6 +1643,94 @@ esxStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
return 1;
}
+/**
+ * esxStorageVolumeUpload
+ *
+ * Upload file contents to a given volume.
+ * Method uses libcurl to POST the contents to ESX server.
+ * flags is used to pass file descriptor of the
+ * source file to be read.
+ */
+static int
+esxStorageVolumeUpload(virStorageVolPtr volume,
+ virStreamPtr stream,
+ unsigned long long offset,
+ unsigned long long length,
+ unsigned int flags)
+{
+ esxPrivate *priv = volume->conn->privateData;
+ int err = -1;
+ char *escapedDatastoreName = NULL;
+ char *url = NULL;
+ virBuffer buffer = VIR_BUFFER_INITIALIZER;
+ int fd = (int)flags;
+
+ /**
+ * Use CURL module to transfer the file to ESX.
+ * Use flags to pass the file handle.
+ */
+ const char *unescapedDatastoreName = virStorageVolGetPoolName(volume);
+ const char *volumeName = virStorageVolGetName(volume);
+
+ if (!unescapedDatastoreName) {
+ goto cleanup;
+ }
+
+ if (volume->conn != stream->conn) {
+ virReportInvalidArg(conn,
+ _("conn in %s must match stream connection."),
+ __FUNCTION__);
+ goto cleanup;
+ }
+
+ virBufferAsprintf(&buffer, "%s://%s:%d/folder/",
+ priv->parsedUri->transport,
+ volume->conn->uri->server, volume->conn->uri->port);
+
+ escapedDatastoreName = esxUtil_EscapeDatastoreItem(unescapedDatastoreName);
+
+ if (escapedDatastoreName == NULL) {
+ goto cleanup;
+ }
+
+ /* Prepare URL to upload file */
+ virBufferAdd(&buffer, volumeName, strlen(volumeName));
+ virBufferAddLit(&buffer, "?dcPath=");
+ virBufferURIEncodeString(&buffer, priv->primary->datacenterPath);
+ virBufferAddLit(&buffer, "&dsName=");
+ virBufferURIEncodeString(&buffer, escapedDatastoreName);
+
+ if (virBufferError(&buffer)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ url = virBufferContentAndReset(&buffer);
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return -1;
+ }
+
+ /* Upload file */
+ if (esxVI_CURL_UploadFile(priv->primary->curl, url,
+ fd, offset, length) < 0) {
+ goto cleanup;
+ }
+
+ err = 0;
+
+ cleanup:
+
+ if (url == NULL) {
+ virBufferFreeAndReset(&buffer);
+ }
+
+ VIR_FREE(escapedDatastoreName);
+ VIR_FREE(url);
+
+ return err;
+
+}
static virStorageDriver esxStorageDriver = {
@@ -1673,6 +1761,7 @@ static virStorageDriver esxStorageDriver = {
.volGetInfo = esxStorageVolumeGetInfo, /* 0.8.4 */
.volGetXMLDesc = esxStorageVolumeGetXMLDesc, /* 0.8.4 */
.volGetPath = esxStorageVolumeGetPath, /* 0.8.4 */
+ .volUpload = esxStorageVolumeUpload, /* 0.9.x */
.poolIsActive = esxStoragePoolIsActive, /* 0.8.2 */
.poolIsPersistent = esxStoragePoolIsPersistent, /* 0.8.2 */
};
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 5b5ab69..831ae36 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -425,7 +425,67 @@ esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content)
return 0;
}
+static size_t
+esxVI_CURL_read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+ size_t retcode = read((int) stream, ptr, size*nmemb);
+
+ VIR_DEBUG("Read bytes: %d", retcode);
+
+ return retcode;
+}
+
+int
+esxVI_CURL_UploadFile(esxVI_CURL *curl,
+ const char *url,
+ int fd,
+ unsigned long long offset,
+ unsigned long long length)
+{
+ int error = -1;
+ int responseCode = 0;
+
+ if (fd < 0) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "Invalid file descriptor: %d",
+ fd);
+ goto cleanup;
+ }
+
+ if (lseek(fd, (off_t) offset, SEEK_SET) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Cannot seek file descriptor "));
+ goto cleanup;
+ }
+
+ virMutexLock(&curl->lock);
+
+ /* set CURL headers */
+ curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt(curl->handle, CURLOPT_URL, url);
+ curl_easy_setopt(curl->handle, CURLOPT_READDATA, fd);
+ curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE_LARGE,
+ (curl_off_t) length);
+ curl_easy_setopt(curl->handle, CURLOPT_READFUNCTION,
+ esxVI_CURL_read_callback);
+ responseCode = esxVI_CURL_Perform(curl, url);
+
+ virMutexUnlock(&curl->lock);
+
+ if (responseCode < 0) {
+ goto cleanup;
+ } else if (responseCode != 200) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("HTTP response code %d for upload to '%s'"),
+ responseCode, url);
+ goto cleanup;
+ }
+ error = 0;
+
+ cleanup:
+
+ return error;
+}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SharedCURL
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index 78d3986..f95ad1d 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -92,7 +92,6 @@ typedef struct _esxVI_EnumerationValue esxVI_EnumerationValue;
typedef struct _esxVI_List esxVI_List;
-
enum _esxVI_APIVersion {
esxVI_APIVersion_Undefined = 0,
esxVI_APIVersion_Unknown,
@@ -167,6 +166,9 @@ void esxVI_CURL_Free(esxVI_CURL **curl);
int esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri);
int esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content);
int esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content);
+int esxVI_CURL_UploadFile(esxVI_CURL *curl, const char *url, int fd,
+ unsigned long long offset,
+ unsigned long long length);
diff --git a/src/libvirt.c b/src/libvirt.c
index 0aa50cb..508593b 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -12537,6 +12537,28 @@ error:
return NULL;
}
+/**
+ * virStorageVolGetPoolName:
+ * @vol: pointer to storage volume
+ *
+ * Fetch the storage volume pool name.
+ *
+ * Returns the pool name, or NULL on error
+ */
+const char*
+virStorageVolGetPoolName(virStorageVolPtr vol)
+{
+ VIR_DEBUG("vol=%p", vol);
+
+ virResetLastError();
+
+ if (!VIR_IS_STORAGE_VOL(vol)) {
+ virLibStorageVolError(VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+ virDispatchError(NULL);
+ return NULL;
+ }
+ return vol->pool;
+}
/**
* virStorageVolGetName:
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 2913a81..cdfbf15 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -542,6 +542,7 @@ LIBVIRT_0.9.13 {
virDomainSnapshotIsCurrent;
virDomainSnapshotListAllChildren;
virDomainSnapshotRef;
+ virStorageVolGetPoolName;
} LIBVIRT_0.9.11;
# .... define new API here using predicted next version number ....
Thanks!
Ata
Attachment:
1. StorageVolUpload.diff
12 years, 4 months