From 7fdd3bb30a0da98b4877d2e97ea15c049f6e7d36 Mon Sep 17 00:00:00 2001 From: Planet-Lab Support Date: Fri, 12 Aug 2005 21:13:03 +0000 Subject: [PATCH 1/1] This commit was manufactured by cvs2svn to create tag 'before-util-vserver-0_30_208-merge'. --- Makefile.am | 7 + Makefile.in | 152 ++++++++-- aclocal.m4 | 15 +- configure | 22 +- distrib/Makefile-files | 1 + distrib/install-fc2 | 50 ++++ distrib/sample.conf | 13 +- doc/FAQ.txt | 20 -- doc/changelog.txt | 20 -- lib/Makefile-files | 2 + lib/sched_cmd.h | 47 +++ lib/virtual.h | 2 + lib/vserver-internal.h | 9 + lib/vserver.h | 22 ++ man/vsh.8 | 48 +++ python/Makefile | 15 + python/bwlimit.py | 158 ++++++++++ python/cpulimit.py | 117 ++++++++ python/pybuild.mk | 32 ++ python/setup.py | 40 +++ python/vduimpl.c | 574 ++++++++++++++++++++++++++++++++++++ python/vserver.py | 360 +++++++++++++++++++++++ python/vserverimpl.c | 261 +++++++++++++++++ scripts/Makefile-files | 3 + scripts/vcached | 102 +++++++ scripts/vserver | 198 +++---------- scripts/vuseradd | 98 +++++++ scripts/vuserdel | 63 ++++ src/Makefile-files | 10 +- src/chcontext.c | 1 + src/dlimit.h | 76 +++++ src/showattr.c | 30 +- src/vbuild.cc | 6 +- src/vdu.c | 292 ++++++++++++++----- src/vdu.h | 374 ++++++++++++++++++++++++ src/vlimit.c | 2 +- src/vsh.c | 645 +++++++++++++++++++++++++++++++++++++++++ src/vunify.cc | 6 +- src/vutil.h | 14 +- sysv/Makefile-files | 4 +- sysv/vcached.conf | 23 ++ sysv/vcached.logrotate | 10 + sysv/vcached.subst | 56 ++++ sysv/vservers.conf | 2 +- sysv/vservers.subst | 107 +++---- util-vserver.spec | 164 +++++++++-- util-vserver.spec.in | 164 +++++++++-- 47 files changed, 3972 insertions(+), 465 deletions(-) create mode 100644 distrib/install-fc2 delete mode 100644 doc/FAQ.txt delete mode 100644 doc/changelog.txt create mode 100644 lib/sched_cmd.h create mode 100644 man/vsh.8 create mode 100644 python/Makefile create mode 100644 python/bwlimit.py create mode 100755 python/cpulimit.py create mode 100644 python/pybuild.mk create mode 100644 python/setup.py create mode 100644 python/vduimpl.c create mode 100644 python/vserver.py create mode 100644 python/vserverimpl.c create mode 100755 scripts/vcached create mode 100755 scripts/vuseradd create mode 100755 scripts/vuserdel create mode 100644 src/dlimit.h create mode 100644 src/vdu.h create mode 100644 src/vsh.c create mode 100644 sysv/vcached.conf create mode 100644 sysv/vcached.logrotate create mode 100755 sysv/vcached.subst diff --git a/Makefile.am b/Makefile.am index 437c818..1ef9cc9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -83,6 +83,13 @@ else ln -sf '$(top_srcdir)/lib/virtual.h' '$@' endif +install-exec-hook: + cd $(DESTDIR)$(sbindir) && $(LN_S) vuseradd vadduser + cd $(DESTDIR)$(sbindir) && $(LN_S) vuserdel vdeluser + +install-data-hook: + cd $(DESTDIR)$(sysvdir) && $(LN_S) vservers vserver-init + include $(top_srcdir)/lib/Makefile-files include $(top_srcdir)/src/Makefile-files include $(top_srcdir)/distrib/Makefile-files diff --git a/Makefile.in b/Makefile.in index 9500fae..92b8a06 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.8.4 from Makefile.am. +# Makefile.in generated by automake 1.8.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -35,7 +35,7 @@ -SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) $(src_chbind_SOURCES) $(src_chcontext_SOURCES) $(src_fakerunlevel_SOURCES) $(src_filetime_SOURCES) $(src_ifspec_SOURCES) $(src_listdevip_SOURCES) $(src_parserpmdump_SOURCES) $(src_readlink_SOURCES) $(src_rebootmgr_SOURCES) $(src_reducecap_SOURCES) $(src_showattr_SOURCES) $(src_showperm_SOURCES) $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) $(src_vdu_SOURCES) $(src_vfiles_SOURCES) $(src_vkill_SOURCES) $(src_vlimit_SOURCES) $(src_vreboot_SOURCES) $(src_vserver_stat_SOURCES) $(src_vunify_SOURCES) $(tests_escaperoot_SOURCES) $(tests_forkbomb_SOURCES) $(tests_testipc_SOURCES) $(tests_testlimit_SOURCES) $(tests_testopenf_SOURCES) +SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) $(src_chbind_SOURCES) $(src_chcontext_SOURCES) $(src_fakerunlevel_SOURCES) $(src_filetime_SOURCES) $(src_ifspec_SOURCES) $(src_listdevip_SOURCES) $(src_parserpmdump_SOURCES) $(src_readlink_SOURCES) $(src_rebootmgr_SOURCES) $(src_reducecap_SOURCES) $(src_showattr_SOURCES) $(src_showperm_SOURCES) $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) $(src_vdlimit_SOURCES) $(src_vdu_SOURCES) $(src_vfiles_SOURCES) $(src_vkill_SOURCES) $(src_vlimit_SOURCES) $(src_vreboot_SOURCES) $(src_vserver_stat_SOURCES) $(src_vsh_SOURCES) $(src_vunify_SOURCES) $(tests_escaperoot_SOURCES) $(tests_forkbomb_SOURCES) $(tests_testipc_SOURCES) $(tests_testlimit_SOURCES) $(tests_testopenf_SOURCES) srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -102,6 +102,7 @@ lib_libvserver_a_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am__objects_1 = lib/lib_libvserver_a-syscall.$(OBJEXT) \ lib/lib_libvserver_a-syscall_rlimit.$(OBJEXT) \ + lib/lib_libvserver_a-syscall_setsched.$(OBJEXT) \ lib/lib_libvserver_a-syscall_kill.$(OBJEXT) \ lib/lib_libvserver_a-checkversion.$(OBJEXT) \ lib/lib_libvserver_a-getctx.$(OBJEXT) \ @@ -120,9 +121,10 @@ am__EXEEXT_2 = src/capchroot$(EXEEXT) src/fakerunlevel$(EXEEXT) \ src/vreboot$(EXEEXT) src/vunify$(EXEEXT) pkglibPROGRAMS_INSTALL = $(INSTALL_PROGRAM) am__EXEEXT_3 = src/chbind$(EXEEXT) src/chcontext$(EXEEXT) \ - src/rebootmgr$(EXEEXT) src/reducecap$(EXEEXT) \ - src/vlimit$(EXEEXT) src/vdu$(EXEEXT) src/vfiles$(EXEEXT) \ - src/vkill$(EXEEXT) src/vserver-stat$(EXEEXT) + src/rebootmgr$(EXEEXT) src/reducecap$(EXEEXT) src/vdu$(EXEEXT) \ + src/vsh$(EXEEXT) src/vdlimit$(EXEEXT) src/vlimit$(EXEEXT) \ + src/vfiles$(EXEEXT) src/vkill$(EXEEXT) \ + src/vserver-stat$(EXEEXT) sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(noinst_PROGRAMS) $(pkglib_PROGRAMS) $(sbin_PROGRAMS) am_src_capchroot_OBJECTS = src/capchroot.$(OBJEXT) @@ -170,6 +172,9 @@ src_vbuild_LDADD = $(LDADD) am_src_vcheck_OBJECTS = src/vcheck.$(OBJEXT) src/vutil.$(OBJEXT) src_vcheck_OBJECTS = $(am_src_vcheck_OBJECTS) src_vcheck_LDADD = $(LDADD) +am_src_vdlimit_OBJECTS = src/vdlimit.$(OBJEXT) +src_vdlimit_OBJECTS = $(am_src_vdlimit_OBJECTS) +src_vdlimit_DEPENDENCIES = lib/libvserver.a am_src_vdu_OBJECTS = src/vdu.$(OBJEXT) src_vdu_OBJECTS = $(am_src_vdu_OBJECTS) src_vdu_LDADD = $(LDADD) @@ -188,6 +193,9 @@ src_vreboot_LDADD = $(LDADD) am_src_vserver_stat_OBJECTS = src/vserver-stat.$(OBJEXT) src_vserver_stat_OBJECTS = $(am_src_vserver_stat_OBJECTS) src_vserver_stat_DEPENDENCIES = lib/libvserver.a +am_src_vsh_OBJECTS = src/vsh.$(OBJEXT) +src_vsh_OBJECTS = $(am_src_vsh_OBJECTS) +src_vsh_DEPENDENCIES = lib/libvserver.a am_src_vunify_OBJECTS = src/src_vunify-vunify.$(OBJEXT) \ src/src_vunify-vutil.$(OBJEXT) src_vunify_OBJECTS = $(am_src_vunify_OBJECTS) @@ -223,6 +231,7 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@ lib/$(DEPDIR)/lib_libvserver_a-syscall.Po \ @AMDEP_TRUE@ lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Po \ @AMDEP_TRUE@ lib/$(DEPDIR)/lib_libvserver_a-syscall_rlimit.Po \ +@AMDEP_TRUE@ lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po \ @AMDEP_TRUE@ lib/$(DEPDIR)/lib_libvserver_a-uint2str.Po \ @AMDEP_TRUE@ src/$(DEPDIR)/capchroot.Po src/$(DEPDIR)/chbind.Po \ @AMDEP_TRUE@ src/$(DEPDIR)/chcontext.Po \ @@ -239,9 +248,10 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@ src/$(DEPDIR)/src_vunify-vunify.Po \ @AMDEP_TRUE@ src/$(DEPDIR)/src_vunify-vutil.Po \ @AMDEP_TRUE@ src/$(DEPDIR)/vbuild.Po src/$(DEPDIR)/vcheck.Po \ -@AMDEP_TRUE@ src/$(DEPDIR)/vdu.Po src/$(DEPDIR)/vfiles.Po \ -@AMDEP_TRUE@ src/$(DEPDIR)/vlimit.Po src/$(DEPDIR)/vreboot.Po \ -@AMDEP_TRUE@ src/$(DEPDIR)/vserver-stat.Po \ +@AMDEP_TRUE@ src/$(DEPDIR)/vdlimit.Po src/$(DEPDIR)/vdu.Po \ +@AMDEP_TRUE@ src/$(DEPDIR)/vfiles.Po src/$(DEPDIR)/vlimit.Po \ +@AMDEP_TRUE@ src/$(DEPDIR)/vreboot.Po \ +@AMDEP_TRUE@ src/$(DEPDIR)/vserver-stat.Po src/$(DEPDIR)/vsh.Po \ @AMDEP_TRUE@ src/$(DEPDIR)/vutil.Po \ @AMDEP_TRUE@ tests/$(DEPDIR)/escaperoot.Po \ @AMDEP_TRUE@ tests/$(DEPDIR)/forkbomb.Po \ @@ -264,13 +274,14 @@ SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) \ $(src_parserpmdump_SOURCES) $(src_readlink_SOURCES) \ $(src_rebootmgr_SOURCES) $(src_reducecap_SOURCES) \ $(src_showattr_SOURCES) $(src_showperm_SOURCES) \ - $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) $(src_vdu_SOURCES) \ + $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) \ + $(src_vdlimit_SOURCES) $(src_vdu_SOURCES) \ $(src_vfiles_SOURCES) $(src_vkill_SOURCES) \ $(src_vlimit_SOURCES) $(src_vreboot_SOURCES) \ - $(src_vserver_stat_SOURCES) $(src_vunify_SOURCES) \ - $(tests_escaperoot_SOURCES) $(tests_forkbomb_SOURCES) \ - $(tests_testipc_SOURCES) $(tests_testlimit_SOURCES) \ - $(tests_testopenf_SOURCES) + $(src_vserver_stat_SOURCES) $(src_vsh_SOURCES) \ + $(src_vunify_SOURCES) $(tests_escaperoot_SOURCES) \ + $(tests_forkbomb_SOURCES) $(tests_testipc_SOURCES) \ + $(tests_testlimit_SOURCES) $(tests_testopenf_SOURCES) DIST_SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) \ $(src_chbind_SOURCES) $(src_chcontext_SOURCES) \ $(src_fakerunlevel_SOURCES) $(src_filetime_SOURCES) \ @@ -278,13 +289,14 @@ DIST_SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) \ $(src_parserpmdump_SOURCES) $(src_readlink_SOURCES) \ $(src_rebootmgr_SOURCES) $(src_reducecap_SOURCES) \ $(src_showattr_SOURCES) $(src_showperm_SOURCES) \ - $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) $(src_vdu_SOURCES) \ + $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) \ + $(src_vdlimit_SOURCES) $(src_vdu_SOURCES) \ $(src_vfiles_SOURCES) $(src_vkill_SOURCES) \ $(src_vlimit_SOURCES) $(src_vreboot_SOURCES) \ - $(src_vserver_stat_SOURCES) $(src_vunify_SOURCES) \ - $(tests_escaperoot_SOURCES) $(tests_forkbomb_SOURCES) \ - $(tests_testipc_SOURCES) $(tests_testlimit_SOURCES) \ - $(tests_testopenf_SOURCES) + $(src_vserver_stat_SOURCES) $(src_vsh_SOURCES) \ + $(src_vunify_SOURCES) $(tests_escaperoot_SOURCES) \ + $(tests_forkbomb_SOURCES) $(tests_testipc_SOURCES) \ + $(tests_testlimit_SOURCES) $(tests_testopenf_SOURCES) man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) @@ -440,6 +452,7 @@ CLEANFILES = $(sysv_GENSCRPTS) $(scripts_GENSCRPTS) \ lib_SRCS = lib/syscall.c \ lib/syscall_rlimit.c \ + lib/syscall_setsched.c \ lib/syscall_kill.c \ lib/checkversion.c \ lib/getctx.c \ @@ -450,6 +463,7 @@ lib_HDRS = lib/vserver.h lib_XHDRS = lib/syscall-compat.hc \ lib/syscall-legacy.hc \ lib/syscall_rlimit-v11.hc \ + lib/syscall_setsched-v13.hc \ lib/syscall_kill-v11.hc \ lib/getctx-compat.hc \ lib/getctx-legacy.hc \ @@ -483,8 +497,10 @@ src_sbin_PRGS = src/chbind \ src/chcontext \ src/rebootmgr \ src/reducecap \ - src/vlimit \ src/vdu \ + src/vsh \ + src/vdlimit \ + src/vlimit \ src/vfiles \ src/vkill \ src/vserver-stat @@ -511,6 +527,10 @@ src_vlimit_LDADD = lib/libvserver.a src_vkill_SOURCES = src/vkill.c src_vkill_LDADD = lib/libvserver.a src_vkill_CPPFLAGS = $(AM_CPPFLAGS) -DLEGACYDIR=\"$(legacydir)\" +src_vsh_SOURCES = src/vsh.c +src_vsh_LDADD = lib/libvserver.a +src_vdlimit_SOURCES = src/vdlimit.c +src_vdlimit_LDADD = lib/libvserver.a src_showattr_SOURCES = src/showattr.c src_showperm_SOURCES = src/showperm.c src_vbuild_SOURCES = src/vbuild.cc src/vutil.cc @@ -530,6 +550,7 @@ distrib_SCRPTS = distrib/install-mdk8.2 \ distrib/install-rh8.0 \ distrib/install-rh9.0 \ distrib/install-fc1 \ + distrib/install-fc2 \ distrib/sample.sh distrib_DAT = distrib/mdk8.2-minimum \ @@ -569,6 +590,9 @@ scripts_src_PRGS = scripts/vpstree \ scripts/vrpm \ scripts/vserver \ scripts/vserver-copy \ + scripts/vcached \ + scripts/vuseradd \ + scripts/vuserdel \ scripts/vtop scripts_gen_PRGS = scripts/vps @@ -606,6 +630,7 @@ sysv_XTRAS = sysv/rebootmgr.subst \ sysv/v_smb.subst \ sysv/v_sshd.subst \ sysv/v_xinetd.subst \ + sysv/vcached.subst \ sysv/vservers.subst sysv_GENSCRPTS = sysv/rebootmgr \ @@ -617,10 +642,11 @@ sysv_GENSCRPTS = sysv/rebootmgr \ sysv/v_smb \ sysv/v_sshd \ sysv/v_xinetd \ + sysv/vcached \ sysv/vservers sysv_SCRPTS = $(sysv_GENSCRPTS) -sysv_CFG = sysv/vservers.conf +sysv_CFG = sysv/vservers.conf sysv/vcached.conf linuxconf_gen_SCRPTS = linuxconf/newvserver linuxconf_src_DATMAN = linuxconf/newvserver.8 linuxconf_cfg_src_DTA = linuxconf/newvserver.defaults @@ -731,6 +757,8 @@ lib/lib_libvserver_a-syscall.$(OBJEXT): lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/lib_libvserver_a-syscall_rlimit.$(OBJEXT): lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) +lib/lib_libvserver_a-syscall_setsched.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) lib/lib_libvserver_a-syscall_kill.$(OBJEXT): lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/lib_libvserver_a-checkversion.$(OBJEXT): lib/$(am__dirstamp) \ @@ -876,6 +904,11 @@ src/vcheck.$(OBJEXT): src/$(am__dirstamp) \ src/vcheck$(EXEEXT): $(src_vcheck_OBJECTS) $(src_vcheck_DEPENDENCIES) src/$(am__dirstamp) @rm -f src/vcheck$(EXEEXT) $(CXXLINK) $(src_vcheck_LDFLAGS) $(src_vcheck_OBJECTS) $(src_vcheck_LDADD) $(LIBS) +src/vdlimit.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/vdlimit$(EXEEXT): $(src_vdlimit_OBJECTS) $(src_vdlimit_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/vdlimit$(EXEEXT) + $(LINK) $(src_vdlimit_LDFLAGS) $(src_vdlimit_OBJECTS) $(src_vdlimit_LDADD) $(LIBS) src/vdu.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/vdu$(EXEEXT): $(src_vdu_OBJECTS) $(src_vdu_DEPENDENCIES) src/$(am__dirstamp) @rm -f src/vdu$(EXEEXT) @@ -905,6 +938,10 @@ src/vserver-stat.$(OBJEXT): src/$(am__dirstamp) \ src/vserver-stat$(EXEEXT): $(src_vserver_stat_OBJECTS) $(src_vserver_stat_DEPENDENCIES) src/$(am__dirstamp) @rm -f src/vserver-stat$(EXEEXT) $(LINK) $(src_vserver_stat_LDFLAGS) $(src_vserver_stat_OBJECTS) $(src_vserver_stat_LDADD) $(LIBS) +src/vsh.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/vsh$(EXEEXT): $(src_vsh_OBJECTS) $(src_vsh_DEPENDENCIES) src/$(am__dirstamp) + @rm -f src/vsh$(EXEEXT) + $(LINK) $(src_vsh_LDFLAGS) $(src_vsh_OBJECTS) $(src_vsh_LDADD) $(LIBS) src/src_vunify-vunify.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/src_vunify-vutil.$(OBJEXT): src/$(am__dirstamp) \ @@ -1028,6 +1065,7 @@ mostlyclean-compile: -rm -f lib/lib_libvserver_a-syscall.$(OBJEXT) -rm -f lib/lib_libvserver_a-syscall_kill.$(OBJEXT) -rm -f lib/lib_libvserver_a-syscall_rlimit.$(OBJEXT) + -rm -f lib/lib_libvserver_a-syscall_setsched.$(OBJEXT) -rm -f lib/lib_libvserver_a-uint2str.$(OBJEXT) -rm -f src/capchroot.$(OBJEXT) -rm -f src/chbind.$(OBJEXT) @@ -1047,11 +1085,13 @@ mostlyclean-compile: -rm -f src/src_vunify-vutil.$(OBJEXT) -rm -f src/vbuild.$(OBJEXT) -rm -f src/vcheck.$(OBJEXT) + -rm -f src/vdlimit.$(OBJEXT) -rm -f src/vdu.$(OBJEXT) -rm -f src/vfiles.$(OBJEXT) -rm -f src/vlimit.$(OBJEXT) -rm -f src/vreboot.$(OBJEXT) -rm -f src/vserver-stat.$(OBJEXT) + -rm -f src/vsh.$(OBJEXT) -rm -f src/vutil.$(OBJEXT) -rm -f tests/escaperoot.$(OBJEXT) -rm -f tests/forkbomb.$(OBJEXT) @@ -1068,6 +1108,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-syscall.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-syscall_rlimit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-uint2str.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/capchroot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/chbind.Po@am__quote@ @@ -1087,11 +1128,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_vunify-vutil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vbuild.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vcheck.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vdlimit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vdu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vfiles.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vlimit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vreboot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vserver-stat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vsh.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vutil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/escaperoot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/forkbomb.Po@am__quote@ @@ -1147,6 +1190,22 @@ lib/lib_libvserver_a-syscall_rlimit.obj: lib/syscall_rlimit.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/lib_libvserver_a-syscall_rlimit.obj `if test -f 'lib/syscall_rlimit.c'; then $(CYGPATH_W) 'lib/syscall_rlimit.c'; else $(CYGPATH_W) '$(srcdir)/lib/syscall_rlimit.c'; fi` +lib/lib_libvserver_a-syscall_setsched.o: lib/syscall_setsched.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/lib_libvserver_a-syscall_setsched.o -MD -MP -MF "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo" -c -o lib/lib_libvserver_a-syscall_setsched.o `test -f 'lib/syscall_setsched.c' || echo '$(srcdir)/'`lib/syscall_setsched.c; \ +@am__fastdepCC_TRUE@ then mv -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo" "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po"; else rm -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lib/syscall_setsched.c' object='lib/lib_libvserver_a-syscall_setsched.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po' tmpdepfile='lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/lib_libvserver_a-syscall_setsched.o `test -f 'lib/syscall_setsched.c' || echo '$(srcdir)/'`lib/syscall_setsched.c + +lib/lib_libvserver_a-syscall_setsched.obj: lib/syscall_setsched.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/lib_libvserver_a-syscall_setsched.obj -MD -MP -MF "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo" -c -o lib/lib_libvserver_a-syscall_setsched.obj `if test -f 'lib/syscall_setsched.c'; then $(CYGPATH_W) 'lib/syscall_setsched.c'; else $(CYGPATH_W) '$(srcdir)/lib/syscall_setsched.c'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo" "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po"; else rm -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lib/syscall_setsched.c' object='lib/lib_libvserver_a-syscall_setsched.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po' tmpdepfile='lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/lib_libvserver_a-syscall_setsched.obj `if test -f 'lib/syscall_setsched.c'; then $(CYGPATH_W) 'lib/syscall_setsched.c'; else $(CYGPATH_W) '$(srcdir)/lib/syscall_setsched.c'; fi` + lib/lib_libvserver_a-syscall_kill.o: lib/syscall_kill.c @am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/lib_libvserver_a-syscall_kill.o -MD -MP -MF "lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Tpo" -c -o lib/lib_libvserver_a-syscall_kill.o `test -f 'lib/syscall_kill.c' || echo '$(srcdir)/'`lib/syscall_kill.c; \ @am__fastdepCC_TRUE@ then mv -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Tpo" "lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Po"; else rm -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Tpo"; exit 1; fi @@ -1435,6 +1494,22 @@ src/showperm.obj: src/showperm.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/showperm.obj `if test -f 'src/showperm.c'; then $(CYGPATH_W) 'src/showperm.c'; else $(CYGPATH_W) '$(srcdir)/src/showperm.c'; fi` +src/vdlimit.o: src/vdlimit.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vdlimit.o -MD -MP -MF "src/$(DEPDIR)/vdlimit.Tpo" -c -o src/vdlimit.o `test -f 'src/vdlimit.c' || echo '$(srcdir)/'`src/vdlimit.c; \ +@am__fastdepCC_TRUE@ then mv -f "src/$(DEPDIR)/vdlimit.Tpo" "src/$(DEPDIR)/vdlimit.Po"; else rm -f "src/$(DEPDIR)/vdlimit.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='src/vdlimit.c' object='src/vdlimit.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='src/$(DEPDIR)/vdlimit.Po' tmpdepfile='src/$(DEPDIR)/vdlimit.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vdlimit.o `test -f 'src/vdlimit.c' || echo '$(srcdir)/'`src/vdlimit.c + +src/vdlimit.obj: src/vdlimit.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vdlimit.obj -MD -MP -MF "src/$(DEPDIR)/vdlimit.Tpo" -c -o src/vdlimit.obj `if test -f 'src/vdlimit.c'; then $(CYGPATH_W) 'src/vdlimit.c'; else $(CYGPATH_W) '$(srcdir)/src/vdlimit.c'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "src/$(DEPDIR)/vdlimit.Tpo" "src/$(DEPDIR)/vdlimit.Po"; else rm -f "src/$(DEPDIR)/vdlimit.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='src/vdlimit.c' object='src/vdlimit.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='src/$(DEPDIR)/vdlimit.Po' tmpdepfile='src/$(DEPDIR)/vdlimit.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vdlimit.obj `if test -f 'src/vdlimit.c'; then $(CYGPATH_W) 'src/vdlimit.c'; else $(CYGPATH_W) '$(srcdir)/src/vdlimit.c'; fi` + src/vdu.o: src/vdu.c @am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vdu.o -MD -MP -MF "src/$(DEPDIR)/vdu.Tpo" -c -o src/vdu.o `test -f 'src/vdu.c' || echo '$(srcdir)/'`src/vdu.c; \ @am__fastdepCC_TRUE@ then mv -f "src/$(DEPDIR)/vdu.Tpo" "src/$(DEPDIR)/vdu.Po"; else rm -f "src/$(DEPDIR)/vdu.Tpo"; exit 1; fi @@ -1515,6 +1590,22 @@ src/vserver-stat.obj: src/vserver-stat.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vserver-stat.obj `if test -f 'src/vserver-stat.c'; then $(CYGPATH_W) 'src/vserver-stat.c'; else $(CYGPATH_W) '$(srcdir)/src/vserver-stat.c'; fi` +src/vsh.o: src/vsh.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vsh.o -MD -MP -MF "src/$(DEPDIR)/vsh.Tpo" -c -o src/vsh.o `test -f 'src/vsh.c' || echo '$(srcdir)/'`src/vsh.c; \ +@am__fastdepCC_TRUE@ then mv -f "src/$(DEPDIR)/vsh.Tpo" "src/$(DEPDIR)/vsh.Po"; else rm -f "src/$(DEPDIR)/vsh.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='src/vsh.c' object='src/vsh.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='src/$(DEPDIR)/vsh.Po' tmpdepfile='src/$(DEPDIR)/vsh.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vsh.o `test -f 'src/vsh.c' || echo '$(srcdir)/'`src/vsh.c + +src/vsh.obj: src/vsh.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vsh.obj -MD -MP -MF "src/$(DEPDIR)/vsh.Tpo" -c -o src/vsh.obj `if test -f 'src/vsh.c'; then $(CYGPATH_W) 'src/vsh.c'; else $(CYGPATH_W) '$(srcdir)/src/vsh.c'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "src/$(DEPDIR)/vsh.Tpo" "src/$(DEPDIR)/vsh.Po"; else rm -f "src/$(DEPDIR)/vsh.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='src/vsh.c' object='src/vsh.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='src/$(DEPDIR)/vsh.Po' tmpdepfile='src/$(DEPDIR)/vsh.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vsh.obj `if test -f 'src/vsh.c'; then $(CYGPATH_W) 'src/vsh.c'; else $(CYGPATH_W) '$(srcdir)/src/vsh.c'; fi` + .cc.o: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @@ -1858,11 +1949,9 @@ TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ - test -z "$$unique" && unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ - fi + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) @@ -1958,7 +2047,7 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(AMTAR) xf - ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac @@ -2080,10 +2169,14 @@ info-am: install-data-am: install-includeHEADERS install-legacySCRIPTS \ install-man install-scriptscfgDATA install-sysvSCRIPTS \ install-vservercfgDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-exec-am: install-libLIBRARIES install-pkglibDATA \ install-pkglibPROGRAMS install-pkglibSCRIPTS \ install-sbinPROGRAMS install-sbinSCRIPTS install-sysconfDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-info: install-info-am @@ -2160,6 +2253,13 @@ linuxvirtual.h: @ENSC_ENABLE_INTERNAL_HEADERS_FALSE@ ln -sf '$(kernelincludedir)/linux/virtual.h' '$@' && test -e '$@' || \ @ENSC_ENABLE_INTERNAL_HEADERS_FALSE@ ln -sf '$(top_srcdir)/lib/virtual.h' '$@' +install-exec-hook: + cd $(DESTDIR)$(sbindir) && $(LN_S) vuseradd vadduser + cd $(DESTDIR)$(sbindir) && $(LN_S) vuserdel vdeluser + +install-data-hook: + cd $(DESTDIR)$(sysvdir) && $(LN_S) vservers vserver-init + #install-data-hook: $(DESTDIR)$(pkglibdir)/setattr #$(DESTDIR)$(pkglibdir)/setattr: diff --git a/aclocal.m4 b/aclocal.m4 index c34e705..928b11c 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.8.4 -*- Autoconf -*- +# generated automatically by aclocal 1.8.3 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 # Free Software Foundation, Inc. @@ -5965,7 +5965,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.8"]) # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.8.4])]) + [AM_AUTOMAKE_VERSION([1.8.3])]) # AM_AUX_DIR_EXPAND @@ -6191,14 +6191,9 @@ AC_CACHE_CHECK([dependency style of $depcc], grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + # (even with -Werror). So we grep stderr for any message + # that says an option was ignored. + if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi diff --git a/configure b/configure index eb2a46c..1177303 100755 --- a/configure +++ b/configure @@ -2491,14 +2491,9 @@ else grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + # (even with -Werror). So we grep stderr for any message + # that says an option was ignored. + if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi @@ -3329,14 +3324,9 @@ else grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + # (even with -Werror). So we grep stderr for any message + # that says an option was ignored. + if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi diff --git a/distrib/Makefile-files b/distrib/Makefile-files index a0e22cc..b870522 100644 --- a/distrib/Makefile-files +++ b/distrib/Makefile-files @@ -24,6 +24,7 @@ distrib_SCRPTS = distrib/install-mdk8.2 \ distrib/install-rh8.0 \ distrib/install-rh9.0 \ distrib/install-fc1 \ + distrib/install-fc2 \ distrib/sample.sh distrib_DAT = distrib/mdk8.2-minimum \ diff --git a/distrib/install-fc2 b/distrib/install-fc2 new file mode 100644 index 0000000..bf8f76b --- /dev/null +++ b/distrib/install-fc2 @@ -0,0 +1,50 @@ +#!/bin/sh + +# Copyright (C) 2003 Enrico Scholz +# based on distrib/install-rh9.0 by Jacques Gelinas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# This script creates a vserver from RedHat 9.0 CD. Only +# the first CD is used and must be mounted in /mnt/cdrom. +# Specify the name of the vserver +# "install-rh9.0 test" will create /vservers/test + +: ${UTIL_VSERVER_VARS:=/usr/lib/util-vserver/util-vserver-vars} +test -e "$UTIL_VSERVER_VARS" || { + echo "Can not find util-vserver installation; aborting..." + exit 1 +} +. "$UTIL_VSERVER_VARS" + +USR_LIB_VSERVER=$PKGLIBDIR + +if [ $# -lt 1 ] ; then + echo $0 vserver-id [ group ] +elif [ -d $VROOTDIR/$1/var/lib/rpm ] ; then + echo $VROOTDIR/$1 already exist +else + VROOT=$VROOTDIR/$1 + $USR_LIB_VSERVER/install-pre.sh $1 + mkdir -p $VROOT/proc + mount -t proc none $VROOT/proc + mount -t devpts none $VROOT/dev/pts + mkdir -p $VROOT/var/lib/rpm + rpm --root $VROOT --initdb + yum --installroot="$VROOT" -y groupinstall "$2" + umount $VROOT/proc + umount $VROOT/dev/pts + $USR_LIB_VSERVER/install-post.sh $1 +fi diff --git a/distrib/sample.conf b/distrib/sample.conf index b56d9a3..9eb0dbc 100644 --- a/distrib/sample.conf +++ b/distrib/sample.conf @@ -2,23 +2,12 @@ # The default is to allocate a free context on the fly # In general you don't need to force a context #S_CONTEXT= -# Select the IP number assigned to the virtual server -# This IP must be one IP of the server, either an interface -# or an IP alias -IPROOT=1.2.3.4 -# The netmask and broadcast are computed by default from IPROOTDEV -#IPROOTMASK= -#IPROOTBCAST= -# You can define on which device the IP alias will be done -# The IP alias will be set when the server is started and unset -# when the server is stopped -IPROOTDEV=eth0 # Uncomment the onboot line if you want to enable this # virtual server at boot time #ONBOOT=yes # You can set a different host name for the vserver # If empty, the host name of the main server is used -S_HOSTNAME=somename.somedomain.com +S_HOSTNAME= # You can set a different NIS domain for the vserver # If empty, the current on is kept # Set it to "none" to have no NIS domain set diff --git a/doc/FAQ.txt b/doc/FAQ.txt deleted file mode 100644 index fe4bd67..0000000 --- a/doc/FAQ.txt +++ /dev/null @@ -1,20 +0,0 @@ - - Object not found! - - The requested URL was not found on this server. If you entered - the URL manually please check your spelling and try again. - - If you think this is a server error, please contact the - [1]webmaster - -Error 404 - - - [2]remtk - ven 18 jui 2003 11:41:32 EDT - Apache/2.0.40 (Red Hat Linux) - -Références - - 1. mailto:root@localhost - 2. http://remtk/ diff --git a/doc/changelog.txt b/doc/changelog.txt deleted file mode 100644 index fe4bd67..0000000 --- a/doc/changelog.txt +++ /dev/null @@ -1,20 +0,0 @@ - - Object not found! - - The requested URL was not found on this server. If you entered - the URL manually please check your spelling and try again. - - If you think this is a server error, please contact the - [1]webmaster - -Error 404 - - - [2]remtk - ven 18 jui 2003 11:41:32 EDT - Apache/2.0.40 (Red Hat Linux) - -Références - - 1. mailto:root@localhost - 2. http://remtk/ diff --git a/lib/Makefile-files b/lib/Makefile-files index c193cd6..5404f72 100644 --- a/lib/Makefile-files +++ b/lib/Makefile-files @@ -19,6 +19,7 @@ lib_SRCS = lib/syscall.c \ lib/syscall_rlimit.c \ + lib/syscall_setsched.c \ lib/syscall_kill.c \ lib/checkversion.c \ lib/getctx.c \ @@ -30,6 +31,7 @@ lib_HDRS = lib/vserver.h lib_XHDRS = lib/syscall-compat.hc \ lib/syscall-legacy.hc \ lib/syscall_rlimit-v11.hc \ + lib/syscall_setsched-v13.hc \ lib/syscall_kill-v11.hc \ lib/getctx-compat.hc \ lib/getctx-legacy.hc \ diff --git a/lib/sched_cmd.h b/lib/sched_cmd.h new file mode 100644 index 0000000..2a6f55b --- /dev/null +++ b/lib/sched_cmd.h @@ -0,0 +1,47 @@ +#ifndef _VX_SCHED_CMD_H +#define _VX_SCHED_CMD_H + +/* sched vserver commands */ + +#define VCMD_set_sched_v2 VC_CMD(SCHED, 1, 2) +#define VCMD_set_sched VC_CMD(SCHED, 1, 3) + +struct vcmd_set_sched_v2 { + int32_t fill_rate; + int32_t interval; + int32_t tokens; + int32_t tokens_min; + int32_t tokens_max; + uint64_t cpu_mask; +}; + +struct vcmd_set_sched_v3 { + uint32_t set_mask; + int32_t fill_rate; + int32_t interval; + int32_t tokens; + int32_t tokens_min; + int32_t tokens_max; + int32_t priority_bias; +}; + + +#define VXSM_FILL_RATE 0x0001 +#define VXSM_INTERVAL 0x0002 +#define VXSM_TOKENS 0x0010 +#define VXSM_TOKENS_MIN 0x0020 +#define VXSM_TOKENS_MAX 0x0040 +#define VXSM_PRIO_BIAS 0x0100 + +#define SCHED_KEEP (-2) + +#ifdef __KERNEL__ + +#include + +extern int vc_set_sched_v1(uint32_t, void __user *); +extern int vc_set_sched_v2(uint32_t, void __user *); +extern int vc_set_sched(uint32_t, void __user *); + +#endif /* __KERNEL__ */ +#endif /* _VX_SCHED_CMD_H */ diff --git a/lib/virtual.h b/lib/virtual.h index f55e6dd..f12b3d7 100644 --- a/lib/virtual.h +++ b/lib/virtual.h @@ -47,6 +47,8 @@ #define VC_CAT_PROCTRL 12 +#define VC_CAT_DLIMIT 36 + #define VC_CAT_RLIMIT 60 #define VC_CAT_SYSTEST 61 diff --git a/lib/vserver-internal.h b/lib/vserver-internal.h index bb9b7db..972f301 100644 --- a/lib/vserver-internal.h +++ b/lib/vserver-internal.h @@ -87,6 +87,15 @@ extern "C" { #endif +#define ENSC_STRUCT_IDX(STRUCT,ATTR) \ + ((char*)(&(STRUCT).ATTR) - (char*)(&(STRUCT))) +#define ENSC_SAME_STRUCT_IDX(LHS,RHS,ATTR) \ + (ENSC_STRUCT_IDX(LHS,ATTR) == ENSC_STRUCT_IDX(RHS,ATTR)) +#define ENSC_SAME_STRUCT_ITEM(LHS,RHS,ATTR) \ + (ENSC_SAME_STRUCT_IDX(LHS,RHS,ATTR) && \ + sizeof((LHS).ATTR)==sizeof((RHS).ATTR) && \ + sizeof(LHS)==sizeof(RHS)) + #ifndef HAVE_VSERVER #ifdef ENSC_SYSCALL_TRADITIONAL inline static UNUSED ALWAYSINLINE diff --git a/lib/vserver.h b/lib/vserver.h index 284f4a4..4f9205a 100644 --- a/lib/vserver.h +++ b/lib/vserver.h @@ -34,6 +34,15 @@ #define VC_LIM_INFINITY (~0ULL) #define VC_LIM_KEEP (~1ULL) +#define VC_VXSM_FILL_RATE 0x0001 +#define VC_VXSM_INTERVAL 0x0002 +#define VC_VXSM_TOKENS 0x0010 +#define VC_VXSM_TOKENS_MIN 0x0020 +#define VC_VXSM_TOKENS_MAX 0x0040 +#define VC_VXSM_PRIO_BIAS 0x0100 + + + #ifdef __cplusplus extern "C" { #endif @@ -81,6 +90,19 @@ extern "C" { int vc_get_rlimit_mask(xid_t ctx, struct vc_rlimit_mask *lim); +#define VC_CAT_SCHED 14 + struct vc_set_sched { + uint_least32_t set_mask; + int_least32_t fill_rate; + int_least32_t interval; + int_least32_t tokens; + int_least32_t tokens_min; + int_least32_t tokens_max; + int_least32_t priority_bias; + }; + + int vc_set_sched(xid_t xid, struct vc_set_sched const *); + /** sends a signal to a context/pid Special values for pid are: * -1 which means every process in ctx except the init-process diff --git a/man/vsh.8 b/man/vsh.8 new file mode 100644 index 0000000..85f914c --- /dev/null +++ b/man/vsh.8 @@ -0,0 +1,48 @@ +.de Sh \" Subsection +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Ip \" List item +.br +.ie \\n(.$>=3 .ne \\$3 +.el .ne 3 +.IP "\\$1" \\$2 +.. +.TH "VSH" 8 "2004-07-29" "PlanetLab specific Vserver shell" "vsh" + +.SH NAME +vsh \- Safely trampoline's a slice user from global vserver context to +the correspondingly named local vserver context\&. + +.SH "SYNOPSIS" + +.PP +\fBvsh\fR [COMMAND] \fR + +.TP +[COMMAND] +when specified, the command to run, otherwise vsh will just run the +user's shell as a login shell + +.SH "SUMMARY" + +.PP +vsh is used as the login shell for slice users in the global vserver's +/etc/passwd\&. It is invoked either by sshd when a slice user logs on +to a PlanetLab node or as root using the su command\&. When this +occurs, vsh switches vserver context and sets the uid/gid of the slice +user, as specified in the slice's vserver /etc/passwd\&. + +.PP +vsh assumes that the same account (by name) used to ssh/su into the +vserver also exists in the vserver specific /etc/passwd file\&. This +is the only reason that for now it is deemed to be PlanetLab +specific\&. diff --git a/python/Makefile b/python/Makefile new file mode 100644 index 0000000..35b5f43 --- /dev/null +++ b/python/Makefile @@ -0,0 +1,15 @@ +INCLUDES := -I.. -I../lib +LIBS = -L../lib -lvserver + +PY_MODS := vserver.py cpulimit.py bwlimit.py +PY_EXT_MODS := vduimpl.so vserverimpl.so + +all: py-build + +install: py-install + ln -s /usr/lib/util-vserver/util-vserver-vars \ + $(INSTALL_ROOT)/usr/lib/python2.3/site-packages/util_vserver_vars.py + +-include pybuild.mk + +.PHONY: all install diff --git a/python/bwlimit.py b/python/bwlimit.py new file mode 100644 index 0000000..b408caa --- /dev/null +++ b/python/bwlimit.py @@ -0,0 +1,158 @@ +#!/bin/env python2 -u + +# Based on code written by: Andy Bavier, acb@cs.princeton.edu +# +# Bandwidth limit script to run on PlanetLab nodes. The intent is to use +# the Hierarchical Token Bucket queueing discipline of 'tc' to (1) cap +# the output bandwidth of the node at a specified rate (e.g., 5Mbps) and +# (2) to allow all vservers to fairly share this rate. For instance, +# if there are N vservers, then each should get at least 5/N Mbps of +# bandwidth. +# +# Some relevant URLs: +# http://lartc.org/howto for how to use tc +# http://luxik.cdi.cz/~devik/qos/htb/ for info on htb + +import sys, os, re, string + +# Global variables +TC="/sbin/tc" # Where the modified tc program lives +OPS = ["change","add"] # Sequence of TC ops we'll try + +# Support to run system commands +import runcmd +def run(cmd): + try: + runcmd.run(cmd) + ret = True + except runcmd.Error, ex: + ret = False + + return ret + +def get_defaults(cap_file="/etc/planetlab/bwcap", default_cap="10mbit"): + # The maximum output bandwidth, read in from cap_file (if it + # exists). If cap_file does not exist, use default_cap for + # bandwidth cap. See also the 'cburst' parameter below. + cap=default_cap + try: + os.stat(cap_file) + fp = open(cap_file) + lines = fp.readlines() + fp.close() + try: + cap=string.strip(lines[0]) + except ValueError, ex: + pass + except OSError, ex: + pass + + # How many bytes a single token bucket is allowed to send at once. + # Small values (i.e., 3080 = two maximum-sized Ethernet packets) + # provide better fine-grained fairness. At high rates (e.g., + # cap=100mbit) this needs to be raised to allow full throughput. + cburst=30800 + + # The 'share' and 'quantum' parameters both influence the actual throughput + # seen by a particular vserver: + + # 'share' is the rate at which tokens fill the bucket, and so is + # the minimum bandwidth given to the task. I think this just + # needs to be set to some small value that is the same for all + # vservers. With the current value and a 5mbit cap, we can + # support 5000 vservers (5mbit/1kbit = 5000). With values lower + # than 10kbit, the HTB output (from tc -s -d class dev eth0) looks + # strange... this needs to be looked into further. + share="1kbit" + + # 'quantum' influences how excess bandwidth (i.e., above the + # 'share') is distributed to vservers. Apparently, vservers can + # send additional packets in proportion to their quantums (and not + # their shares, as one might expect). See: + # http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm#sharing + # The above link states that 'quantum' is automatically + # calculated for shares above 120kbit. Otherwise it should be + # set to a small value but at least one MTU, so I set it to one + # MTU. All vservers are assigned the same quantum and so they + # should share equally. + quantum=1540 + + return cap, cburst, share, quantum + + +def init(eth): + global TC, OPS + + cap, cburst, share, quantum = get_defaults() + if cap == "-1": return + + # Install HTB on $ETH. Specifies that all packets not matching a + # filter rule go to class with handle 9999. If we don't supply a + # default class, it sounds like non-matching packets can be sent + # at an unlimited rate. + for op in OPS: + cmd = "%s qdisc %s dev %s root handle 1: htb default 9999" % (TC,op,eth) + if run(cmd): break + + # Add a root class with bwcap capped rate + for op in OPS: + cmd = "%s class %s dev %s parent 1: classid 1:1 htb rate %s quantum %d" % \ + (TC, op, eth, cap, quantum) + if run(cmd): break + + # Set up the default class. Packets will fail to match a filter rule + # and end up here if they are sent by a process with UID < 500. + for op in OPS: + cmd = "%s class %s dev %s parent 1:1 classid 1:9999 htb rate %s ceil %s quantum %d cburst %d" % \ + (TC, op, eth, share, cap, quantum, cburst) + if run(cmd): break + + # The next command appears to throttle back processes that are + # sending faster than the token bucket can support, rather than + # just dropping their packets. + for op in OPS: + cmd = "%s qdisc %s dev %s parent 1:9999 handle 9999 pfifo" % \ + (TC, op, eth) + if run(cmd): break + +def on(xid, eth, bwlimit, cap, minrate, maxrate): + global TC, OPS + + default_cap, default_cburst, default_share, default_quantum = get_defaults() + quantum = bwlimit * default_quantum + + # Set up the per-vserver token bucket + for op in OPS: + cmd = "%s class %s dev %s parent 1:1 classid 1:%d htb rate %s ceil %s quantum %d cburst %d" % \ + (TC, op, eth, xid, minrate, cap, quantum, default_cburst) + if run(cmd): break + + # The next command appears to throttle back processes that are + # sending faster than the token bucket can support, rather than + # just dropping their packets. + for op in OPS: + cmd = "%s qdisc %s dev %s parent 1:%d handle %d pfifo" % \ + (TC, op, eth, xid, xid) + if run(cmd): break + + # Matches packets sent by a vserver to the appropriate token bucket. + # The raw socket module marks each packet with its vserver id. + # See: http://lartc.org/howto/lartc.qdisc.filters.html for more + # info on the filter command. + cmd = "%s filter del dev %s protocol ip prio %d" % (TC, eth, xid) + run(cmd) + cmd = "%s filter add dev %s prio %d parent 1:0 protocol ip handle %d fw flowid 1:%d" % \ + (TC, eth, xid, xid, xid) + run(cmd) + +def off(xid, eth): + cmd = "%s filter del dev %s protocol ip prio %d" % (TC, eth, xid) + run(cmd) + + cmd = "%s qdisc del dev %s parent 1:%d" % (TC, eth, xid) + run(cmd) + + cmd = "%s class del dev %s classid 1:%d" % (TC, eth, xid) + run(cmd) + + diff --git a/python/cpulimit.py b/python/cpulimit.py new file mode 100755 index 0000000..708f092 --- /dev/null +++ b/python/cpulimit.py @@ -0,0 +1,117 @@ +#!/usr/bin/python2 -u + +import sys, os, re, string + + +TCBASE="/rcfs/taskclass/" +RULES="/rcfs/ce/rules/" + +SYSCLASS=TCBASE + "system" +SYSRULE=RULES + "system" +SYSCPUSHARE=100 +DEFAULTMAXCPUSHARE=8192 + +def checkckrm(): + checks = [ "/rcfs", TCBASE, RULES ] + + for check in checks: + try: + answer = os.stat(check) + except: + print "%s does not exist" % check + return False + + return True + +def checkclass(tc): + try: + answer = os.stat(TCBASE + tc) + return True + + except: + print "%s class does not exist" % tc + return False + +def getxid(name): + xid = -1 + fp = open('/etc/passwd') + for line in fp.readlines(): + rec = string.splitfields(line,':') + if rec[0] == name: + xid = int(rec[2]) + break + + fp.close() + + if xid == -1: + # raise an exception + pass + + return xid + +def write(filename,s): + fp = os.open(filename,os.O_WRONLY|os.O_CREAT) + os.write(fp,s) + os.close(fp) + +def vs2ckrm_on(tc): + xid = getxid(tc) + + try: + os.mkdir(TCBASE + tc) + except OSError: + pass # ignore oserror for file exists + + s = "xid=%d,class=%s" % (xid,TCBASE+tc) + fname = RULES + tc + write(fname, s) + +def vs2ckrm_off(tc): + fname = TCBASE + tc + "/members" + for i in range(1,15): + fp = open(fname) + lines = fp.readlines() + try: + lines.remove("No data to display\n") + except ValueError: + pass + if len(lines) == 0: + try: + answer = os.stat(RULES + tc) + os.unlink(RULES + tc) + answer = os.stat(TCBASE + tc) + os.rmdir(TCBASE + tc) + except: + pass + break + + else: + print "enter context 1 and kill processes", lines + + +def cpulimit(tc,limit): + global TCBASE + + fname = TCBASE + tc + "/shares" + s = "res=cpu,guarantee=%d\n" % limit + write(fname,s) + +def cpuinit(): + global TCBASE + + fname = TCBASE + "shares" + s = "res=cpu,total_guarantee=%d\n" % DEFAULTMAXCPUSHARE + write(fname,s) + +if __name__ == "__main__": + try: + name = sys.argv[1] + limit = int(sys.argv[2]) + except: + print "caught exception" + + if checkckrm() is True: + cpuinit() + vs2ckrm_on(name) + cpulimit(name,limit) + vs2ckrm_off(name) diff --git a/python/pybuild.mk b/python/pybuild.mk new file mode 100644 index 0000000..140cc14 --- /dev/null +++ b/python/pybuild.mk @@ -0,0 +1,32 @@ +# Copyright 2005 Princeton University +# +# PY_MODS variable should be list of Python source modules +# PY_EXT_MODS should be list of Python extension modules (.so) that need +# to be built +# + +_PY_TMPDIR := .pybuild + +# use strip to remove extra whitespace +_PY_SETUP = $(strip python setup.py \ + $(foreach i,DEFS INCLUDES LIBS PY_MODS PY_EXT_MODS,\ + $(if $(subst undefined,,$(origin $i)),$i="$($i)"))) + +_PY_BUILD_ARGS := -t $(_PY_TMPDIR) -b $(_PY_TMPDIR)/build + +py-build: .pybuild/.prep-done $(PY_MODS) $(PY_EXT_MODS) + +.pybuild/.prep-done: + mkdir build .pybuild + ln -s ../build .pybuild + touch $@ + +$(PY_EXT_MODS): PY_EXT_MODS = $@ + +$(PY_EXT_MODS): %.so: %.c + $(_PY_SETUP) build_ext -f $(_PY_BUILD_ARGS) + +py-install: + $(_PY_SETUP) install --root=$(INSTALL_ROOT) + +.PHONY: py-build py-install py-clean diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 0000000..507a5c2 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,40 @@ +#!/usr/bin/python + +import re +import sys + +from distutils.core import setup, Extension + +MODULE_NAME_RE = "[A-Za-z_]+" + +if __name__ == "__main__": + + build_arg_re = re.compile(r"^([A-Z_]+)= *(.*)") + def split_args((build_args, argv), arg): + m = build_arg_re.match(arg) + if m: + (k, v) = m.groups() + build_args[k] = v + else: + argv += [arg] + return (build_args, argv) + + (build_args, argv) = reduce(split_args, sys.argv[1:], ({}, [])) + sys.argv[1:] = argv + extension_args = { "extra_compile_args": ["-Wall"] } + if "INCLUDES" in build_args: + extension_args["include_dirs"] = re.findall(r"-I([^ ]+)", + build_args["INCLUDES"]) + lib_args = build_args.get("LIBS", "") + if lib_args: + extension_args["library_dirs"] = re.findall(r"-L([^ ]+)", lib_args) + extension_args["libraries"] = re.findall(r"-l([^ ]+)", lib_args) + modules = re.findall("(%s).py" % MODULE_NAME_RE, + build_args.get("PY_MODS", "")) + extensions = map(lambda modname: Extension(modname, + [modname + ".c"], + **extension_args), + re.findall("(%s).so" % MODULE_NAME_RE, + build_args.get("PY_EXT_MODS", ""))) + + setup(py_modules = modules, ext_modules = extensions) diff --git a/python/vduimpl.c b/python/vduimpl.c new file mode 100644 index 0000000..01fc63c --- /dev/null +++ b/python/vduimpl.c @@ -0,0 +1,574 @@ +/* Copyright 2005 Princeton University */ + +#include + +#define _LARGEFILE64_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * hash table implementation + */ + +typedef ino64_t KEY; +typedef KEY *PKEY; +typedef struct stat64 VAL; +typedef VAL *PVAL; + +static inline +unsigned int +HASH(PKEY key){ + return (int) *key; +} + +static inline +unsigned int // boolean +EQUAL(PKEY key1, PKEY key2){ + return *key1 == *key2; +} + +#ifndef MIN +#define MIN(x,y) (((x)<(y))?(x):(y)) +#endif // MIN + +#ifndef MAX +#define MAX(x,y) (((x)>(y))?(x):(y)) +#endif // MAX + + +/* + * hash table support for efficient lookup of duplicate inodes + */ + +#define Multiplier (0x9e3779b9) +#define MaxLogBuckets (((sizeof (unsigned long))*8) - 2) +#define MaxBuckets (1< 2*MinDensity; *) + * to avoid excessive probes, we must try to keep MaxDensity low. *) + * Divide by 100 before using + */ +#define MaxDensity 75 /* max numEntries/NUMBER(buckets) */ +#define MinDensity 20 /* min numEntries/NUMBER(buckets) */ +#define IdealDensity 50 +#define BITSIZE(x) (sizeof(x)*8) + +#define NEW(type,num) ((type*)malloc(sizeof(type)*num)) +#define DISPOSE(ptr) (free((void*)ptr)) + +/* + * Generic Hash Entry Type + */ + +typedef struct VoidList { + struct VoidList *tail; +} VoidList, *PVoidList; + +typedef struct HashTable { + PVoidList *buckets; + unsigned int numBuckets; // number of buckets + unsigned int minLogBuckets; // minimum value for Log_2(initial size) + unsigned int logBuckets; // CEILING(Log2(NUMBER(buckets^))) + unsigned int maxEntries; // maximum number of entries + unsigned int minEntries; // minimum number of entries + unsigned int numEntries; // current num of entries in table + PVoidList cache; // cache of removed elements + int cacheSize; // current size of the cache + int maxCacheSize; // maximum size, -1 means unbounded, 0 no cache +} HashTable, *PHashTable; + +/* + * Hash Prototypes + */ + +PHashTable +Init(PHashTable tbl, unsigned int n, int maxCacheSize); + +void +Dispose(PHashTable tbl); + +unsigned int +Log_2(unsigned int x); + +void +NewBuckets(PHashTable tbl, unsigned int logBuckets); + +/* + * Generic Hash Table support + */ + +PHashTable +Init(PHashTable tbl, unsigned int n, int maxCacheSize){ + int idealBuckets; + int minBuckets; + + idealBuckets = MIN(((n*100)/IdealDensity),MaxBuckets); + minBuckets = MAX(MinBuckets, idealBuckets); + tbl->minLogBuckets = Log_2(minBuckets); + + NewBuckets(tbl, tbl->minLogBuckets); + tbl->numEntries = 0; + tbl->maxCacheSize = maxCacheSize; + tbl->cacheSize = 0; + tbl->cache = 0; + return tbl; +} // Init() + + +/* + * Internal procedures + */ + +unsigned int +Log_2(unsigned int x){ + /* return CEILING(LOG_2(x)) */ + unsigned int log = 0; + unsigned int n= 1; + + assert(x != 0); + while ((log < MaxLogBuckets) && (x > n)){ + log++; + n += n; + } + return log; +} + +void +NewBuckets(PHashTable tbl, unsigned int logBuckets){ + /* Allocate "2^logBuckets" buckets. */ + unsigned int numBuckets = 1 << logBuckets; + PVoidList *b; + unsigned int i; + + tbl->buckets = NEW(PVoidList, numBuckets); + tbl->numBuckets = numBuckets; + b = tbl->buckets; + + for (i=0; inumBuckets; i++){ + b[i] = NULL; + } + tbl->logBuckets = logBuckets; + tbl->maxEntries = MaxDensity * numBuckets / 100; + tbl->minEntries = MinDensity * numBuckets / 100; +} + +#ifndef NULL +#define NULL (void*)0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* + * Type specific hash entry + */ +typedef struct EntryList { + struct EntryList *tail; + KEY key; + VAL val; +}EntryList, *PEntryList; + +/* + * Type specific Hash implementation functions + */ + +static +void +Rehash(PHashTable tbl, unsigned int logBuckets) { + /* Reallocate "2^logBuckets" buckets, and rehash the entries into + * the new table. + */ + + PVoidList *oldBucketPointer; + PEntryList *ob, obi; + PEntryList *nb, *nbh; + PEntryList that, tail; + unsigned int index; + unsigned int i; + unsigned int oldNumBuckets; + + return; + assert(logBuckets <= MaxLogBuckets); + assert(logBuckets >= tbl->minLogBuckets); + oldBucketPointer = tbl->buckets; + ob = (PEntryList*)tbl->buckets; + oldNumBuckets = tbl->numBuckets; + + NewBuckets(tbl, logBuckets); + nb = (PEntryList*)tbl->buckets; + + for(i=0;ikey))*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets); + nbh = &(nb[index]); + tail = that->tail; + that->tail = *nbh; + *nbh = that; + that = tail; + } + } + DISPOSE (oldBucketPointer); +} + +static inline +unsigned int /* boolean */ +Get(PHashTable tbl, PKEY key, PVAL *val){ + PEntryList that; + unsigned int index; + + index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets); + that = (PEntryList)tbl->buckets[index]; + while ((that != NULL) && !EQUAL(key,&(that->key))) { + that = that->tail; + } + if (that != NULL){ + *val = &that->val; + return TRUE; + } + else { + return FALSE; + } +} + +static inline +unsigned int /* boolean */ +Put(PHashTable tbl, PKEY key, PVAL *val){ + PEntryList that; + PEntryList *first; + unsigned int index; + unsigned int res; + + index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets); + first = (PEntryList*)&(tbl->buckets[index]); + that = *first; + while ((that != NULL) && !EQUAL(key, &(that->key))){ + that = that->tail; + } + + /* found an entry in the hash table given above key */ + if (that != NULL){ + res = TRUE; + } + else { + /* check if we can reuse something from the cache */ + if (tbl->cache != NULL) { + that = (PEntryList)tbl->cache; + tbl->cache = (PVoidList)tbl->cache->tail; + that->key = *key; + that->tail = *first; + *first = that; + } + else { + that = NEW(EntryList,1); + that->key = *key; + that->tail = *first; + *first = that; + } + that->val = **val; + + tbl->numEntries++; + if ((tbl->logBuckets < MaxLogBuckets) + && (tbl->numEntries > tbl->maxEntries)){ + Rehash(tbl, tbl->logBuckets + 1); /* too crowded */ + } + res = FALSE; + } + *val = &that->val; + return res; + +} + +static inline +int +Delete(PHashTable tbl,PKEY key){ + PEntryList that, prev; + PEntryList *first; + unsigned int index; + + index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets); + first = (PEntryList*)&(tbl->buckets[index]); + that = *first; + prev = NULL; + + while ((that != NULL) && !EQUAL(key, &(that->key))){ + prev = that; + that = that->tail; + } + if (that != NULL) { + if (prev == NULL) { + *first = that->tail; + } + else { + prev->tail = that->tail; + } + if ((tbl->maxCacheSize == -1)||(tbl->cacheSize < tbl->maxCacheSize)) { + that->tail = (PEntryList)tbl->cache; + tbl->cache = (PVoidList)that; + tbl->cacheSize++; + } + else { + DISPOSE (that); + } + tbl->numEntries--; + if (tbl->maxCacheSize == 0) { + if ((tbl->logBuckets > tbl->minLogBuckets) + && (tbl->numEntries < tbl->minEntries)) { + Rehash(tbl, tbl->logBuckets - 1); /* too sparse */ + } + } + return TRUE; + } + else { + return FALSE; + } +} + +typedef void (*callback)(PKEY key, PVAL val); + +void +Iterate(PHashTable tbl, callback fn) +{ + PVoidList that; + unsigned int i; + + for(i=0;inumBuckets;i++) { + that = tbl->buckets[i]; + while ( that != (PVoidList)0 ) { + PEntryList entry = (PEntryList)that; + fn(&entry->key,&entry->val); + that = that->tail; + } + } +} + +void +Dispose(PHashTable tbl) +{ + PVoidList that, next; + unsigned int i; + + for(i=0;inumBuckets;i++) { + that = tbl->buckets[i]; + while( that != NULL) { + next = that->tail; + DISPOSE (that); + tbl->numEntries--; + that = next; + } + } + DISPOSE(tbl->buckets); + assert(tbl->numEntries = 0); +} + +static int /* boolean */ +INOPut(PHashTable tbl, ino64_t* key, struct stat64 **val){ + return Put(tbl, key, val); +} + +__extension__ typedef long long longlong; + +struct stats { + longlong inodes; + longlong blocks; + longlong size; +}; + +static short verbose = 0; + +static int vdu_onedir (PHashTable tbl, struct stats *__s, char const *path) +{ + char const *foo = path; + struct stat64 dirst, st; + struct dirent *ent; + char *name; + DIR *dir; + int dirfd; + int res = 0; + longlong dirsize, dirinodes, dirblocks; + + dirsize = dirinodes = dirblocks = 0; + + // A handle to speed up chdir + if ((dirfd = open (path,O_RDONLY)) == -1) { + return -1; + } + + if (fchdir (dirfd) == -1) { + return -1; + } + + if (fstat64 (dirfd,&dirst) != 0) { + return -1; + } + + if ((dir = opendir (".")) == NULL) { + return -1; + } + + /* Walk the directory entries and compute the sum of inodes, + * blocks, and disk space used. This code will recursively descend + * down the directory structure. + */ + + while ((ent=readdir(dir))!=NULL){ + if (lstat64(ent->d_name,&st)==-1){ + continue; + } + + dirinodes ++; + + if (S_ISREG(st.st_mode)){ + if (st.st_nlink > 1){ + struct stat64 *val; + int nlink; + + /* Check hash table if we've seen this inode + * before. Note that the hash maintains a + * (inode,struct stat) key value pair. + */ + + val = &st; + + (void) INOPut(tbl,&st.st_ino,&val); + + /* Note that after the INOPut call "val" refers to the + * value entry in the hash table --- not &st. This + * means that if the inode has been put into the hash + * table before, val will refer to the first st that + * was put into the hashtable. Otherwise, if it is + * the first time it is put into the hash table, then + * val will be equal to this &st. + */ + nlink = val->st_nlink; + nlink --; + + /* val refers to value in hash tbale */ + if (nlink == 0) { + + /* We saw all hard links to this particular inode + * as part of this sweep of vdu. So account for + * the size and blocks required by the file. + */ + + dirsize += val->st_size; + dirblocks += val->st_blocks; + + /* Do not delete the (ino,val) tuple from the tbl, + * as we need to handle the case when we are + * double counting a file due to a bind mount. + */ + val->st_nlink = 0; + + } else if (nlink > 0) { + val->st_nlink = nlink; + } else /* if(nlink < 0) */ { + /* We get here when we are double counting nlinks + due a bind mount. */ + + /* DO NOTHING */ + } + } else { + dirsize += st.st_size; + dirblocks += st.st_blocks; + } + + } else if (S_ISDIR(st.st_mode)) { + if ((st.st_dev == dirst.st_dev) && + (strcmp(ent->d_name,".")!=0) && + (strcmp(ent->d_name,"..")!=0)) { + + dirsize += st.st_size; + dirblocks += st.st_blocks; + + name = strdup(ent->d_name); + if (name==0) { + return -1; + } + res |= vdu_onedir(tbl,__s,name); + free(name); + fchdir(dirfd); + } + } else { + /* dirsize += st.st_size; */ + /* dirblocks += st.st_blocks; */ + } + } + closedir (dir); + close (dirfd); + __s->inodes += dirinodes; + __s->blocks += dirblocks; + __s->size += dirsize; + if (verbose) { + printf("%16lld %16lld %16lld %s\n",dirinodes, dirblocks, dirsize,foo); + printf("%16lld %16lld %16lld %s\n",__s->inodes, __s->blocks, __s->size,foo); + } + + return res; +} + + +static PyObject * +do_vdu(PyObject *self, PyObject *args) +{ + PyObject *tuple; + + const char *path; + int res; + struct stats s; + HashTable tbl; + + if (!PyArg_ParseTuple(args, "s", &path)) + return Py_None; + + /* init of tbl and stats */ + s.inodes = s.blocks = s.size = 0; + (void) Init(&tbl,0,0); + + res = vdu_onedir(&tbl, &s, path); + + /* deallocate whatever has been added to tbl */ + Dispose(&tbl); + + /* create a python (inode, block, size) tuple */ + tuple = Py_BuildValue("(L,L,L)", + s.inodes, + s.blocks>>1, /* NOTE: div by 2 to adjust + * 512b block count to 1K + * block count + */ + s.size); + return (res == -1) ? PyErr_SetFromErrno(PyExc_OSError) : tuple; +} + +static PyMethodDef methods[] = { + { "vdu", do_vdu, METH_VARARGS, + "perform vdu operation on directory tree" }, + { NULL, NULL, 0, NULL } +}; + +PyMODINIT_FUNC +initvduimpl(void) +{ + Py_InitModule("vduimpl", methods); +} diff --git a/python/vserver.py b/python/vserver.py new file mode 100644 index 0000000..1ec678a --- /dev/null +++ b/python/vserver.py @@ -0,0 +1,360 @@ +# Copyright 2005 Princeton University + +import errno +import fcntl +import os +import re +import sys +import time +import traceback + +import mountimpl +import linuxcaps +import passfdimpl +import utmp +import vserverimpl, vduimpl +import cpulimit, bwlimit + +from util_vserver_vars import * + +CAP_SAFE = (linuxcaps.CAP_CHOWN | + linuxcaps.CAP_DAC_OVERRIDE | + linuxcaps.CAP_DAC_READ_SEARCH | + linuxcaps.CAP_FOWNER | + linuxcaps.CAP_FSETID | + linuxcaps.CAP_KILL | + linuxcaps.CAP_SETGID | + linuxcaps.CAP_SETUID | + linuxcaps.CAP_SETPCAP | + linuxcaps.CAP_SYS_TTY_CONFIG | + linuxcaps.CAP_LEASE | + linuxcaps.CAP_SYS_CHROOT | + linuxcaps.CAP_SYS_PTRACE) + +# +# these are the flags taken from the kernel linux/vserver/legacy.h +# +FLAGS_LOCK = 1 +FLAGS_SCHED = 2 # XXX - defined in util-vserver/src/chcontext.c +FLAGS_NPROC = 4 +FLAGS_PRIVATE = 8 +FLAGS_INIT = 16 +FLAGS_HIDEINFO = 32 +FLAGS_ULIMIT = 64 +FLAGS_NAMESPACE = 128 + +# default values for new vserver scheduler +SCHED_TOKENS_MIN = 50 +SCHED_TOKENS_MAX = 100 + + +class VServer: + + INITSCRIPTS = [('/etc/rc.vinit', 'start'), + ('/etc/rc.d/rc', '%(runlevel)d')] + + def __init__(self, name): + + self.name = name + self.config = self.__read_config_file("/etc/vservers.conf") + self.config.update(self.__read_config_file("/etc/vservers/%s.conf" % + self.name)) + self.flags = 0 + flags = self.config["S_FLAGS"].split(" ") + if "lock" in flags: + self.flags |= FLAGS_LOCK + if "nproc" in flags: + self.flags |= FLAGS_NPROC + self.remove_caps = ~CAP_SAFE + self.ctx = int(self.config["S_CONTEXT"]) + + config_var_re = re.compile(r"^ *([A-Z_]+)=(.*)\n?$", re.MULTILINE) + + def __read_config_file(self, filename): + + f = open(filename, "r") + data = f.read() + f.close() + config = {} + for m in self.config_var_re.finditer(data): + (key, val) = m.groups() + config[key] = val.strip('"') + return config + + def __do_chroot(self): + + return os.chroot("%s/%s" % (VROOTDIR, self.name)) + + def set_disklimit(self, blocktotal): + path = "%s/%s" % (VROOTDIR, self.name) + inodes, blockcount, size = vduimpl.vdu(path) + blockcount = blockcount >> 1 + + if blocktotal > blockcount: + vserverimpl.setdlimit(path, self.ctx, blockcount>>1, \ + blocktotal, inodes, -1, 2) + else: + # should raise some error value + print "block limit (%d) ignored for vserver %s" %(blocktotal,self.name) + + def get_disklimit(self): + path = "%s/%s" % (VROOTDIR, self.name) + try: + blocksused, blocktotal, inodesused, inodestotal, reserved = \ + vserverimpl.getdlimit(path,self.ctx) + except OSError, ex: + if ex.errno == 3: + # get here if no vserver disk limit has been set for xid + # set blockused to -1 to indicate no limit + blocktotal = -1 + + return blocktotal + + def set_sched(self, shares, besteffort = True): + # for the old CKRM scheduler + if cpulimit.checkckrm() is True: + cpulimit.cpuinit() + cpulimit.vs2ckrm_on(self.name) + try: + cpulimit.cpulimit(self.name,shares) + except OSError, ex: + if ex.errno == 22: + print "invalid shares argument" + # should re-raise exception?! + + # for the new vserver scheduler + else: + global SCHED_TOKENS_MIN, SCHED_TOKENS_MAX + tokensmin = SCHED_TOKENS_MIN + tokensmax = SCHED_TOKENS_MAX + + if besteffort is True: + # magic "interval" value for Andy's scheduler to denote besteffort + interval = 1000 + fillrate = shares + else: + interval = 1001 + fillrate = shares + + try: + vserverimpl.setsched(self.ctx,fillrate,interval,tokensmin,tokensmax) + except OSError, ex: + if ex.errno == 22: + print "kernel does not support vserver scheduler" + else: + raise ex + + def get_sched(self): + # have no way of querying scheduler right now on a per vserver basis + return (-1, False) + + def set_memlimit(self, limit): + ret = vserverimpl.setrlimit(self.ctx,5,limit) + return ret + + def get_memlimit(self): + ret = vserverimpl.getrlimit(self.ctx,5) + return ret + + def set_tasklimit(self, limit): + ret = vserverimpl.setrlimit(self.ctx,6,limit) + return ret + + def get_tasklimit(self): + ret = vserverimpl.getrlimit(self.ctx,6) + return ret + + def set_bwlimit(self, eth, limit, cap, minrate, maxrate): + if cap == "-1": + bwlimit.off(self.ctx,eth) + else: + bwlimit.on(self.ctx, eth, limit, cap, minrate, maxrate) + + def get_bwlimit(self, eth): + # not implemented yet + bwlimit = -1 + cap = "unknown" + minrate = "unknown" + maxrate = "unknown" + return (bwlimit, cap, minrate, maxrate) + + def open(self, filename, mode = "r", bufsize = -1): + + (sendsock, recvsock) = passfdimpl.socketpair() + child_pid = os.fork() + if child_pid == 0: + try: + # child process + self.__do_chroot() + f = open(filename, mode) + passfdimpl.sendmsg(f.fileno(), sendsock) + os._exit(0) + except EnvironmentError, ex: + (result, errmsg) = (ex.errno, ex.strerror) + except Exception, ex: + (result, errmsg) = (255, str(ex)) + os.write(sendsock, errmsg) + os._exit(result) + + # parent process + + # XXX - need this since a lambda can't raise an exception + def __throw(ex): + raise ex + + os.close(sendsock) + throw = lambda : __throw(Exception(errmsg)) + while True: + try: + (pid, status) = os.waitpid(child_pid, 0) + if os.WIFEXITED(status): + result = os.WEXITSTATUS(status) + if result != 255: + errmsg = os.strerror(result) + throw = lambda : __throw(IOError(result, errmsg)) + else: + errmsg = "unexpected exception in child" + else: + result = -1 + errmsg = "child killed" + break + except OSError, ex: + if ex.errno != errno.EINTR: + os.close(recvsock) + raise ex + fcntl.fcntl(recvsock, fcntl.F_SETFL, os.O_NONBLOCK) + try: + (fd, errmsg) = passfdimpl.recvmsg(recvsock) + except OSError, ex: + if ex.errno != errno.EAGAIN: + throw = lambda : __throw(ex) + fd = 0 + os.close(recvsock) + if not fd: + throw() + + return os.fdopen(fd, mode, bufsize) + + def __do_chcontext(self, state_file = None): + + vserverimpl.chcontext(self.ctx, self.remove_caps) + if not state_file: + return + print >>state_file, "S_CONTEXT=%d" % self.ctx + print >>state_file, "S_PROFILE=%s" % self.config.get("S_PROFILE", "") + state_file.close() + + def __prep(self, runlevel, log): + + """ Perform all the crap that the vserver script does before + actually executing the startup scripts. """ + + # remove /var/run and /var/lock/subsys files + # but don't remove utmp from the top-level /var/run + RUNDIR = "/var/run" + LOCKDIR = "/var/lock/subsys" + filter_fn = lambda fs: filter(lambda f: f != 'utmp', fs) + garbage = reduce((lambda (out, ff), (dir, subdirs, files): + (out + map((dir + "/").__add__, ff(files)), + lambda fs: fs)), + list(os.walk(RUNDIR)), + ([], filter_fn))[0] + garbage += filter(os.path.isfile, map((LOCKDIR + "/").__add__, + os.listdir(LOCKDIR))) + for f in garbage: + os.unlink(f) + + # set the initial runlevel + f = open(RUNDIR + "/utmp", "w") + utmp.set_runlevel(f, runlevel) + f.close() + + # mount /proc and /dev/pts + self.__do_mount("none", "/proc", "proc") + # XXX - magic mount options + self.__do_mount("none", "/dev/pts", "devpts", 0, "gid=5,mode=0620") + + def __do_mount(self, *mount_args): + + try: + mountimpl.mount(*mount_args) + except OSError, ex: + if ex.errno == errno.EBUSY: + # assume already mounted + return + raise ex + + def enter(self): + + state_file = open("/var/run/vservers/%s.ctx" % self.name, "w") + self.__do_chroot() + self.__do_chcontext(state_file) + + def start(self, wait, runlevel = 3): + + child_pid = os.fork() + if child_pid == 0: + # child process + try: + # get a new session + os.setsid() + + # open state file to record vserver info + state_file = open("/var/run/vservers/%s.ctx" % self.name, "w") + + # use /dev/null for stdin, /var/log/boot.log for stdout/err + os.close(0) + os.close(1) + os.open("/dev/null", os.O_RDONLY) + self.__do_chroot() + log = open("/var/log/boot.log", "w", 0) + os.dup2(1, 2) + + print >>log, ("%s: starting the virtual server %s" % + (time.asctime(time.gmtime()), self.name)) + + # perform pre-init cleanup + self.__prep(runlevel, log) + + # execute each init script in turn + # XXX - we don't support all scripts that vserver script does + cmd_pid = 0 + for cmd in self.INITSCRIPTS + [None]: + # wait for previous command to terminate, unless it + # is the last one and the caller has specified to wait + if cmd_pid and (cmd != None or wait): + try: + os.waitpid(cmd_pid, 0) + except: + print >>log, "error waiting for %s:" % cmd_pid + traceback.print_exc() + + # end of list + if cmd == None: + os._exit(0) + + # fork and exec next command + cmd_pid = os.fork() + if cmd_pid == 0: + try: + # enter vserver context + self.__do_chcontext(state_file) + arg_subst = { 'runlevel': runlevel } + cmd_args = [cmd[0]] + map(lambda x: x % arg_subst, + cmd[1:]) + print >>log, "executing '%s'" % " ".join(cmd_args) + os.execl(cmd[0], *cmd_args) + except: + traceback.print_exc() + os._exit(1) + else: + # don't want to write state_file multiple times + state_file = None + + # we get here due to an exception in the top-level child process + except Exception, ex: + traceback.print_exc() + os._exit(0) + + # parent process + return child_pid diff --git a/python/vserverimpl.c b/python/vserverimpl.c new file mode 100644 index 0000000..5b2cdb8 --- /dev/null +++ b/python/vserverimpl.c @@ -0,0 +1,261 @@ +/* Copyright 2005 Princeton University + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PRINCETON +UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include + +#include "config.h" +#include "compat.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vserver.h" +#include "vserver-internal.h" +#include "sched_cmd.h" +#include "virtual.h" + +/* + * chcontext + */ +static PyObject * +vserver_chcontext(PyObject *self, PyObject *args) +{ + unsigned xid; + unsigned caps_remove = 0; + + if (!PyArg_ParseTuple(args, "I|I", &xid, &caps_remove)) + return NULL; + + if (vc_new_s_context(xid, caps_remove, 0) < 0) + return PyErr_SetFromErrno(PyExc_OSError); + + return Py_None; +} + +static PyObject * +vserver_set_rlimit(PyObject *self, PyObject *args) { + struct vc_rlimit limits; + int xid, resource; + PyObject *ret; + + limits.min = VC_LIM_KEEP; + limits.soft = VC_LIM_KEEP; + limits.hard = VC_LIM_KEEP; + + if (!PyArg_ParseTuple(args, "iiL", &xid, &resource, &limits.hard)) + return NULL; + + ret = Py_None; + if (vc_set_rlimit(xid, resource, &limits)) + ret = PyErr_SetFromErrno(PyExc_OSError); + else if (vc_get_rlimit(xid, resource, &limits)==-1) + ret = PyErr_SetFromErrno(PyExc_OSError); + else + ret = Py_BuildValue("L",limits.hard); + + return ret; +} + +static PyObject * +vserver_get_rlimit(PyObject *self, PyObject *args) { + struct vc_rlimit limits; + int xid, resource; + PyObject *ret; + + limits.min = VC_LIM_KEEP; + limits.soft = VC_LIM_KEEP; + limits.hard = VC_LIM_KEEP; + + if (!PyArg_ParseTuple(args, "ii", &xid, &resource)) + return NULL; + + ret = Py_None; + if (vc_get_rlimit(xid, resource, &limits)==-1) + ret = PyErr_SetFromErrno(PyExc_OSError); + else + ret = Py_BuildValue("L",limits.hard); + + return ret; +} + +/* + * setsched + */ +static PyObject * +vserver_setsched(PyObject *self, PyObject *args) +{ + unsigned xid; + struct vc_set_sched sched; + + sched.set_mask = (VC_VXSM_FILL_RATE | + VC_VXSM_INTERVAL | + VC_VXSM_TOKENS_MIN | + VC_VXSM_TOKENS_MAX); + + if (!PyArg_ParseTuple(args, "I|I|I|I|I", &xid, + &sched.fill_rate, + &sched.interval, + &sched.tokens_min, + &sched.tokens_max)) + return NULL; + + if (vc_set_sched(xid, &sched) == -1) + return PyErr_SetFromErrno(PyExc_OSError); + + return Py_None; +} + +/* + * setsched + */ + +/* inode vserver commands */ +#define VCMD_add_dlimit VC_CMD(DLIMIT, 1, 0) +#define VCMD_rem_dlimit VC_CMD(DLIMIT, 2, 0) +#define VCMD_set_dlimit VC_CMD(DLIMIT, 5, 0) +#define VCMD_get_dlimit VC_CMD(DLIMIT, 6, 0) + +struct vcmd_ctx_dlimit_base_v0 { + char *name; + uint32_t flags; +}; + +struct vcmd_ctx_dlimit_v0 { + char *name; + uint32_t space_used; /* used space in kbytes */ + uint32_t space_total; /* maximum space in kbytes */ + uint32_t inodes_used; /* used inodes */ + uint32_t inodes_total; /* maximum inodes */ + uint32_t reserved; /* reserved for root in % */ + uint32_t flags; +}; + +#define CDLIM_UNSET (0ULL) +#define CDLIM_INFINITY (~0ULL) +#define CDLIM_KEEP (~1ULL) + +static PyObject * +vserver_get_dlimit(PyObject *self, PyObject *args) +{ + PyObject *res; + char* path; + unsigned xid; + struct vcmd_ctx_dlimit_v0 data; + int r; + + if (!PyArg_ParseTuple(args, "si", &path,&xid)) + return NULL; + + memset(&data, 0, sizeof(data)); + data.name = path; + data.flags = 0; + r = vserver(VCMD_get_dlimit, xid, &data); + if (r>=0) { + res = Py_BuildValue("(i,i,i,i,i)", + data.space_used, + data.space_total, + data.inodes_used, + data.inodes_total, + data.reserved); + } else { + res = PyErr_SetFromErrno(PyExc_OSError); + } + + return res; +} + + +static PyObject * +vserver_set_dlimit(PyObject *self, PyObject *args) +{ + char* path; + unsigned xid; + struct vcmd_ctx_dlimit_base_v0 init; + struct vcmd_ctx_dlimit_v0 data; + int r; + + memset(&data,0,sizeof(data)); + if (!PyArg_ParseTuple(args, "siiiiii", &path, + &xid, + &data.space_used, + &data.space_total, + &data.inodes_used, + &data.inodes_total, + &data.reserved)) + return NULL; + + data.name = path; + data.flags = 0; + + memset(&init, 0, sizeof(init)); + init.name = path; + init.flags = 0; + + r = vserver(VCMD_rem_dlimit, xid, &init); + if (r<0){} + r = vserver(VCMD_add_dlimit, xid, &init); + if (r<0){} + r = vserver(VCMD_set_dlimit, xid, &data); + if (r<0){} + return Py_None; +} + +static PyMethodDef methods[] = { + { "chcontext", vserver_chcontext, METH_VARARGS, + "Change to the given vserver context" }, + { "setsched", vserver_setsched, METH_VARARGS, + "Change vserver scheduling attributes for given vserver context" }, + { "setdlimit", vserver_set_dlimit, METH_VARARGS, + "Set disk limits for given vserver context" }, + { "getdlimit", vserver_get_dlimit, METH_VARARGS, + "Get disk limits for given vserver context" }, + { "setrlimit", vserver_set_rlimit, METH_VARARGS, + "Set resource limits for given resource of a vserver context" }, + { "getrlimit", vserver_get_rlimit, METH_VARARGS, + "Get resource limits for given resource of a vserver context" }, + { NULL, NULL, 0, NULL } +}; + +PyMODINIT_FUNC +initvserverimpl(void) +{ + Py_InitModule("vserverimpl", methods); +} diff --git a/scripts/Makefile-files b/scripts/Makefile-files index cec9518..fccc81b 100644 --- a/scripts/Makefile-files +++ b/scripts/Makefile-files @@ -36,6 +36,9 @@ scripts_src_PRGS = scripts/vpstree \ scripts/vrpm \ scripts/vserver \ scripts/vserver-copy \ + scripts/vcached \ + scripts/vuseradd \ + scripts/vuserdel \ scripts/vtop scripts_gen_PRGS = scripts/vps diff --git a/scripts/vcached b/scripts/vcached new file mode 100755 index 0000000..19e0dff --- /dev/null +++ b/scripts/vcached @@ -0,0 +1,102 @@ +#!/bin/bash +# +# vcached: VServer cache daemon +# +# Description: A daemon that periodically preallocates vservers and stores +# them in a cache. Preallocated vservers from the cache may be then used to +# instantiate real vservers. Requires that /var/run/vcached.pid does not +# exist on startup. Should start/stop/restart from /etc/init.d. Can also be +# run periodically with -s from /etc/cron.d. +# +# Based on work by: +# +# Brent Chun - bnc@intel-research.net +# Tristan Koo - tristan.koo@intel-research.net +# William Wung - wungism@uclink.berkeley.edu +# +# Mark Huang +# Copyright (c) 2004 The Trustees of Princeton University (Trustees). +# +# $Id: vcached,v 1.9 2004/11/23 14:47:35 mlhuang Exp $ +# + +# get configuration +. /etc/vcached.conf + +# parse options +while getopts 'fdsl:' OPT ; do + case "$OPT" in + f) foreground=1 ;; + d) debug=1 ;; + s) single=1 ;; + l) exec 1>>$OPTARG ; exec 2>>$OPTARG ;; + esac +done + +# check if we are already running +if [ -f $pidfile ] ; then + echo "vcached(`cat $pidfile`) already running" + exit 1 +fi + +# daemonize +if [ $foreground -eq 0 ] ; then + nohup setsid nice -n $nice -- $0 $* -f -l $logfile >/dev/null 2>&1 >$logfile ; exec 2>>$logfile" HUP +echo $$ > $pidfile + +: ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars} +test -e "$UTIL_VSERVER_VARS" || { + echo "Can not find util-vserver installation; aborting..." + exit 1 +} +. "$UTIL_VSERVER_VARS" + +# make sure barrier bit is set on /vservers to prevent chroot() escapes +$PKGLIBDIR/setattr --barrier $VROOTDIR + +# take out the trash +rm -rf "$VROOTDIR/.vtmp" + +mkdir -p "$VROOTDIR/.vcache" +mkdir -p "$VROOTDIR/.vtmp" + +# loop forever +while : ; do + [ $debug -ne 0 ] && echo "$(date) Checking the cache" + for i in $(seq 0 $(($slots - 1))) ; do + if [ ! -d "$VROOTDIR/.vcache/v$i" ] ; then + echo "$(date) Caching v$i" + # build image in .vtmp + TMP=$(mktemp -d "$VROOTDIR/.vtmp/v$i.XXXXXX") + "$PKGLIBDIR/vbuild" "$VROOTDIR/vserver-reference" "$TMP" + RETVAL=$? + # move it to .vcache when complete + if [ $RETVAL -eq 0 ] ; then + # sanity check + vnewsize=$(du -s "$TMP" | awk "{ print \$1 }") + vrefsize=$(du -s "$VROOTDIR/vserver-reference" | awk "{ print \$1 }") + if [ $vnewsize -lt $vrefsize ] ; then + echo "WARNING: Unexpected for 'du -s $VROOTDIR/$NAME'=$vnewsize to be less than 'du -s $VROOTDIR/vserver-reference'=$vrefsize" + fi + + mv "$TMP" "$VROOTDIR/.vcache/v$i" + echo "$(date) v$i ready" + else + echo "$(date) Error $RETVAL building v$i" + rm -rf "$TMP" + fi + fi + done + # just run once + if [ $single -ne 0 ] ; then + break + fi + [ $debug -ne 0 ] && echo "$(date) Sleeping for $period seconds" + sleep $period +done diff --git a/scripts/vserver b/scripts/vserver index 79e553f..7aae608 100755 --- a/scripts/vserver +++ b/scripts/vserver @@ -30,7 +30,8 @@ USR_SBIN=$SBINDIR USR_LIB_VSERVER=$PKGLIBDIR VSERVER_CMD=$USR_SBIN/vserver -CHBIND_CMD=$USR_SBIN/chbind +WAITFOR_CMD="waitfor 60" +VINIT_CMD=/etc/rc.vinit CHCONTEXT_CMD=$USR_SBIN/chcontext SAVE_S_CONTEXT_CMD=$USR_LIB_VSERVER/save_s_context CAPCHROOT_CMD=$USR_LIB_VSERVER/capchroot @@ -74,114 +75,6 @@ testperm() echo fi } -# Set the IP alias needed by a vserver -ifconfig_iproot() -{ - if [ "$NODEV" = "" -a "$IPROOT" != "" -a "$IPROOT" != "0.0.0.0" -a "$IPROOT" != "ALL" ] ;then - # A vserver may have more than one IP - # The first alias is dev:vserver - # and the other are dev:vserver1,2,3 and so on - # An IP may hold the device. The following is valid - # IPROOT="1.2.4.5 eth1:1.2.3.5" - # IPROOTDEV=eth0 - # The first IP 1.2.3.4 will go on eth0 and the other on eth1 - # VLAN devices are also supported (eth0.231 for vlan 231) - SUFFIX= - for oneip in $IPROOT - do - IPDEV=$IPROOTDEV - MASK=$IPROOTMASK - BCAST=$IPROOTBCAST - # Split the device and IP if available - case $oneip in - *:*) - eval `echo $oneip | tr : ' ' | (read dev ip; echo oneip=$ip; echo IPDEV=$dev)` - ;; - esac - # Split the IP and the netmask if available - case $oneip in - */*) - eval `echo $oneip | tr / ' ' | (read ip msk; echo oneip=$ip; echo MASK=$msk)` - eval `$USR_LIB_VSERVER/ifspec "" "$oneip" "$MASK" "$BCAST"` - ;; - esac - if [ "$IPDEV" != "" ] ; then - case $IPDEV in - *.*) - if [ ! -f /proc/net/vlan/$IPDEV ] ; then - /sbin/vconfig add `echo $IPDEV | tr . ' '` - # Put a dummy IP - /sbin/ifconfig $IPDEV 127.0.0.1 - fi - ;; - esac - # Compute the default netmask, if missing - eval `$USR_LIB_VSERVER/ifspec $IPDEV "$oneip" "$MASK" "$BCAST"` - IPROOTMASK=$NETMASK - IPROOTBCAST=$BCAST - #echo /sbin/ifconfig $IPDEV:$1$SUFFIX $oneip netmask $IPROOTMASK broadcast $IPROOTBCAST - /sbin/ifconfig $IPDEV:$1$SUFFIX $oneip netmask $IPROOTMASK broadcast $IPROOTBCAST - fi - if [ "$SUFFIX" = "" ] ; then - SUFFIX=1 - else - SUFFIX=`expr $SUFFIX + 1` - fi - done - fi - if [ "$IPROOTBCAST" = "" ] ; then - IPROOTBCAST=255.255.255.255 - fi -} -ifconfig_iproot_off() -{ - if [ "$NODEV" = "" -a "$IPROOT" != "" -a "$IPROOT" != "0.0.0.0" -a "$IPROOT" != "ALL" -a "$IPROOTDEV" != "" ] ;then - SUFFIX= - for oneip in $IPROOT - do - IPDEV=$IPROOTDEV - # Split the device and IP if available - case $oneip in - *:*) - eval `echo $oneip | tr : ' ' | (read dev ip; echo IPDEV=$dev)` - ;; - esac - /sbin/ifconfig $IPDEV:$1$SUFFIX down 2>/dev/null - if [ "$SUFFIX" = "" ] ; then - SUFFIX=1 - else - SUFFIX=`expr $SUFFIX + 1` - fi - done - fi -} -# Split an IPROOT definition, trash the devices and -# compose a set of --ip option for chbind -setipopt(){ - RET= - IPS="$*" - if [ "$IPS" = "" ] ; then - IPS=0.0.0.0 - fi - if [ "$1" = "ALL" ] ; then - IPS=`$USR_LIB_VSERVER/listdevip` - fi - for oneip in $IPS - do - # Split the device and IP if available - case $oneip in - *:*) - eval `echo $oneip | tr : ' ' | (read dev ip; echo oneip=$ip)` - ;; - esac - #case $oneip in - #*/*) - # eval `echo $oneip | tr / ' ' | (read ip msk; echo oneip=$ip)` - # ;; - #esac - echo --ip $oneip - done -} # Extract the initial runlevel from the vserver inittab get_initdefault() @@ -202,6 +95,28 @@ readlastconf() export PROFILE . /etc/vservers/$1.conf } + +# Wait for a process to finish for $1 seconds. +waitfor() +{ + timeout=$1 + shift + # Background the process. + $@ & + # Wait for it to finish. + while [ $timeout -gt 0 ] ; do + sleep 1 + kill -0 $! 2>/dev/null || break + timeout=$(($timeout - 1)) + done + # Try nicely terminating it, then just kill it. + if [ $timeout -eq 0 ] ; then + kill -TERM $! && kill -0 $! 2>/dev/null && kill -KILL $! + fi + # Cleanup. + wait +} + usage() { echo vserver [ options ] server-name command ... @@ -224,10 +139,6 @@ usage() echo " status : Tells some information about a vserver" echo " chkconfig : It turns a server on or off in a vserver" echo - echo "--nodev : Do not configure the IP aliases of the vserver" - echo " Useful to enter a vserver without enabling its network" - echo " and avoiding conflicts with another copy of this vserver" - echo " running elsewhere" echo "--silent : No informative messages about vserver context and IP numbers" echo " Useful when you want to redirect the output" } @@ -248,15 +159,11 @@ calculateCaps() } SILENT= -NODEV= while true do if [ "$1" = "--silent" ] ; then SILENT=--silent shift - elif [ "$1" = "--nodev" ] ; then - NODEV=--nodev - shift else break fi @@ -395,7 +302,8 @@ S_FLAGS="lock nproc" # ULIMIT="-HS -u 200" # The example above, combined with the nproc S_FLAGS will limit the # vserver to a maximum of 200 processes -ULIMIT="-HS -u 1000" +#ULIMIT="-HS -u 1000" +ULIMIT="" # You can set various capabilities. By default, the vserver are run # with a limited set, so you can let root run in a vserver and not # worry about it. He can't take over the machine. In some cases @@ -443,15 +351,10 @@ elif [ "$2" = "start" ] ; then if ! $VSERVER_CMD $1 running then test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1 - IPROOT= - IPROOTMASK= - IPROOTBCAST= - IPROOTDEV= S_NICE= S_FLAGS= . /etc/vservers/$1.conf export PROFILE - ifconfig_iproot $1 cd $VROOTDIR/$1 || exit 1 if [ "$PROFILE" != "" ] ; then @@ -539,12 +442,14 @@ elif [ "$2" = "start" ] ; then # We switch to $VROOTDIR/$1 now, because after the # security context switch $VROOTDIR directory becomes a dead zone. cd $VROOTDIR/$1 - IPOPT=`setipopt $IPROOT` export PATH=$DEFAULTPATH - $NICECMD $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \ - $CHCONTEXT_CMD $SILENT $DISCONNECT $CAPS $FLAGS $CTXOPT $HOSTOPT $DOMAINOPT --secure \ - $SAVE_S_CONTEXT_CMD /var/run/vservers/$1.ctx \ - $CAPCHROOT_CMD $CHROOTOPT . $STARTCMD + # XXX execute /etc/rc.vinit first for backward compatibility + for CMD in "$VINIT_CMD $2" "$STARTCMD" ; do + $NICECMD \ + $CHCONTEXT_CMD $SILENT $DISCONNECT $CAPS $FLAGS $CTXOPT $HOSTOPT $DOMAINOPT --secure \ + $SAVE_S_CONTEXT_CMD /var/run/vservers/$1.ctx \ + $CAPCHROOT_CMD $CHROOTOPT . $CMD + done sleep 2 test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-start $1 fi @@ -575,17 +480,12 @@ elif [ "$2" = "status" ] ; then fi elif [ "$2" = "stop" ] ; then echo Stopping the virtual server $1 - IPROOT= - IPROOTMASK= - IPROOTBCAST= - IPROOTDEV= CAPS= IS_MINIT= readlastconf $1 if $VSERVER_CMD $1 running then test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-stop $1 - ifconfig_iproot $1 cd $VROOTDIR/$1 mountproc $VROOTDIR/$1 # The fakeinit flag tell us how to turn off the server @@ -625,11 +525,12 @@ elif [ "$2" = "stop" ] ; then calculateCaps $S_CAPS cd $VROOTDIR/$1 - IPOPT=`setipopt $IPROOT` export PATH=$DEFAULTPATH - $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \ - $CHCONTEXT_CMD $SILENT $CAPS --secure --ctx $S_CONTEXT \ - $CAPCHROOT_CMD . $STOPCMD + # XXX execute /etc/rc.vinit first for backward compatibility + for CMD in "$VINIT_CMD $2" "$STOPCMD" ; do + $WAITFOR_CMD $CHCONTEXT_CMD $SILENT $CAPS --secure --ctx $S_CONTEXT \ + $CAPCHROOT_CMD . $CMD + done if test "$IS_MINIT"; then echo "Waiting for minit finish-signal" @@ -641,8 +542,7 @@ elif [ "$2" = "stop" ] ; then fi echo Killing all processes - $CHBIND_CMD --silent $IPOPT --bcast $IPROOTBCAST \ - $CHCONTEXT_CMD $CAPS --secure --silent --ctx $S_CONTEXT \ + $CHCONTEXT_CMD $CAPS --secure --silent --ctx $S_CONTEXT \ $VSERVERKILLALL_CMD fi # We umount anyway, because "enter" establish the mount @@ -650,7 +550,6 @@ elif [ "$2" = "stop" ] ; then umountproc $VROOTDIR/$1 cd / test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-stop $1 - ifconfig_iproot_off $1 elif [ "$2" = "restart" ] ; then if $0 $1 running then @@ -667,14 +566,9 @@ elif [ "$2" = "suexec" ] ; then echo "vserver vserver-name suexec user command [ args ... ]" >&2 exit 1 else - IPROOT= - IPROOTMASK= - IPROOTBCAST= - IPROOTDEV= readlastconf $1 . /etc/vservers/$1.conf cd $VROOTDIR/$1 - ifconfig_iproot $1 mountproc $VROOTDIR/$1 PS1="[\u@vserver:$1 \W]" export PS1 @@ -718,10 +612,8 @@ elif [ "$2" = "suexec" ] ; then then . /var/run/vservers/$VSERVER.ctx cd $VROOTDIR/$VSERVER - IPOPT=`setipopt $IPROOT` export PATH=$DEFAULTPATH - exec $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \ - $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure --ctx $S_CONTEXT \ + exec $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure --ctx $S_CONTEXT \ $CAPCHROOT_CMD --suid $USERID . "$@" else test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1 @@ -740,10 +632,8 @@ elif [ "$2" = "suexec" ] ; then fi mkdir -p /var/run/vservers cd $VROOTDIR/$VSERVER - IPOPT=`setipopt $IPROOT` export PATH=$DEFAULTPATH - exec $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \ - $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure $CTXOPT $HOSTOPT $DOMAINOPT \ + exec $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure $CTXOPT $HOSTOPT $DOMAINOPT \ $SAVE_S_CONTEXT_CMD /var/run/vservers/$VSERVER.ctx \ $CAPCHROOT_CMD --suid $USERID $CHROOTOPT . "$@" fi @@ -751,15 +641,15 @@ elif [ "$2" = "suexec" ] ; then elif [ "$2" = "exec" ] ; then VSERV=$1 shift; shift - exec $0 $NODEV $SILENT $VSERV suexec root "$@" + exec $0 $SILENT $VSERV suexec root "$@" elif [ "$2" = "enter" ] ; then testperm $1 - exec $0 $NODEV $SILENT $1 exec /bin/bash -login + exec $0 $SILENT $1 exec /bin/bash -login elif [ "$2" = "service" ] ; then VSERVER=$1 shift shift - exec $0 $NODEV $SILENT $VSERVER exec /sbin/service "$@" + exec $0 $SILENT $VSERVER exec /sbin/service "$@" elif [ "$2" = "chkconfig" ] ; then VSERVER=$1 LEVELS=() diff --git a/scripts/vuseradd b/scripts/vuseradd new file mode 100755 index 0000000..2be0ac9 --- /dev/null +++ b/scripts/vuseradd @@ -0,0 +1,98 @@ +#!/bin/bash +# +# useradd(8) wrapper for vservers +# +# Copyright (c) 2004 The Trustees of Princeton University (Trustees). +# +# $Id: vuseradd,v 1.21 2005/04/26 21:23:28 mlhuang Exp $ +# + +: ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars} +test -e "$UTIL_VSERVER_VARS" || { + echo "Can not find util-vserver installation; aborting..." + exit 1 +} +. "$UTIL_VSERVER_VARS" + +usage() +{ + echo "usage: $0 name" + exit 1 +} + +[ -z "$1" ] && usage +[ "$1" == "--static" ] && { STATIC=yes; shift; } +NAME=$1 + +# add slices group if not already present +groupadd slices 2>/dev/null || : + +# add user +[ -z "$STATIC" ] && useradd -g slices -s /bin/vsh $NAME + +# openssh-server 3.8 and above refuse login for "locked" accounts +sed -i -e "s/$NAME:\!\!:\(.*\)/$NAME:*:\1/" /etc/shadow + +USERID=`id -u $NAME` +GROUPID=`id -g $NAME` +GROUPNAME=`id -gn $NAME` + +# create vserver configuration file +if [ ! -f /etc/vservers/$NAME.conf ] ; then + sed \ + -e "s/.*S_CONTEXT=.*/S_CONTEXT=$USERID/" \ + -e "s/.*ONBOOT=.*/ONBOOT=yes/" \ + < $PKGLIBDIR/sample.conf \ + > /etc/vservers/$NAME.conf +fi + +if [ ! -d "$VROOTDIR/$NAME" ] ; then + # check the cache + shopt -s nullglob + for i in "$VROOTDIR/.vcache/"* ; do + [ -d "$i" ] && mv "$i" "$VROOTDIR/$NAME" && break + done + # build vserver + if [ ! -d "$VROOTDIR/$NAME" ] ; then + # build image in .vtmp + TMP=$(mktemp -d "$VROOTDIR/.vtmp/$NAME.XXXXXX") + "$PKGLIBDIR/vbuild" "$VROOTDIR/vserver-reference" "$TMP" + RETVAL=$? + # move it to .vcache when complete + if [ $RETVAL -ne 0 ] ; then + echo "Error $RETVAL building $VROOTDIR/$NAME" + rm -rf "$TMP" /etc/vservers/$NAME.conf /var/run/vservers/$NAME.ctx + userdel -r $NAME + exit $RETVAL + else + # sanity check + vnewsize=$(du -s "$TMP" | awk "{ print \$1 }") + vrefsize=$(du -s "$VROOTDIR/vserver-reference" | awk "{ print \$1 }") + if [ $vnewsize -lt $vrefsize ] ; then + echo "WARNING: Unexpected for 'du -s $VROOTDIR/$NAME'=$vnewsize to be less than 'du -s $VROOTDIR/vserver-reference'=$vrefsize" + fi + + mv "$TMP" "$VROOTDIR/$NAME" + fi + fi +fi + +if [ -d "$VROOTDIR/$NAME" ] ; then + # fix permissions + chmod 755 "$VROOTDIR/$NAME" + + # add user in vserver + vserver $NAME suexec root groupadd -g $GROUPID $GROUPNAME + vserver $NAME suexec root useradd -u $USERID -g $GROUPID -p '' $NAME + + # add an unrestricted entry to /etc/sudoers file + if [ -f "$VROOTDIR/$NAME/etc/sudoers" ] && \ + ! grep -q "^$NAME" "$VROOTDIR/$NAME/etc/sudoers" ; then + echo "$NAME ALL=(ALL) ALL" >> "$VROOTDIR/$NAME/etc/sudoers" + fi +fi + +# turn resource management on for vserver $NAME +service resman start $NAME +# XXX - resman doesn't print a trailing newline +echo diff --git a/scripts/vuserdel b/scripts/vuserdel new file mode 100755 index 0000000..24d4bd6 --- /dev/null +++ b/scripts/vuserdel @@ -0,0 +1,63 @@ +#!/bin/bash +# +# userdel(8) wrapper for vservers +# +# Copyright (c) 2004 The Trustees of Princeton University (Trustees). +# +# $Id: vuserdel,v 1.7 2005/04/07 19:37:25 smuir Exp $ +# + +: ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars} +test -e "$UTIL_VSERVER_VARS" || { + echo "Can not find util-vserver installation; aborting..." + exit 1 +} +. "$UTIL_VSERVER_VARS" + +usage() +{ + echo "usage: $0 name" + exit 1 +} + +[ -z "$1" ] && usage +[ "$1" == "--static" ] && { STATIC=yes; shift; } +NAME=$1 + +# read config file to get context ID +. /etc/vservers/$NAME.conf +CTX=$S_CONTEXT + +# don't bother stopping gracefully, just kill all the processes +$SBINDIR/chcontext --silent --secure --ctx $CTX $PKGLIBDIR/vserverkillall + +# unmount any directories in vserver that are mount points +for d in `sed -ne "s%^[^ ]* \($VROOTDIR/$NAME/[^ ]*\) .*%\1%p" /proc/mounts` +do + # use echo -e to turn escaped whitespace back into regular chars + # be careful about embedded backquotes here (i think we're safe) + dir=`echo -e "$d"` + echo "unmounting $dir" + umount -l "$dir" +done + +# turn resource management off for vserver $NAME +service resman stop $NAME +# XXX - resman doesn't print a trailing newline +echo + +# delete user +[ -z "$STATIC" ] && userdel -r $NAME + +# remove vserver configuration file +rm -f /etc/vservers/$NAME.conf + +# remove vserver profile +rm -f /var/run/vservers/$NAME.ctx + +# destroy vserver +if [ -d $VROOTDIR/$NAME ] ; then + TMP=$(mktemp -d "$VROOTDIR/.vtmp/$NAME.XXXXXX") + mv "$VROOTDIR/$NAME" "$TMP" + rm -rf "$TMP" +fi diff --git a/src/Makefile-files b/src/Makefile-files index 2d2586e..695aea8 100644 --- a/src/Makefile-files +++ b/src/Makefile-files @@ -39,8 +39,10 @@ src_sbin_PRGS = src/chbind \ src/chcontext \ src/rebootmgr \ src/reducecap \ - src/vlimit \ src/vdu \ + src/vsh \ + src/vdlimit \ + src/vlimit \ src/vfiles \ src/vkill \ src/vserver-stat @@ -76,6 +78,12 @@ src_vkill_SOURCES = src/vkill.c src_vkill_LDADD = lib/libvserver.a src_vkill_CPPFLAGS = $(AM_CPPFLAGS) -DLEGACYDIR=\"$(legacydir)\" +src_vsh_SOURCES = src/vsh.c +src_vsh_LDADD = lib/libvserver.a + +src_vdlimit_SOURCES = src/vdlimit.c +src_vdlimit_LDADD = lib/libvserver.a + src_showattr_SOURCES = src/showattr.c src_showperm_SOURCES = src/showperm.c src_vbuild_SOURCES = src/vbuild.cc src/vutil.cc diff --git a/src/chcontext.c b/src/chcontext.c index 236e0cc..1b5275a 100644 --- a/src/chcontext.c +++ b/src/chcontext.c @@ -122,6 +122,7 @@ int main (int argc, char *argv[]) unsigned remove_cap = 0; unsigned add_cap = 0; unsigned long secure = (1< excldirs; -static int ext2flags = EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL; +static int ext2flags = EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL; static struct { int nblink; int nbcopy; @@ -228,9 +228,9 @@ int main (int argc, char *argv[]) }else if (strcmp(arg,"--noflags")==0){ ext2flags = 0; }else if (strcmp(arg,"--immutable")==0){ - ext2flags |= EXT2_IMMUTABLE_FILE_FL; + ext2flags |= EXT2_IMMUTABLE_FL; }else if (strcmp(arg,"--immutable-mayunlink")==0){ - ext2flags |= EXT2_IMMUTABLE_LINK_FL; + ext2flags |= EXT2_IUNLINK_FL; }else if (strcmp(arg,"--excldir")==0){ i++; excldirs.push_back (EXCLDIR(argv[i])); diff --git a/src/vdu.c b/src/vdu.c index 55f6082..b6cfc59 100644 --- a/src/vdu.c +++ b/src/vdu.c @@ -1,4 +1,4 @@ -// $Id: vdu.c,v 1.1 2003/09/29 22:01:57 ensc Exp $ +// $Id: vdu-new.c,v 1.2 2004/08/17 14:44:14 mef-pl_kernel Exp $ // Copyright (C) 2003 Enrico Scholz // based on vdu.cc by Jacques Gelinas @@ -17,6 +17,8 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#define _LARGEFILE64_SOURCE + #include #include #include @@ -26,89 +28,229 @@ #include #include #include +#include + +#include + +#include "vdu.h" + +HashTable tbl; + +static int // boolean +INOPut(PHashTable tbl, ino64_t* key, struct stat64 **val){ + return Put(tbl, key, val); +} __extension__ typedef long long longlong; +//__extension__ typedef long longlong; + +static longlong inodes; +static longlong blocks; +static longlong size; + +static short verbose = 0; + +static inline void warning(char *s) { + fprintf(stderr,"%s (%s)\n",s,strerror(errno)); +} + +void panic(char *s) { + warning(s); + exit(2); +} -static int vdu_onedir (char const *path, longlong *size) +static void vdu_onedir (char const *path) { - int ret = -1; - int dirfd = open (path,O_RDONLY); // A handle to speed up - // chdir - if (dirfd == -1){ - fprintf (stderr,"Can't open directory %s (%s)\n",path - ,strerror(errno)); - }else{ - DIR *dir; - - fchdir (dirfd); - dir = opendir ("."); - if (dir == NULL){ - fprintf (stderr,"Can't open (opendir) directory %s (%s)\n",path - ,strerror(errno)); - }else{ - struct stat dirst; - struct dirent *ent; - longlong dirsize = 0; - - ret = 0; - lstat (".",&dirst); - while ((ent=readdir(dir))!=NULL){ - struct stat st; - if (lstat(ent->d_name,&st)==-1){ - fprintf (stderr,"Can't stat %s/%s (%s)\n",path - ,ent->d_name,strerror(errno)); - ret = -1; - break; - }else if (S_ISREG(st.st_mode)){ - if (st.st_nlink == 1){ - dirsize += st.st_size; - } - }else if (S_ISDIR(st.st_mode) && st.st_dev == dirst.st_dev){ - if (strcmp(ent->d_name,".")!=0 - && strcmp(ent->d_name,"..")!=0){ - char *tmp = malloc(strlen(path) + strlen(ent->d_name) + 2); - if (tmp==0) ret=-1; - else { - strcpy(tmp, path); - strcat(tmp, "/"); - strcat(tmp, ent->d_name); - ret = vdu_onedir(tmp,&dirsize); - free(tmp); - fchdir (dirfd); - } - } - } - } - closedir (dir); - *size += dirsize; + char const *foo = path; + struct stat64 dirst, st; + struct dirent *ent; + char *name; + DIR *dir; + int dirfd; + longlong dirsize, dirinodes, dirblocks; + + dirsize = dirinodes = dirblocks = 0; + + // A handle to speed up chdir + if ((dirfd = open (path,O_RDONLY)) == -1) { + fprintf (stderr,"Can't open directory %s\n",path); + panic("open failed"); + } + + if (fchdir (dirfd) == -1) { + fprintf (stderr,"Can't fchdir directory %s\n",path); + panic("fchdir failed"); + } + + if (fstat64 (dirfd,&dirst) != 0) { + fprintf (stderr,"Can't lstat directory %s\n",path); + panic("lstat failed"); + } + + if ((dir = opendir (".")) == NULL) { + fprintf (stderr,"Can't open (opendir) directory %s\n",path); + panic("opendir failed"); + } + + + /* Walk the directory entries and compute the sum of inodes, + * blocks, and disk space used. This code will recursively descend + * down the directory structure. + */ + + while ((ent=readdir(dir))!=NULL){ + if (lstat64(ent->d_name,&st)==-1){ + fprintf (stderr,"Can't stat %s/%s\n",path,ent->d_name); + warning("lstat failed"); + continue; + } + + dirinodes ++; + + if (S_ISREG(st.st_mode)){ + if (st.st_nlink > 1){ + struct stat64 *val; + int nlink; + + /* Check hash table if we've seen this inode + * before. Note that the hash maintains a + * (inode,struct stat) key value pair. + */ + + val = &st; + + (void) INOPut(&tbl,&st.st_ino,&val); + + /* Note that after the INOPut call "val" refers to the + * value entry in the hash table --- not &st. This + * means that if the inode has been put into the hash + * table before, val will refer to the first st that + * was put into the hashtable. Otherwise, if it is + * the first time it is put into the hash table, then + * val will be equal to this &st. + */ + nlink = val->st_nlink; + nlink --; + + /* val refers to value in hash tbale */ + if (nlink == 0) { + + /* We saw all hard links to this particular inode + * as part of this sweep of vdu. So account for + * the size and blocks required by the file. + */ + + dirsize += val->st_size; + dirblocks += val->st_blocks; + + /* Do not delete the (ino,val) tuple from the tbl, + * as we need to handle the case when we are + * double counting a file due to a bind mount. + */ + val->st_nlink = 0; + + } else if (nlink > 0) { + val->st_nlink = nlink; + } else /* if(nlink < 0) */ { + /* We get here when we are double counting nlinks + due a bind mount. */ + + /* DO NOTHING */ + } + } else { + dirsize += st.st_size; + dirblocks += st.st_blocks; + } + + } else if (S_ISDIR(st.st_mode)) { + if ((st.st_dev == dirst.st_dev) && + (strcmp(ent->d_name,".")!=0) && + (strcmp(ent->d_name,"..")!=0)) { + + dirsize += st.st_size; + dirblocks += st.st_blocks; + + name = strdup(ent->d_name); + if (name==0) { + panic("Out of memory\n"); } - close (dirfd); + vdu_onedir(name); + free(name); + fchdir(dirfd); + } + } else { + // dirsize += st.st_size; + // dirblocks += st.st_blocks; } - return ret; + } + closedir (dir); + close (dirfd); + if (verbose) + printf("%16lld %16lld %16lld %s\n",dirinodes, dirblocks, dirsize,foo); + inodes += dirinodes; + blocks += dirblocks; + size += dirsize; } -int main (int argc, char *argv[]) +static void +Count(ino64_t* key, struct stat64* val) { + if(val->st_nlink) { + blocks += val->st_blocks; + size += val->st_size; + printf("ino=%16lld nlink=%d\n",val->st_ino, val->st_nlink); + } +} + +int +main (int argc, char **argv) { - int ret = -1; - if (argc < 2){ - fprintf (stderr,"vdu version %s\n",VERSION); - fprintf (stderr,"vdu directory ...\n\n"); - fprintf (stderr - ,"Compute the size of a directory tree, ignoring files\n" - "with more than one link.\n"); - }else{ - int i; - - ret = 0; - for (i=1; i> 10; - printf ("%s\t%ldK\n",argv[i],ksize); - } + int startdir, i; + + if (argc < 2){ + fprintf (stderr,"vdu version %s\n",VERSION); + fprintf (stderr,"vdu directory ...\n\n"); + fprintf (stderr,"Compute the size of a directory tree.\n"); + }else{ + if ((startdir = open (".",O_RDONLY)) == -1) { + fprintf (stderr,"Can't open current working directory\n"); + panic("open failed"); } - return ret; + + /* hash table support for hard link count */ + (void) Init(&tbl,0,0); + + for (i=1; i>1, + size, + argv[i]); + if (fchdir (startdir) == -1) { + panic("fchdir failed"); + } + } + + if(0) { + /* show size & blocks for files with nlinks from outside of dir */ + inodes = blocks = size = 0; + Iterate(&tbl,Count); + printf("%16lld %16lld %16lld NOT COUNTED\n", + inodes, + blocks, + size); + } + + // Dispose(&tbl); this fails to delete all entries + close(startdir); + } + return 0; } +/* + * Local variables: + * c-basic-offset: 4 + * End: + */ diff --git a/src/vdu.h b/src/vdu.h new file mode 100644 index 0000000..5405a59 --- /dev/null +++ b/src/vdu.h @@ -0,0 +1,374 @@ +#ifndef __VDU_H +#define __VDU_H + +typedef ino64_t KEY; +typedef KEY *PKEY; +typedef struct stat64 VAL; +typedef VAL *PVAL; + +static inline +unsigned int +HASH(PKEY key){ + return (int) *key; +} + +static inline +unsigned int // boolean +EQUAL(PKEY key1, PKEY key2){ + return *key1 == *key2; +} + +#ifndef MIN +#define MIN(x,y) (((x)<(y))?(x):(y)) +#endif // MIN + +#ifndef MAX +#define MAX(x,y) (((x)>(y))?(x):(y)) +#endif // MAX + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +// hash table support for efficient lookup of duplicate inodes */ +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +#define Multiplier (0x9e3779b9) +#define MaxLogBuckets (((sizeof (unsigned long))*8) - 2) +#define MaxBuckets (1< 2*MinDensity; *) +// to avoid excessive probes, we must try to keep MaxDensity low. *) +// Divide by 100 before using +#define MaxDensity 75 /* max numEntries/NUMBER(buckets) */ +#define MinDensity 20 /* min numEntries/NUMBER(buckets) */ +#define IdealDensity 50 +#define BITSIZE(x) (sizeof(x)*8) + +#define NEW(type,num) ((type*)malloc(sizeof(type)*num)) +#define DISPOSE(ptr) (free((void*)ptr)) + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +// Generic Hash Entry Type +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +typedef struct VoidList { + struct VoidList *tail; +} VoidList, *PVoidList; + +typedef struct HashTable { + PVoidList *buckets; + unsigned int numBuckets; // number of buckets + unsigned int minLogBuckets; // minimum value for Log_2(initial size) + unsigned int logBuckets; // CEILING(Log2(NUMBER(buckets^))) + unsigned int maxEntries; // maximum number of entries + unsigned int minEntries; // minimum number of entries + unsigned int numEntries; // current num of entries in table + PVoidList cache; // cache of removed elements + int cacheSize; // current size of the cache + int maxCacheSize; // maximum size, -1 means unbounded, 0 no cache +} HashTable, *PHashTable; + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +// Hash Prototypes +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +PHashTable +Init(PHashTable tbl, unsigned int n, int maxCacheSize); + +void +Dispose(PHashTable tbl); + +unsigned int +Log_2(unsigned int x); + +void +NewBuckets(PHashTable tbl, unsigned int logBuckets); + +// +// Generic Hash Table support +// + +PHashTable +Init(PHashTable tbl, unsigned int n, int maxCacheSize){ + int idealBuckets; + int minBuckets; + + idealBuckets = MIN(((n*100)/IdealDensity),MaxBuckets); + minBuckets = MAX(MinBuckets, idealBuckets); + tbl->minLogBuckets = Log_2(minBuckets); + + NewBuckets(tbl, tbl->minLogBuckets); + tbl->numEntries = 0; + tbl->maxCacheSize = maxCacheSize; + tbl->cacheSize = 0; + tbl->cache = 0; + return tbl; +} // Init() + + +// +// Internal procedures +// + +unsigned int +Log_2(unsigned int x){ + // return CEILING(LOG_2(x)) + unsigned int log = 0; + unsigned int n= 1; + + assert(x != 0); + while ((log < MaxLogBuckets) && (x > n)){ + log++; + n += n; + } + return log; +} // Log_2() + +void +NewBuckets(PHashTable tbl, unsigned int logBuckets){ + // Allocate "2^logBuckets" buckets. + unsigned int numBuckets = 1 << logBuckets; + PVoidList *b; + unsigned int i; + + tbl->buckets = NEW(PVoidList, numBuckets); + tbl->numBuckets = numBuckets; + b = tbl->buckets; + + for (i=0; inumBuckets; i++){ + b[i] = NULL; + } + tbl->logBuckets = logBuckets; + tbl->maxEntries = MaxDensity * numBuckets / 100; + tbl->minEntries = MinDensity * numBuckets / 100; +} // NewBuckets() + +#ifndef NULL +#define NULL (void*)0 +#endif // !NULL + +#ifndef TRUE +#define TRUE 1 +#endif // !TRUE + +#ifndef FALSE +#define FALSE 0 +#endif // !FALSE + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +// Type specific hash entry +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +typedef struct EntryList { + struct EntryList *tail; + KEY key; + VAL val; +}EntryList, *PEntryList; + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +// Type specific Hash implementation functions +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +static +void +Rehash(PHashTable tbl, unsigned int logBuckets) { + // Reallocate "2^logBuckets" buckets, and rehash the entries into + // the new table. + + PVoidList *oldBucketPointer; + PEntryList *ob, obi; + PEntryList *nb, *nbh; + PEntryList that, tail; + unsigned int index; + unsigned int i; + unsigned int oldNumBuckets; + + return; + assert(logBuckets <= MaxLogBuckets); + assert(logBuckets >= tbl->minLogBuckets); + oldBucketPointer = tbl->buckets; + ob = (PEntryList*)tbl->buckets; + oldNumBuckets = tbl->numBuckets; + + NewBuckets(tbl, logBuckets); + nb = (PEntryList*)tbl->buckets; + + for(i=0;ikey))*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets); + nbh = &(nb[index]); + tail = that->tail; + that->tail = *nbh; + *nbh = that; + that = tail; + } + } + DISPOSE (oldBucketPointer); +} + +static inline +unsigned int // boolean +Get(PHashTable tbl, PKEY key, PVAL *val){ + PEntryList that; + unsigned int index; + + index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets); + that = (PEntryList)tbl->buckets[index]; + while ((that != NULL) && !EQUAL(key,&(that->key))) { + that = that->tail; + } + if (that != NULL){ + *val = &that->val; + return TRUE; + } + else { + return FALSE; + } +} // Get() + +static inline +unsigned int // boolean +Put(PHashTable tbl, PKEY key, PVAL *val){ + PEntryList that; + PEntryList *first; + unsigned int index; + unsigned int res; + + index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets); + first = (PEntryList*)&(tbl->buckets[index]); + that = *first; + while ((that != NULL) && !EQUAL(key, &(that->key))){ + that = that->tail; + } + + // found an entry in the hash table given above key + if (that != NULL){ + res = TRUE; + } + else { + // check if we can reuse something from the cache + if (tbl->cache != NULL) { + that = (PEntryList)tbl->cache; + tbl->cache = (PVoidList)tbl->cache->tail; + that->key = *key; + that->tail = *first; + *first = that; + } + else { + that = NEW(EntryList,1); + that->key = *key; + that->tail = *first; + *first = that; + } + that->val = **val; + + tbl->numEntries++; + if ((tbl->logBuckets < MaxLogBuckets) + && (tbl->numEntries > tbl->maxEntries)){ + Rehash(tbl, tbl->logBuckets + 1); // too crowded + } + res = FALSE; + } + *val = &that->val; + return res; + +} // Put() + +static inline +int +Delete(PHashTable tbl,PKEY key){ + PEntryList that, prev; + PEntryList *first; + unsigned int index; + + index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets); + first = (PEntryList*)&(tbl->buckets[index]); + that = *first; + prev = NULL; + + while ((that != NULL) && !EQUAL(key, &(that->key))){ + prev = that; + that = that->tail; + } + if (that != NULL) { + if (prev == NULL) { + *first = that->tail; + } + else { + prev->tail = that->tail; + } + if ((tbl->maxCacheSize == -1)||(tbl->cacheSize < tbl->maxCacheSize)) { + that->tail = (PEntryList)tbl->cache; + tbl->cache = (PVoidList)that; + tbl->cacheSize++; + } + else { + DISPOSE (that); + } + tbl->numEntries--; + if (tbl->maxCacheSize == 0) { + if ((tbl->logBuckets > tbl->minLogBuckets) + && (tbl->numEntries < tbl->minEntries)) { + Rehash(tbl, tbl->logBuckets - 1); // too sparse + } + } + return TRUE; + } + else { + return FALSE; + } +} // Delete() + +typedef void (*callback)(PKEY key, PVAL val); + +void +Iterate(PHashTable tbl, callback fn) +{ + PVoidList that; + unsigned int i; + + for(i=0;inumBuckets;i++) { + that = tbl->buckets[i]; + while ( that != (PVoidList)0 ) { + PEntryList entry = (PEntryList)that; + fn(&entry->key,&entry->val); + that = that->tail; + } + } +} + +void +Dispose(PHashTable tbl) +{ + PVoidList that, next; + unsigned int i; + + for(i=0;inumBuckets;i++) { + that = tbl->buckets[i]; + while( that != NULL) { + next = that->tail; + DISPOSE (that); + tbl->numEntries--; + that = next; + } + } + DISPOSE(tbl->buckets); + assert(tbl->numEntries = 0); +} // Dispose; + + + +#endif // __VDU_H diff --git a/src/vlimit.c b/src/vlimit.c index 44fe511..6fd955b 100644 --- a/src/vlimit.c +++ b/src/vlimit.c @@ -195,7 +195,7 @@ int main (int argc, char *argv[]) if (set_mask & 1) limits[id].min = val; if (set_mask & 2) limits[id].soft = val; - if (set_mask & 4) limits[id].soft = val; + if (set_mask & 4) limits[id].hard = val; lim_mask |= (1< + * + * Copyright (c) 2004 The Trustees of Princeton University (Trustees). + * + * vsh is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * vsh is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Poptop; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#include "compat.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//-------------------------------------------------------------------- +#include "linuxcaps.h" +#include "vserver.h" + +/* Null byte made explicit */ +#define NULLBYTE_SIZE 1 + +/* Base for all vserver roots for chroot */ +#define VSERVER_ROOT_BASE "/vservers" + +/* Change to root:root (before entering new context) */ +static int setuidgid_root() +{ + if (setgid(0) < 0) { + fprintf(stderr, "setgid error\n"); + return -1; + } + if (setuid(0) < 0) { + fprintf(stderr, "setuid error\n"); + return -1; + } + return 0; +} + +static void compute_new_root(char *base, char **root, uid_t uid) +{ + int root_len; + struct passwd *pwd; + + if ((pwd = getpwuid(uid)) == NULL) { + perror("vserver: getpwuid error "); + exit(1); + } + + root_len = + strlen(base) + strlen("/") + + strlen(pwd->pw_name) + NULLBYTE_SIZE; + (*root) = (char *)malloc(root_len); + if ((*root) == NULL) { + perror("vserver: malloc error "); + exit(1); + } + + sprintf((*root), "%s/%s", base, pwd->pw_name); + (*root)[root_len - 1] = '\0'; +} + +/* Example: sandbox_root = /vservers/bnc, relpath = /proc/1 */ +static int sandbox_file_exists(char *sandbox_root, char *relpath) +{ + struct stat stat_buf; + char *file; + int len, exists = 0; + + len = strlen(sandbox_root) + strlen(relpath) + NULLBYTE_SIZE; + if ((file = (char *)malloc(len)) == NULL) { + perror("vserver: malloc error "); + exit(1); + } + sprintf(file, "%s%s", sandbox_root, relpath); + file[len - 1] = '\0'; + if (stat(file, &stat_buf) == 0) { + exists = 1; + } + + + free(file); + return exists; +} + +static int proc_mounted(char *sandbox_root) +{ + return sandbox_file_exists(sandbox_root, "/proc/1"); +} + +static int devpts_mounted(char *sandbox_root) +{ + return sandbox_file_exists(sandbox_root, "/dev/pts/0"); +} + +static void mount_proc(char *sandbox_root,uid_t uid) +{ + char *source = "/proc"; + char *target; + int len; + + len = strlen(sandbox_root) + strlen("/") + strlen("proc") + NULLBYTE_SIZE; + if ((target = (char *)malloc(len)) == NULL) { + perror("vserver: malloc error "); + exit(1); + } + + sprintf(target, "%s/proc", sandbox_root); + target[len - 1] = '\0'; + if (!proc_mounted(sandbox_root)) + mount(source, target, "proc", MS_BIND | MS_RDONLY, NULL); + + free(target); +} + +static void mount_devpts(char *sandbox_root) +{ + char *source = "/dev/pts"; + char *target; + int len; + + len = strlen(sandbox_root) + strlen("/") + strlen("dev/pts") + NULLBYTE_SIZE; + if ((target = (char *)malloc(len)) == NULL) { + perror("vserver: malloc error "); + exit(1); + } + + sprintf(target, "%s/dev/pts", sandbox_root); + target[len - 1] = '\0'; + if (!devpts_mounted(sandbox_root)) + mount(source, target, "devpts", 0, NULL); + + free(target); +} + +static int sandbox_chroot(uid_t uid) +{ + char *sandbox_root = NULL; + + compute_new_root(VSERVER_ROOT_BASE,&sandbox_root, uid); + mount_proc(sandbox_root,uid); + mount_devpts(sandbox_root); + if (chroot(sandbox_root) < 0) { + fprintf(stderr,"vserver: chroot error (%s): ",sandbox_root); + perror(""); + exit(1); + } + if (chdir("/") < 0) { + perror("vserver: chdir error "); + exit(1); + } + return 0; +} + +#ifndef CAP_CONTEXT +# define CAP_CONTEXT 29 +#endif + +static struct { + const char *option; + int bit; +}tbcap[]={ + // The following capabilities are normally available + // to vservers administrator, but are place for + // completeness + {"CAP_CHOWN",CAP_CHOWN}, + {"CAP_DAC_OVERRIDE",CAP_DAC_OVERRIDE}, + {"CAP_DAC_READ_SEARCH",CAP_DAC_READ_SEARCH}, + {"CAP_FOWNER",CAP_FOWNER}, + {"CAP_FSETID",CAP_FSETID}, + {"CAP_KILL",CAP_KILL}, + {"CAP_SETGID",CAP_SETGID}, + {"CAP_SETUID",CAP_SETUID}, + {"CAP_SETPCAP",CAP_SETPCAP}, + {"CAP_SYS_TTY_CONFIG",CAP_SYS_TTY_CONFIG}, + {"CAP_LEASE",CAP_LEASE}, + {"CAP_SYS_CHROOT",CAP_SYS_CHROOT}, + + // Those capabilities are not normally available + // to vservers because they are not needed and + // may represent a security risk + {"CAP_LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE}, + {"CAP_NET_BIND_SERVICE",CAP_NET_BIND_SERVICE}, + {"CAP_NET_BROADCAST",CAP_NET_BROADCAST}, + {"CAP_NET_ADMIN", CAP_NET_ADMIN}, + {"CAP_NET_RAW", CAP_NET_RAW}, + {"CAP_IPC_LOCK", CAP_IPC_LOCK}, + {"CAP_IPC_OWNER", CAP_IPC_OWNER}, + {"CAP_SYS_MODULE",CAP_SYS_MODULE}, + {"CAP_SYS_RAWIO", CAP_SYS_RAWIO}, + {"CAP_SYS_PACCT", CAP_SYS_PACCT}, + {"CAP_SYS_ADMIN", CAP_SYS_ADMIN}, + {"CAP_SYS_BOOT", CAP_SYS_BOOT}, + {"CAP_SYS_NICE", CAP_SYS_NICE}, + {"CAP_SYS_RESOURCE",CAP_SYS_RESOURCE}, + {"CAP_SYS_TIME", CAP_SYS_TIME}, + {"CAP_MKNOD", CAP_MKNOD}, + {"CAP_CONTEXT", CAP_CONTEXT}, + {NULL,0} +}; + +#define VSERVERCONF "/etc/vservers/" +static unsigned get_remove_cap(char *name) { + FILE *fb; + unsigned remove_cap; + + char *vserverconf; + int vserverconflen; + + remove_cap = /* NOTE: keep in sync with chcontext.c */ + (1<pw_gid) < 0) { + perror("vserver: setgid error "); + exit(1); + } + + if (setuid(pwd->pw_uid) < 0) { + perror("vserver: setuid error "); + exit(1); + } + + if (chdir(pwd->pw_dir) < 0) { + perror("vserver: chdir error "); + exit(1); + } + + home_len = strlen("HOME=") + strlen(pwd->pw_dir) + NULLBYTE_SIZE; + logname_len = strlen("LOGNAME=") + strlen(username) + NULLBYTE_SIZE; + mail_len = strlen("MAIL=/var/spool/mail/") + strlen(username) + + NULLBYTE_SIZE; + shell_len = strlen("SHELL=") + strlen(pwd->pw_shell) + NULLBYTE_SIZE; + user_len = strlen("USER=") + strlen(username) + NULLBYTE_SIZE; + + home_env = (char *)malloc(home_len); + logname_env = (char *)malloc(logname_len); + mail_env = (char *)malloc(mail_len); + shell_env = (char *)malloc(shell_len); + user_env = (char *)malloc(user_len); + + if ((home_env == NULL) || + (logname_env == NULL) || + (mail_env == NULL) || + (shell_env == NULL) || + (user_env == NULL)) { + perror("vserver: malloc error "); + exit(1); + } + + sprintf(home_env, "HOME=%s", pwd->pw_dir); + sprintf(logname_env, "LOGNAME=%s", username); + sprintf(mail_env, "MAIL=/var/spool/mail/%s", username); + sprintf(shell_env, "SHELL=%s", pwd->pw_shell); + sprintf(user_env, "USER=%s", username); + + home_env[home_len - 1] = '\0'; + logname_env[logname_len - 1] = '\0'; + mail_env[mail_len - 1] = '\0'; + shell_env[shell_len - 1] = '\0'; + user_env[user_len - 1] = '\0'; + + envp[0] = home_env; + envp[1] = logname_env; + envp[2] = mail_env; + envp[3] = shell_env; + envp[4] = user_env; + envp[5] = 0; + + if ((putenv(home_env) < 0) || + (putenv(logname_env) < 0) || + (putenv(mail_env) < 0) || + (putenv(shell_env) < 0) || + (putenv(user_env) < 0)) { + perror("vserver: putenv error "); + exit(1); + } +} + +void slice_enter(char *context) +{ + struct passwd pwdd, *pwd = &pwdd, *result; + char *pwdBuffer; + long pwdBuffer_len; + unsigned remove_cap; + uid_t uid; + + pwdBuffer_len = sysconf(_SC_GETPW_R_SIZE_MAX); + if (pwdBuffer_len == -1) { + perror("vserver: _SC_GETPW_R_SIZE_MAX not defined "); + exit(1); + } + + pwdBuffer = (char*)malloc(pwdBuffer_len); + if (pwdBuffer == NULL) { + perror("vserver: malloc error "); + exit(1); + } + + errno = 0; + if ((getpwnam_r(context,pwd,pwdBuffer,pwdBuffer_len, &result) != 0) || (errno != 0)) { + fprintf(stderr,"vserver: getpwname(%s) failed",context); + perror(""); + exit(2); + } + + context = (char*)malloc(strlen(pwd->pw_name)+NULLBYTE_SIZE); + if (!context) { + perror("vserver: malloc failed"); + exit(2); + } + strcpy(context,pwd->pw_name); + + if (setuidgid_root() < 0) { /* For chroot, new_s_context */ + fprintf(stderr,"vserver: Could not setuid/setguid to root:root\n"); + exit(2); + } + + remove_cap = get_remove_cap(context); + + uid = pwd->pw_uid; + if (sandbox_chroot(uid) < 0) { + fprintf(stderr, "vserver: Could not chroot to vserver root\n"); + exit(2); + } + + if (sandbox_processes(uid, remove_cap) < 0) { + fprintf(stderr, "vserver: Could not sandbox processes in vserver\n"); + exit(2); + } +} + +//-------------------------------------------------------------------- + +#define DEFAULT_SHELL "/bin/sh" + +/* Exit statuses for programs like 'env' that exec other programs. + EXIT_FAILURE might not be 1, so use EXIT_FAIL in such programs. */ +enum +{ + EXIT_CANNOT_INVOKE = 126, + EXIT_ENOENT = 127 +}; + +int main(int argc, char **argv) +{ + struct passwd pwdd, *pwd = &pwdd, *result; + char *context, *username, *shell, *pwdBuffer; + long pwdBuffer_len; + uid_t uid; + int index, i; + + if (argv[0][0]=='-') + index = 1; + else + index = 0; + + uid = getuid(); + if ((pwd = getpwuid(uid)) == NULL) { + fprintf(stderr,"vsh: getpwnam error failed for %d\n",uid); + exit(1); + } + + context = (char*)strdup(pwd->pw_name); + if (!context) { + perror("vsh: strdup failed"); + exit(2); + } + + /* enter vserver "context" */ + slice_enter(context); + + /* Now run as username in this context. Note that for PlanetLab's + vserver configuration the context name also happens to be the + "default" username within the vserver context. + */ + username = context; + runas_slice_user(username); + + /* With the uid/gid appropriately set. Let's figure out what the + * shell in the vserver's /etc/passwd is for the given username. + */ + + pwdBuffer_len = sysconf(_SC_GETPW_R_SIZE_MAX); + if (pwdBuffer_len == -1) { + perror("vserver: _SC_GETPW_R_SIZE_MAX not defined "); + exit(1); + } + pwdBuffer = (char*)malloc(pwdBuffer_len); + if (pwdBuffer == NULL) { + perror("vserver: malloc error "); + exit(1); + } + + errno = 0; + if ((getpwnam_r(username,pwd,pwdBuffer,pwdBuffer_len, &result) != 0) || (errno != 0)) { + fprintf(stderr,"vsh: getpwnam error failed for %s\n",username); + exit(1); + } + + /* Make sure pw->pw_shell is non-NULL.*/ + if (pwd->pw_shell == NULL || pwd->pw_shell[0] == '\0') { + pwd->pw_shell = (char *) DEFAULT_SHELL; + } + + shell = (char *)strdup(pwd->pw_shell); + if (!shell) { + perror("vsh: strdup failed"); + exit(2); + } + + /* Check whether 'su' or 'sshd' invoked us as a login shell or + not; did this above when testing argv[0]=='-'. + */ + argv[0] = shell; + if (index == 1) { + char **args; + args = (char**)malloc(sizeof(char*)*(argc+2)); + if (!args) { + perror("vsh: malloc failed"); + } + args[0] = argv[0]; + args[1] = "-l"; + for(i=1;i/dev/null` 2>/dev/null || true + endscript +} diff --git a/sysv/vcached.subst b/sysv/vcached.subst new file mode 100755 index 0000000..7714371 --- /dev/null +++ b/sysv/vcached.subst @@ -0,0 +1,56 @@ +#!/bin/sh +# +# chkconfig: 2345 65 80 +# description: vcached startup script +# pidfile: /var/run/vcached.pid +# +. /etc/init.d/functions +RETVAL=0 +USR_SBIN=/usr/sbin + +start() { + echo -n "Starting vcached: " + initlog -c $USR_SBIN/vcached + RETVAL=$? + [ "$RETVAL" -eq 0 ] && success $"vcached start" || failure $"vcached start" + echo + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/vcached + return $RETVAL +} + +stop() { + echo -n "Stopping vcached: " + if [[ -e /var/run/vcached.pid ]]; then + /bin/kill `cat /var/run/vcached.pid` + RETVAL=$? + else + RETVAL=1 + fi + [ "$RETVAL" -eq 0 ] && success $"vcached shutdown" || failure $"vcached shutdown +" + echo + rm -f /var/lock/subsys/vcached + rm -f /var/run/vcached.pid + return $RETVAL +} + +restart() { + stop + start +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + restart + ;; + *) + echo $"Usage: $0 {start|stop|restart}" + exit 1 +esac +exit $? diff --git a/sysv/vservers.conf b/sysv/vservers.conf index 0f309e3..7f13fc1 100644 --- a/sysv/vservers.conf +++ b/sysv/vservers.conf @@ -2,6 +2,6 @@ # BACKGROUND=yes # start the vservers on tty9, in background so the rest of the # boot process end early -BACKGROUND=no +BACKGROUND=yes diff --git a/sysv/vservers.subst b/sysv/vservers.subst index 7be797d..acaced0 100755 --- a/sysv/vservers.subst +++ b/sysv/vservers.subst @@ -1,91 +1,92 @@ #!/bin/sh -# chkconfig: 345 98 10 +# chkconfig: 345 99 01 # description: The vservers service is used to start and stop all # the virtual servers. USR_SBIN=/usr/sbin - +VROOTDIR=/vservers # Print the vserver name in priority/alpha order sortserver(){ - ( - cd /etc/vservers - for serv in *.conf - do - test -f "$serv" || continue - - PRIORITY=100 - . $serv - printf "%03d %s\n" $PRIORITY `basename $serv .conf` - done - ) | sort $* | (while read a b; do echo $b; done) + ( + cd /etc/vservers + for serv in *.conf ; do + # XXX - why is this check necessary? + test -f "$serv" || continue + PRIORITY=100 + . $serv + echo $PRIORITY `basename $serv .conf` + done + ) | sort -n $* | cut -d ' ' -f 2 } startservers(){ - echo "Starting the virtual servers" - cd /etc/vservers - for name in `sortserver` - do - ONBOOT= - . $name.conf - if [ "$ONBOOT" = "yes" ] ; then - $USR_SBIN/vserver $name start - else - echo virtual server $name not configured for on boot start - fi - done + echo "Starting the virtual servers" + cd /etc/vservers + for name in $*; do + if ! test -f "$name.conf" ; then + echo No configuration for this vserver: /etc/vservers/$name.conf + continue + fi + ONBOOT= + BACKGROUND=no + if [ -f /etc/vservers.conf ] ; then + . /etc/vservers.conf + fi + . $name.conf + if [ "$ONBOOT" = "yes" ] ; then + mkdir -p $VROOTDIR/$name/var/log + if [ "$BACKGROUND" = "yes" ] ; then + nohup setsid $USR_SBIN/vserver $name start >$VROOTDIR/$name/var/log/boot.log 2>&1 &1 /dev/tty8 /dev/tty8 & + # do nothing unless passed a vserver name - 'start all' functionality + # subsumed by Node Manager + if [ -z "$2" ]; then + touch /var/lock/subsys/vservers else - startservers + startservers $2 fi - touch /var/lock/subsys/vservers ;; stop) + shift echo "Stopping the virtual servers" cd /etc/vservers - for name in `sortserver -r` - do - $USR_SBIN/vserver $name stop + for name in ${*:-`sortserver -r`} ; do + chcontext --ctx `id -u $name` /usr/lib/util-vserver/vserverkillall + umount $VROOTDIR/$name/proc + umount $VROOTDIR/$name/dev/pts done rm -f /var/lock/subsys/vservers ;; restart|force-reload) - $0 stop - $0 start + shift + $0 stop $* + $0 start $* ;; reload) echo Not implemented ;; status) cd /etc/vservers - for serv in *.conf - do - ONBOOT=no - name=`basename $serv .conf` - . $serv - echo -n ONBOOT=$ONBOOT " " - $USR_SBIN/vserver $name running + for serv in *.conf ; do + ONBOOT=no + name=`basename $serv .conf` + . $serv + echo -n ONBOOT=$ONBOOT " " + $USR_SBIN/vserver $name running done ;; *) echo "Usage: vservers {start|stop|restart|reload|status}" exit 1 esac - -exit 0 - - - - diff --git a/util-vserver.spec b/util-vserver.spec index dfb7941..2e337a3 100644 --- a/util-vserver.spec +++ b/util-vserver.spec @@ -1,13 +1,19 @@ -%define __chattr /usr/bin/chattr +%define name util-vserver +%define version 0.30 +%define release 15.planetlab%{?date:.%{date}} + +Vendor: PlanetLab +Packager: PlanetLab Central +Distribution: PlanetLab 3.0 +URL: http://cvs.planet-lab.org/cvs/util-vserver Summary: Linux virtual server utilities -Name: util-vserver -Version: 0.30 -Release: 0 +Name: %{name} +Version: %{version} +Release: %{release} Epoch: 0 Copyright: GPL Group: System Environment/Base -URL: http://savannah.nongnu.org/projects/util-vserver/ Source0: http://savannah.nongnu.org/download/util-vserver/stable.pkg/%version/%name-%version.tar.bz2 Provides: %name-devel = %epoch:%version-%release BuildRoot: %_tmppath/%name-%version-%release-root @@ -15,7 +21,6 @@ Provides: vserver = %epoch:%version-%release Conflicts: vserver < %epoch:%version-%release Conflicts: vserver > %epoch:%version-%release BuildRequires: e2fsprogs-devel -Requires(post): %__chattr %package linuxconf Summary: Linuxconf administration modules for vservers @@ -43,12 +48,17 @@ linuxconf. %prep %setup -q +aclocal -I m4 +autoconf +automake --add-missing +# bootstrap to avoid BuildRequires of kernel-source +for linux in $RPM_BUILD_DIR/linux-* /lib/modules/`uname -r`/build ; do + [[ -d $linux/include ]] && %configure --with-kerneldir=$linux --enable-linuxconf && break +done %build -%configure --enable-linuxconf -%__make %{?_smp_mflags} - +make %install rm -rf $RPM_BUILD_ROOT @@ -60,36 +70,44 @@ test "%_initrddir" = %_sysconfdir/init.d || { mv ${RPM_BUILD_ROOT}%_sysconfdir/init.d/* ${RPM_BUILD_ROOT}%_initrddir/ } +mkdir -p ${RPM_BUILD_ROOT}/bin +ln -f ${RPM_BUILD_ROOT}%_sbindir/vsh ${RPM_BUILD_ROOT}/bin/vsh -%clean -rm -rf $RPM_BUILD_ROOT - - -%define v_services httpd named portmap sendmail smb sshd xinetd -%post -/sbin/chkconfig --add vservers -/sbin/chkconfig --add rebootmgr +install -D -m 644 sysv/vcached.logrotate ${RPM_BUILD_ROOT}/etc/logrotate.d/vcached -for i in %v_services; do - /sbin/chkconfig --add v_$i -done +mkdir -p $RPM_BUILD_ROOT/etc/cron.d +. sysv/vcached.conf +echo "*/$(($period / 60)) * * * * root %_sbindir/vcached -s -f -l $logfile" > $RPM_BUILD_ROOT/etc/cron.d/vcached -%__chattr +t /vservers || : +%__make -C python INSTALL_ROOT=$RPM_BUILD_ROOT install +%clean +rm -rf $RPM_BUILD_ROOT -%preun -test "$1" != 0 || for i in %v_services; do - /sbin/chkconfig --del v_$i -done +%post +chkconfig --add vservers +chkconfig vservers on -test "$1" != 0 || %{_initrddir}/rebootmgr stop &>/dev/null || : -test "$1" != 0 || /sbin/chkconfig --del rebootmgr -test "$1" != 0 || /sbin/chkconfig --del vservers +if [ ! -f /etc/shells ] || ! grep -q '^/bin/vsh$' /etc/shells ; then + echo /bin/vsh >> /etc/shells +fi +# make sure barrier bit is set on /vservers to prevent chroot() escapes +%_libdir/%name/setattr --barrier /vservers %postun -test "$1" = 0 || %{_initrddir}/rebootmgr condrestart >/dev/null || : +# 0 = erase, 1 = upgrade +if [ "$1" = 0 ] ; then + perl -i -n -e 'next if /^\/bin\/vsh$/; print' /etc/shells +fi +%preun +# 0 = erase, 1 = upgrade +if [ $1 -eq 0 ] ; then + [ "$PL_BOOTCD" = "1" ] || service vservers stop + chkconfig vservers off + chkconfig --del vservers +fi %files %defattr(-,root,root) @@ -101,12 +119,17 @@ test "$1" = 0 || %{_initrddir}/rebootmgr condrestart >/dev/null || : %_mandir/man8/* %config %_initrddir/* %config(noreplace) /etc/vservers.conf +%config(noreplace) /etc/vcached.conf +/etc/logrotate.d/vcached +/etc/cron.d/vcached +%dir /etc/vservers %attr(0,root,root) %dir /vservers +%attr(4755,root,root) /usr/sbin/vsh +%attr(4755,root,root) /bin/vsh %exclude %_sbindir/newvserver %exclude %_mandir/man8/newvserver* - %files linuxconf %defattr(-,root,root) %config(noreplace) /etc/vservers/newvserver.defaults @@ -114,9 +137,90 @@ test "$1" = 0 || %{_initrddir}/rebootmgr condrestart >/dev/null || : %_mandir/man8/newvserver* + +%package py23 +Summary: Python modules for manipulating vservers +Group: Applications/System +Requires: python /usr/lib/util-vserver/util-vserver-vars util-python + +%description py23 +Python modules for manipulating vservers. Provides a superset of the +functionality of the vserver script (at least will do in the future), +but more readily accessible from Python code. + +%files py23 +%defattr(0644,root,root) +/usr/lib/python2.3/site-packages/bwlimit.py +/usr/lib/python2.3/site-packages/bwlimit.pyc +/usr/lib/python2.3/site-packages/cpulimit.py +/usr/lib/python2.3/site-packages/cpulimit.pyc +/usr/lib/python2.3/site-packages/util_vserver_vars.py +/usr/lib/python2.3/site-packages/vduimpl.so +/usr/lib/python2.3/site-packages/vserver.py +/usr/lib/python2.3/site-packages/vserver.pyc +/usr/lib/python2.3/site-packages/vserverimpl.so + + + %changelog +* Thu Jul 28 2005 Steve Muir +- add support for static vserver IDs to vuseradd and vuserdel + +* Thu Jul 21 2005 Steve Muir +- add bwlimit and cpulimit modules + +* Mon Jun 20 2005 Steve Muir +- import Marc's vdu implementation + +* Wed Jun 15 2005 Steve Muir +- 'vserver-init start' functionality subsumed by Node Manager + +* Thu Jun 02 2005 Marc E. Fiuczynski +- Fixed vlimit command + +* Wed May 25 2005 Steve Muir +- add Python modules for manipulating vservers + +* Thu Apr 7 2005 Steve Muir +- vuserdel changes: don't shutdown vserver, just kill all processes; + unmount all mountpoints in vserver before deleting + +* Fri Nov 19 2004 Mark Huang +- vcached no longer runs as a daemon +- do not restart vservers when package is upgraded + +* Wed Nov 17 2004 Mark Huang 0.30-6.planetlab ++ planetlab-3_0-rc4 +- PL2445 +- Both vcached and vuseradd now print a warning message when vbuild + succeeds but the resulting new vserver image is smaller in size than + the vserver-reference image. +- vuseradd: clean up some more junk on failure + +* Tue Nov 16 2004 Mark Huang 0.30-5.planetlab ++ planetlab-3_0-rc3 +- PL3026: This is the upgraded version of vdu that maintains an + internal hash table of files with a nlink count > 1. Only if vdu + sees all hard links to a particular inode does it add its size and + block count to the total. + +* Fri Nov 12 2004 Mark Huang 0.30-4.planetlab +- PL2445 Use -b option to du to avoid rounding errors. + +* Sat Nov 6 2004 Mark Huang 0.30-3.planetlab ++ planetlab-3_0-rc2 +- don't create the symbolic link /home/slice/.ssh, this is not how + pl_sshd works + +* Mon Oct 11 2004 Marc E. Fiuczynski +- added vsh + +* Wed Aug 11 2004 Mark Huang 0.29-1.planetlab +- initial PlanetLab 3.0 build. + * Thu Mar 18 2004 Enrico Scholz - 0:0.29.3-0 - removed '%%doc doc/FAQ.txt' since file does not exist anymore * Fri Sep 26 2003 Enrico Scholz - 0:0.23.4-1 - initial build. + diff --git a/util-vserver.spec.in b/util-vserver.spec.in index 2c9b396..0d625bc 100644 --- a/util-vserver.spec.in +++ b/util-vserver.spec.in @@ -1,13 +1,19 @@ -%define __chattr /usr/bin/chattr +%define name @PACKAGE@ +%define version @VERSION@ +%define release 15.planetlab%{?date:.%{date}} + +Vendor: PlanetLab +Packager: PlanetLab Central +Distribution: PlanetLab 3.0 +URL: http://cvs.planet-lab.org/cvs/util-vserver Summary: Linux virtual server utilities -Name: @PACKAGE@ -Version: @VERSION@ -Release: 0 +Name: %{name} +Version: %{version} +Release: %{release} Epoch: 0 Copyright: GPL Group: System Environment/Base -URL: http://savannah.nongnu.org/projects/util-vserver/ Source0: http://savannah.nongnu.org/download/util-vserver/stable.pkg/%version/%name-%version.tar.bz2 Provides: %name-devel = %epoch:%version-%release BuildRoot: %_tmppath/%name-%version-%release-root @@ -15,7 +21,6 @@ Provides: vserver = %epoch:%version-%release Conflicts: vserver < %epoch:%version-%release Conflicts: vserver > %epoch:%version-%release BuildRequires: e2fsprogs-devel -Requires(post): %__chattr %package linuxconf Summary: Linuxconf administration modules for vservers @@ -43,12 +48,17 @@ linuxconf. %prep %setup -q +aclocal -I m4 +autoconf +automake --add-missing +# bootstrap to avoid BuildRequires of kernel-source +for linux in $RPM_BUILD_DIR/linux-* /lib/modules/`uname -r`/build ; do + [[ -d $linux/include ]] && %configure --with-kerneldir=$linux --enable-linuxconf && break +done %build -%configure --enable-linuxconf -%__make %{?_smp_mflags} - +make %install rm -rf $RPM_BUILD_ROOT @@ -60,36 +70,44 @@ test "%_initrddir" = %_sysconfdir/init.d || { mv ${RPM_BUILD_ROOT}%_sysconfdir/init.d/* ${RPM_BUILD_ROOT}%_initrddir/ } +mkdir -p ${RPM_BUILD_ROOT}/bin +ln -f ${RPM_BUILD_ROOT}%_sbindir/vsh ${RPM_BUILD_ROOT}/bin/vsh -%clean -rm -rf $RPM_BUILD_ROOT - - -%define v_services httpd named portmap sendmail smb sshd xinetd -%post -/sbin/chkconfig --add vservers -/sbin/chkconfig --add rebootmgr +install -D -m 644 sysv/vcached.logrotate ${RPM_BUILD_ROOT}/etc/logrotate.d/vcached -for i in %v_services; do - /sbin/chkconfig --add v_$i -done +mkdir -p $RPM_BUILD_ROOT/etc/cron.d +. sysv/vcached.conf +echo "*/$(($period / 60)) * * * * root %_sbindir/vcached -s -f -l $logfile" > $RPM_BUILD_ROOT/etc/cron.d/vcached -%__chattr +t /vservers || : +%__make -C python INSTALL_ROOT=$RPM_BUILD_ROOT install +%clean +rm -rf $RPM_BUILD_ROOT -%preun -test "$1" != 0 || for i in %v_services; do - /sbin/chkconfig --del v_$i -done +%post +chkconfig --add vservers +chkconfig vservers on -test "$1" != 0 || %{_initrddir}/rebootmgr stop &>/dev/null || : -test "$1" != 0 || /sbin/chkconfig --del rebootmgr -test "$1" != 0 || /sbin/chkconfig --del vservers +if [ ! -f /etc/shells ] || ! grep -q '^/bin/vsh$' /etc/shells ; then + echo /bin/vsh >> /etc/shells +fi +# make sure barrier bit is set on /vservers to prevent chroot() escapes +%_libdir/%name/setattr --barrier /vservers %postun -test "$1" = 0 || %{_initrddir}/rebootmgr condrestart >/dev/null || : +# 0 = erase, 1 = upgrade +if [ "$1" = 0 ] ; then + perl -i -n -e 'next if /^\/bin\/vsh$/; print' /etc/shells +fi +%preun +# 0 = erase, 1 = upgrade +if [ $1 -eq 0 ] ; then + [ "$PL_BOOTCD" = "1" ] || service vservers stop + chkconfig vservers off + chkconfig --del vservers +fi %files %defattr(-,root,root) @@ -101,12 +119,17 @@ test "$1" = 0 || %{_initrddir}/rebootmgr condrestart >/dev/null || : %_mandir/man8/* %config %_initrddir/* %config(noreplace) /etc/vservers.conf +%config(noreplace) /etc/vcached.conf +/etc/logrotate.d/vcached +/etc/cron.d/vcached +%dir /etc/vservers %attr(0,root,root) %dir /vservers +%attr(4755,root,root) /usr/sbin/vsh +%attr(4755,root,root) /bin/vsh %exclude %_sbindir/newvserver %exclude %_mandir/man8/newvserver* - %files linuxconf %defattr(-,root,root) %config(noreplace) /etc/vservers/newvserver.defaults @@ -114,9 +137,90 @@ test "$1" = 0 || %{_initrddir}/rebootmgr condrestart >/dev/null || : %_mandir/man8/newvserver* + +%package py23 +Summary: Python modules for manipulating vservers +Group: Applications/System +Requires: python /usr/lib/util-vserver/util-vserver-vars util-python + +%description py23 +Python modules for manipulating vservers. Provides a superset of the +functionality of the vserver script (at least will do in the future), +but more readily accessible from Python code. + +%files py23 +%defattr(0644,root,root) +/usr/lib/python2.3/site-packages/bwlimit.py +/usr/lib/python2.3/site-packages/bwlimit.pyc +/usr/lib/python2.3/site-packages/cpulimit.py +/usr/lib/python2.3/site-packages/cpulimit.pyc +/usr/lib/python2.3/site-packages/util_vserver_vars.py +/usr/lib/python2.3/site-packages/vduimpl.so +/usr/lib/python2.3/site-packages/vserver.py +/usr/lib/python2.3/site-packages/vserver.pyc +/usr/lib/python2.3/site-packages/vserverimpl.so + + + %changelog +* Thu Jul 28 2005 Steve Muir +- add support for static vserver IDs to vuseradd and vuserdel + +* Thu Jul 21 2005 Steve Muir +- add bwlimit and cpulimit modules + +* Mon Jun 20 2005 Steve Muir +- import Marc's vdu implementation + +* Wed Jun 15 2005 Steve Muir +- 'vserver-init start' functionality subsumed by Node Manager + +* Thu Jun 02 2005 Marc E. Fiuczynski +- Fixed vlimit command + +* Wed May 25 2005 Steve Muir +- add Python modules for manipulating vservers + +* Thu Apr 7 2005 Steve Muir +- vuserdel changes: don't shutdown vserver, just kill all processes; + unmount all mountpoints in vserver before deleting + +* Fri Nov 19 2004 Mark Huang +- vcached no longer runs as a daemon +- do not restart vservers when package is upgraded + +* Wed Nov 17 2004 Mark Huang 0.30-6.planetlab ++ planetlab-3_0-rc4 +- PL2445 +- Both vcached and vuseradd now print a warning message when vbuild + succeeds but the resulting new vserver image is smaller in size than + the vserver-reference image. +- vuseradd: clean up some more junk on failure + +* Tue Nov 16 2004 Mark Huang 0.30-5.planetlab ++ planetlab-3_0-rc3 +- PL3026: This is the upgraded version of vdu that maintains an + internal hash table of files with a nlink count > 1. Only if vdu + sees all hard links to a particular inode does it add its size and + block count to the total. + +* Fri Nov 12 2004 Mark Huang 0.30-4.planetlab +- PL2445 Use -b option to du to avoid rounding errors. + +* Sat Nov 6 2004 Mark Huang 0.30-3.planetlab ++ planetlab-3_0-rc2 +- don't create the symbolic link /home/slice/.ssh, this is not how + pl_sshd works + +* Mon Oct 11 2004 Marc E. Fiuczynski +- added vsh + +* Wed Aug 11 2004 Mark Huang 0.29-1.planetlab +- initial PlanetLab 3.0 build. + * Thu Mar 18 2004 Enrico Scholz - 0:0.29.3-0 - removed '%%doc doc/FAQ.txt' since file does not exist anymore * Fri Sep 26 2003 Enrico Scholz - 0:0.23.4-1 - initial build. + -- 2.43.0