Add internal APIs for dealing with namespaces

Add some APIs for acquiring namespace file descriptors and
switching namespaces

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2012-12-21 16:50:18 +00:00
parent 3fd121c170
commit 5f669ea976
4 changed files with 126 additions and 1 deletions

View File

@ -180,7 +180,7 @@ dnl Availability of various common functions (non-fatal if missing),
dnl and various less common threadsafe functions
AC_CHECK_FUNCS_ONCE([cfmakeraw geteuid getgid getgrnam_r getmntent_r \
getpwuid_r getuid initgroups kill mmap newlocale posix_fallocate \
posix_memalign regexec sched_getaffinity])
posix_memalign regexec sched_getaffinity setns])
dnl Availability of pthread functions (if missing, win32 threading is
dnl assumed). Because of $LIB_PTHREAD, we cannot use AC_CHECK_FUNCS_ONCE.

View File

@ -1795,9 +1795,11 @@ virPidFileWritePath;
# virprocess.h
virProcessAbort;
virProcessGetAffinity;
virProcessGetNamespaces;
virProcessKill;
virProcessKillPainfully;
virProcessSetAffinity;
virProcessSetNamespaces;
virProcessTranslateStatus;
virProcessWait;

View File

@ -22,6 +22,8 @@
#include <config.h>
#include <dirent.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
@ -30,6 +32,7 @@
#include "virprocess.h"
#include "virerror.h"
#include "viralloc.h"
#include "virfile.h"
#include "virlog.h"
#include "virutil.h"
@ -489,3 +492,116 @@ int virProcessGetAffinity(pid_t pid ATTRIBUTE_UNUSED,
return -1;
}
#endif /* HAVE_SCHED_GETAFFINITY */
#if HAVE_SETNS
int virProcessGetNamespaces(pid_t pid,
size_t *nfdlist,
int **fdlist)
{
int ret = -1;
DIR *dh = NULL;
struct dirent *de;
char *nsdir = NULL;
char *nsfile = NULL;
size_t i;
*nfdlist = 0;
*fdlist = NULL;
if (virAsprintf(&nsdir, "/proc/%llu/ns",
(unsigned long long)pid) < 0) {
virReportOOMError();
goto cleanup;
}
if (!(dh = opendir(nsdir))) {
virReportSystemError(errno,
_("Cannot read directory %s"),
nsdir);
goto cleanup;
}
while ((de = readdir(dh))) {
int fd;
if (de->d_name[0] == '.')
continue;
if (VIR_EXPAND_N(*fdlist, *nfdlist, 1) < 0) {
virReportOOMError();
goto cleanup;
}
if (virAsprintf(&nsfile, "%s/%s", nsdir, de->d_name) < 0) {
virReportOOMError();
goto cleanup;
}
if ((fd = open(nsfile, O_RDWR)) < 0) {
virReportSystemError(errno,
_("Unable to open %s"),
nsfile);
goto cleanup;
}
(*fdlist)[(*nfdlist)-1] = fd;
VIR_FREE(nsfile);
}
ret = 0;
cleanup:
if (dh)
closedir(dh);
VIR_FREE(nsdir);
VIR_FREE(nsfile);
if (ret < 0) {
for (i = 0 ; i < *nfdlist ; i++) {
VIR_FORCE_CLOSE((*fdlist)[i]);
}
VIR_FREE(*fdlist);
}
return ret;
}
int virProcessSetNamespaces(size_t nfdlist,
int *fdlist)
{
size_t i;
if (nfdlist == 0) {
virReportInvalidArg(nfdlist, "%s",
_("Expected at least one file descriptor"));
return -1;
}
for (i = 0 ; i < nfdlist ; i++) {
if (setns(fdlist[i], 0) < 0) {
virReportSystemError(errno, "%s",
_("Unable to join domain namespace"));
return -1;
}
}
return 0;
}
#else /* ! HAVE_SETNS */
int virProcessGetNamespaces(pid_t pid,
size_t *nfdlist ATTRIBUTE_UNUSED,
int **fdlist ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS,
_("Cannot get namespaces for %llu"),
(unsigned long long)pid);
return -1;
}
int virProcessSetNamespaces(size_t nfdlist ATTRIBUTE_UNUSED,
int *fdlist ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s",
_("Cannot set namespaces"));
return -1;
}
#endif /* ! HAVE_SETNS */

View File

@ -47,4 +47,11 @@ int virProcessGetAffinity(pid_t pid,
virBitmapPtr *map,
int maxcpu);
int virProcessGetNamespaces(pid_t pid,
size_t *nfdlist,
int **fdlist);
int virProcessSetNamespaces(size_t nfdlist,
int *fdlist);
#endif /* __VIR_PROCESS_H__ */