[libvirt] Patch set to add InteractiveContainer support to virt-sandbox

Resend of patches with lots of cleanups. This patch set adds InteractiveContainer support to virt-sandbox-service command. This is needed if we want to support the OpenShift model of containers. There are also some bug fix patches in the set. [sandbox PATCH 01/15] virt-sandbox-service-util needs to free [sandbox PATCH 02/15] Add support for InteractiveContainers to [sandbox PATCH 03/15] Move virt-sandbox-service bash completion [sandbox PATCH 04/15] Add -u UNITFILE option to virt-sandbox-service [sandbox PATCH 05/15] Change virt-sandbox-service-create.pod to use [sandbox PATCH 06/15] Internationalize all output strings in [sandbox PATCH 07/15] Remove distinction from Internal vs External [sandbox PATCH 08/15] Make CONFIG_PATH external to the Container [sandbox PATCH 09/15] Add exception handler GlibGerror to [sandbox PATCH 10/15] Change variable config to config_path to avoid [sandbox PATCH 11/15] Refactor Container class into Container and [sandbox PATCH 12/15] Add support for InteractiveContainer [sandbox PATCH 13/15] Use args.uri rather then hard coding lxc:/// [sandbox PATCH 14/15] Check for LXC if virt-sandbox-service execute [sandbox PATCH 15/15] Create new /etc/rc.d directory to bind mount

Coverity found that we could be leaking memory with virt-sandbox-service-util -e --- bin/virt-sandbox-service-util.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bin/virt-sandbox-service-util.c b/bin/virt-sandbox-service-util.c index 4d164d8..a292fcd 100644 --- a/bin/virt-sandbox-service-util.c +++ b/bin/virt-sandbox-service-util.c @@ -194,8 +194,9 @@ static int set_process_label(pid_t pid) { static int container_execute( GVirSandboxContext *ctx, const gchar *command, pid_t pid ) { int ret = EXIT_FAILURE; - char **argv; - int argc; + char **argv = NULL; + int argc=-1; + int i; if (set_process_label(pid) < 0) goto cleanup; @@ -227,6 +228,10 @@ static int container_execute( GVirSandboxContext *ctx, const gchar *command, pid } cleanup: + for (i = argc; i >= 0; i--) + free(argv[i]); + free(argv); + return ret; } -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:19PM -0400, Dan Walsh wrote:
Coverity found that we could be leaking memory with virt-sandbox-service-util -e --- bin/virt-sandbox-service-util.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/bin/virt-sandbox-service-util.c b/bin/virt-sandbox-service-util.c index 4d164d8..a292fcd 100644 --- a/bin/virt-sandbox-service-util.c +++ b/bin/virt-sandbox-service-util.c @@ -194,8 +194,9 @@ static int set_process_label(pid_t pid) { static int container_execute( GVirSandboxContext *ctx, const gchar *command, pid_t pid ) {
int ret = EXIT_FAILURE; - char **argv; - int argc; + char **argv = NULL; + int argc=-1; + int i;
if (set_process_label(pid) < 0) goto cleanup; @@ -227,6 +228,10 @@ static int container_execute( GVirSandboxContext *ctx, const gchar *command, pid }
cleanup: + for (i = argc; i >= 0; i--)
Can you use the more normal (i = 0 ; i < argc ; i++)
+ free(argv[i]);
Identation is off here
+ free(argv); + return ret; }
ACK if those two things are fixed before pushing. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

We need to add support for interactive sandbox/containers for OpenShift. This patch will create the correct container type based off the /etc/libvirt-sandbox/service/* --- bin/virt-sandbox-service-util.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/bin/virt-sandbox-service-util.c b/bin/virt-sandbox-service-util.c index a292fcd..c4b774c 100644 --- a/bin/virt-sandbox-service-util.c +++ b/bin/virt-sandbox-service-util.c @@ -1,7 +1,7 @@ /* * virt-sandbox-service-util.c: libvirt sandbox service util command * - * Copyright (C) 2012 Red Hat, Inc. + * Copyright (C) 2012-2013 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -353,7 +353,6 @@ static gboolean libvirt_lxc_attach(const gchar *option_name, int main(int argc, char **argv) { GMainLoop *loop = NULL; - GVirSandboxConfigService *cfg = NULL; GVirSandboxConfig *config = NULL; GVirSandboxContext *ctx = NULL; GError *err = NULL; @@ -361,7 +360,6 @@ int main(int argc, char **argv) { int ret = EXIT_FAILURE; pid_t pid = 0; gchar *buf=NULL; - GVirSandboxContextService *service; gchar *uri = NULL; gchar *command = NULL; @@ -452,16 +450,25 @@ int main(int argc, char **argv) { goto cleanup; } - cfg = GVIR_SANDBOX_CONFIG_SERVICE(config); + if (GVIR_SANDBOX_IS_CONFIG_INTERACTIVE(config)) { + GVirSandboxContextInteractive *service; + if (!(service = gvir_sandbox_context_interactive_new(hv, GVIR_SANDBOX_CONFIG_INTERACTIVE(config)))) { + g_printerr(_("Unable to create new context service: %s\n"), + err && err->message ? err->message : _("unknown")); + goto cleanup; + } + ctx = GVIR_SANDBOX_CONTEXT(service); + } else { + GVirSandboxContextService *service; - if (!(service = gvir_sandbox_context_service_new(hv, cfg))) { - g_printerr(_("Unable to create new context service: %s\n"), - err && err->message ? err->message : _("unknown")); - goto cleanup; + if (!(service = gvir_sandbox_context_service_new(hv, GVIR_SANDBOX_CONFIG_SERVICE(config)))) { + g_printerr(_("Unable to create new context service: %s\n"), + err && err->message ? err->message : _("unknown")); + goto cleanup; + } + ctx = GVIR_SANDBOX_CONTEXT(service); } - ctx = GVIR_SANDBOX_CONTEXT(service); - if (command) { container_execute(ctx, command, pid); } @@ -476,8 +483,8 @@ cleanup: free(buf); - if (cfg) - g_object_unref(cfg); + if (config) + g_object_unref(config); exit(ret); } -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:20PM -0400, Dan Walsh wrote:
We need to add support for interactive sandbox/containers for OpenShift.
This patch will create the correct container type based off the /etc/libvirt-sandbox/service/* --- bin/virt-sandbox-service-util.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) @@ -452,16 +450,25 @@ int main(int argc, char **argv) { goto cleanup; }
- cfg = GVIR_SANDBOX_CONFIG_SERVICE(config); + if (GVIR_SANDBOX_IS_CONFIG_INTERACTIVE(config)) { + GVirSandboxContextInteractive *service; + if (!(service = gvir_sandbox_context_interactive_new(hv, GVIR_SANDBOX_CONFIG_INTERACTIVE(config)))) { + g_printerr(_("Unable to create new context service: %s\n"), + err && err->message ? err->message : _("unknown")); + goto cleanup;
Again your identation here is not right - 4 space indent is the norm,
+ } + ctx = GVIR_SANDBOX_CONTEXT(service); + } else { + GVirSandboxContextService *service;
- if (!(service = gvir_sandbox_context_service_new(hv, cfg))) { - g_printerr(_("Unable to create new context service: %s\n"), - err && err->message ? err->message : _("unknown")); - goto cleanup; + if (!(service = gvir_sandbox_context_service_new(hv, GVIR_SANDBOX_CONFIG_SERVICE(config)))) { + g_printerr(_("Unable to create new context service: %s\n"), + err && err->message ? err->message : _("unknown")); + goto cleanup;
And here ACK if identation is fixed before pushing Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

bash_completion scripts have added a new way to do completions, where you place you scripts in /usr/share/bash_completion/completions rather then /etc/bash_completions.d. We should follow the new standard, and this patch moves our bash_completion script to the proper location with the proper name. --- bin/Makefile.am | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/Makefile.am b/bin/Makefile.am index 69af01e..1942dab 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -5,14 +5,14 @@ libexec_PROGRAMS = virt-sandbox-service-util bin_SCRIPTS = virt-sandbox-service -virtsandboxcompdir = $(sysconfdir)/bash_completion.d/ -virtsandboxcomp_DATA = virt-sandbox-service-bash-completion.sh +virtsandboxcompdir = $(datarootdir)/bash-completion/completions/ crondailydir = $(sysconfdir)/cron.daily crondaily_SCRIPTS = virt-sandbox-service.logrotate POD_FILES = virt-sandbox-service.pod virt-sandbox-service-execute.pod virt-sandbox-service-create.pod virt-sandbox-service-clone.pod virt-sandbox-service-connect.pod virt-sandbox-service-delete.pod virt-sandbox-service-start.pod virt-sandbox-service-stop.pod virt-sandbox-service-reload.pod virt-sandbox-service-list.pod EXTRA_DIST = $(bin_SCRIPTS) $(POD_FILES) virt-sandbox-service-bash-completion.sh virt-sandbox-service.logrotate +EXTRA_DIST += virt-sandbox-service-bash-completion.sh man1_MANS = virt-sandbox.1 virt-sandbox-service.1 virt-sandbox-service-execute.1 virt-sandbox-service-create.1 virt-sandbox-service-clone.1 virt-sandbox-service-connect.1 virt-sandbox-service-delete.1 virt-sandbox-service-start.1 virt-sandbox-service-stop.1 virt-sandbox-service-reload.1 virt-sandbox-service-list.1 @@ -84,7 +84,10 @@ virt_sandbox_service_util_LDFLAGS = \ install-data-local: $(MKDIR_P) $(DESTDIR)$(sysconfdir)/libvirt-sandbox/services + $(MKDIR_P) $(DESTDIR)$(virtsandboxcompdir) + cp virt-sandbox-service-bash-completion.sh $(DESTDIR)$(virtsandboxcompdir)/virt-sandbox-service uninstall-local: $(rmdir) $(DESTDIR)$(sysconfdir)/libvirt-sandbox/services ||: $(rmdir) $(DESTDIR)$(sysconfdir)/libvirt-sandbox ||: + rm -f $(DESTDIR)$(virtsandboxcompdir)/virt-sandbox-service -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:21PM -0400, Dan Walsh wrote:
bash_completion scripts have added a new way to do completions, where you place you scripts in /usr/share/bash_completion/completions rather then /etc/bash_completions.d.
We should follow the new standard, and this patch moves our bash_completion script to the proper location with the proper name. --- bin/Makefile.am | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

The command will allow administrators or the systemd service to reload units which are running within a container. If you have one or more units defined for a container, then just those units will get the reloads, as opposed to stopping and restarting the container. --- bin/virt-sandbox-service | 56 ++++++++++++++++++++--------- bin/virt-sandbox-service-bash-completion.sh | 3 +- bin/virt-sandbox-service-reload.pod | 9 +++-- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 478769d..ff14be1 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -164,12 +164,12 @@ After=libvirtd.service [Service] Type=simple ExecStart=/usr/bin/virt-sandbox-service start %(NAME)s -ExecReload=/usr/bin/virt-sandbox-service reload %(NAME)s +ExecReload=/usr/bin/virt-sandbox-service reload -u %(RELOAD)s %(NAME)s ExecStop=/usr/bin/virt-sandbox-service stop %(NAME)s [Install] WantedBy=%(TARGET)s -""" % { 'NAME':name, 'FOLLOW':self.__follow_units(), 'TARGET':self.__target() } +""" % { 'NAME':name, 'FOLLOW':self.__follow_units(), 'TARGET':self.__target(), 'RELOAD': " -u ".join(map(lambda x: x[0], self.unit_file_list)) } fd = open(self.unitfile, "w") fd.write(unit) fd.close() @@ -649,11 +649,18 @@ PrivateNetwork=false pass raise e - def reload(self): - # Crude way of doing this. - self.stop() - self.start() - # self.execute("systemctl reload %s.service" % self.get_name()) + def reload(self, unitfiles): + # + # Reload Container + # + class Args: + command = [] + noseclabel = None + name = self.name + uri = self.uri + args = Args() + args.command = [ "systemctl", "reload" ] + map(lambda x: x[0], unitfiles) + execute(args) def __connect(self): if not self.conn: @@ -800,8 +807,9 @@ def sandbox_list(args): def sandbox_reload(args): - container = Container(args.name, args.uri) - container.reload() + config = read_config(args.name) + container = Container(uri = args.uri, config = config) + container.reload(args.unitfiles) def start(args): os.execl("/usr/libexec/virt-sandbox-service-util", "virt-sandbox-service-util","-s", args.name) @@ -893,17 +901,28 @@ class SizeAction(argparse.Action): setattr(namespace, self.dest, int(values)) class CheckUnit(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): - src = "/etc/systemd/system/" + values - if not os.path.exists(src): - src = "/lib/systemd/system/" + values - if not os.path.exists(src): - raise OSError("Requested unit %s does not exist" % values) + def __call__(self, parser, namespace, value, option_string=None): + def check_unit(unit): + src = "/etc/systemd/system/" + unit + if os.path.exists(src): + return src + src = "/lib/systemd/system/" + unit + if os.path.exists(src): + return src + return None + src = check_unit(value) + if not src: + src = check_unit(value + ".service") + if src: + value = value + ".service" + else: + raise OSError("Requested unit %s does not exist" % value) + unitfiles = getattr(namespace, self.dest) if unitfiles: - unitfiles.append((values, src)) + unitfiles.append((value, src)) else: - unitfiles = [ (values, src) ] + unitfiles = [ (value, src) ] setattr(namespace, self.dest, unitfiles) class SetNet(argparse.Action): @@ -989,6 +1008,9 @@ def gen_stop_args(subparser): def gen_reload_args(subparser): parser = subparser.add_parser("reload", help=_("Reload a running sandbox container")) + parser.add_argument("-u", "--unitfile", required=True, + action=CheckUnit, dest="unitfiles", + help=_("Systemd Unit file to reload within the sandbox container")) requires_name(parser) parser.set_defaults(func=sandbox_reload) diff --git a/bin/virt-sandbox-service-bash-completion.sh b/bin/virt-sandbox-service-bash-completion.sh index c855fd2..ce14a7d 100755 --- a/bin/virt-sandbox-service-bash-completion.sh +++ b/bin/virt-sandbox-service-bash-completion.sh @@ -57,6 +57,7 @@ _virt_sandbox_service () { [ALL]='-h --help' [CREATE]='-u --unitfile -p --path -t --type -l --level -d --dynamic -n --clone -i --image -s --size' [LIST]='-r --running' + [RELOAD]='-u --unitfile' [EXECUTE]='-N --noseclabel' ) @@ -88,7 +89,7 @@ _virt_sandbox_service () { COMPREPLY=( $(compgen -W "${OPTS[ALL]} $( __get_all_running_containers ) " -- "$cur") ) return 0 elif test "$verb" == "reload" ; then - COMPREPLY=( $(compgen -W "${OPTS[ALL]} $( __get_all_running_containers ) " -- "$cur") ) + COMPREPLY=( $(compgen -W "${OPTS[ALL]} ${OPTS[RELOAD]} $( __get_all_running_containers ) " -- "$cur") ) return 0 elif test "$verb" == "connect" ; then COMPREPLY=( $(compgen -W "${OPTS[ALL]} $( __get_all_running_containers ) " -- "$cur") ) diff --git a/bin/virt-sandbox-service-reload.pod b/bin/virt-sandbox-service-reload.pod index d26af82..b4919be 100644 --- a/bin/virt-sandbox-service-reload.pod +++ b/bin/virt-sandbox-service-reload.pod @@ -4,7 +4,7 @@ virt-sandbox-service reload - Reload a security container =head1 SYNOPSIS - virt-sandbox-service [-c URI] reload [-h] NAME + virt-sandbox-service [-c URI] reload [-h] -u UNIT_FILE NAME =head1 DESCRIPTION @@ -26,6 +26,11 @@ Display help message =item B<-c> URI, B<--connect URI> +=item B<-u UNIT_FILE>, B<--unitfile UNIT_FILE> + +Name of the systemd unit file to reload within the container. Can be repeated +if multiple unit files need to be reloaded within the sandbox. + The connection URI for the hypervisor (only LXC or QEMU are supported currently). @@ -35,7 +40,7 @@ supported currently). Reload the httpd1 container - # virt-sandbox-service reload httpd1 + # virt-sandbox-service reload -u httpd.service httpd1 =head1 SEE ALSO -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:22PM -0400, Dan Walsh wrote:
The command will allow administrators or the systemd service to reload units which are running within a container. If you have one or more units defined for a container, then just those units will get the reloads, as opposed to stopping and restarting the container. --- bin/virt-sandbox-service | 56 ++++++++++++++++++++--------- bin/virt-sandbox-service-bash-completion.sh | 3 +- bin/virt-sandbox-service-reload.pod | 9 +++-- 3 files changed, 48 insertions(+), 20 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Current the documentation says that you use --clone while the code uses --copy when you are createing a sandbox service container. Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service-create.pod | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/virt-sandbox-service-create.pod b/bin/virt-sandbox-service-create.pod index 1f82e1d..3fb8ae0 100644 --- a/bin/virt-sandbox-service-create.pod +++ b/bin/virt-sandbox-service-create.pod @@ -4,7 +4,7 @@ virt-sandbox-service create - Create a Security container =head1 SYNOPSIS - virt-sandbox-service [-c URI] create [-h] -u UNIT_FILE [ --clone ] [-p PATH] [-N NETWORK-OPTS] [-s SECURITY-OPTS] [-i SIZE] [-n] NAME + virt-sandbox-service [-c URI] create [-h] -u UNIT_FILE [ --copy ] [-p PATH] [-N NETWORK-OPTS] [-s SECURITY-OPTS] [-i SIZE] [-n] NAME =head1 DESCRIPTION @@ -34,9 +34,9 @@ supported currently). Name of the systemd unit file to be to run within the container. Can be repeated if multiple unit files are required within the sandbox. -=item B<-C>, B<--clone> +=item B<-C>, B<--copy> -Clone content from /etc and /var directories that will be mounted within the container. +Copy content from /etc and /var directories that will be mounted within the container. =item B<-p PATH>, B<--path PATH> -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:23PM -0400, Dan Walsh wrote:
Current the documentation says that you use --clone while the code uses --copy when you are createing a sandbox service container.
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service-create.pod | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Wrap all output strings with _() to make sure we get proper translations. Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index ff14be1..8788183 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -91,7 +91,7 @@ class Container: if create: if config and os.path.exists(config): - raise ValueError(["Container already exists"]) + raise ValueError([_("Container already exists")]) self.config = LibvirtSandbox.ConfigService.new(name) return @@ -123,7 +123,7 @@ class Container: def __get_sandbox_target(self): if len(self.unit_file_list) > 1: - raise ValueError(["Only Valid for single units"]) + raise ValueError([_("Only Valid for single units")]) return "%s_sandbox.target" % self.__get_sandboxed_service() def __target(self): @@ -178,8 +178,8 @@ WantedBy=%(TARGET)s p = Popen(["/usr/bin/systemctl","enable", self.unitfile],stdout=PIPE, stderr=PIPE) p.communicate() if p.returncode and p.returncode != 0: - raise OSError("Failed to enable %s unit file " % self.unitfile) - sys.stdout.write("Created unit file %s\n" % self.unitfile) + raise OSError(_("Failed to enable %s unit file") % self.unitfile) + sys.stdout.write(_("Created unit file %s\n") % self.unitfile) def __add_dir(self, newd): if newd in self.all_dirs: @@ -229,7 +229,7 @@ WantedBy=%(TARGET)s def get_name(self): if self.config: return self.config.get_name() - raise ValueError(["Name not configured"]) + raise ValueError([_("Name not configured")]) def set_copy(self, copy): self.copy = copy @@ -255,10 +255,10 @@ WantedBy=%(TARGET)s selabel = self.get_security_label() if selabel is None: - raise ValueError(["Missing security label configuration"]) + raise ValueError([_("Missing security label configuration")]) parts = selabel.split(":") if len(parts) != 5 and len(parts) != 4: - raise ValueError(["Expected 5 parts in SELinux security label %s" % parts]) + raise ValueError([_("Expected 5 parts in SELinux security label %s") % parts]) if len(parts) == 5: selinux.chcon(self.dest, "system_u:object_r:%s:%s:%s" % ( @@ -276,7 +276,7 @@ WantedBy=%(TARGET)s def set_name(self, name): if self.config: - raise ValueError(["Cannot modify Name"]) + raise ValueError([_("Cannot modify Name")]) self.dest = "%s/%s" % (self.path, self.name) self.config = LibvirtSandbox.ConfigService.new(name) @@ -317,7 +317,7 @@ WantedBy=%(TARGET)s try: h = mi.next(); except exceptions.StopIteration: - raise ValueError(["Cannot find package containing %s" % unitfile]) + raise ValueError([_("Cannot find package containing %s") % unitfile]) for fentry in h.fiFromHeader(): fname = fentry[0] @@ -337,7 +337,7 @@ WantedBy=%(TARGET)s try: h = mi.next(); except exceptions.StopIteration: - raise ValueError(["Cannot find base package %s" % srcrpmbits[0]]) + raise ValueError([_("Cannot find base package %s") % srcrpmbits[0]]) for fentry in h.fiFromHeader(): fname = fentry[0] @@ -528,7 +528,7 @@ PrivateNetwork=false p = Popen(["/bin/umount", self.dest]) p.communicate() if p.returncode and p.returncode != 0: - raise OSError("Failed to unmount image %s from %s " % (self.image, self.dest)) + raise OSError(_("Failed to unmount image %s from %s") % (self.image, self.dest)) def __create_image(self): fd = open(self.image, "w") @@ -537,12 +537,12 @@ PrivateNetwork=false p = Popen(["/sbin/mkfs","-F", "-t", "ext4", self.image],stdout=PIPE, stderr=PIPE) p.communicate() if p.returncode and p.returncode != 0: - raise OSError("Failed to build image %s" % self.image ) + raise OSError(_("Failed to build image %s") % self.image ) p = Popen(["/bin/mount", self.image, self.dest]) p.communicate() if p.returncode and p.returncode != 0: - raise OSError("Failed to mount image %s on %s " % (self.image, self.dest)) + raise OSError(_("Failed to mount image %s on %s") % (self.image, self.dest)) def save_config(self): config = self.get_config_path() @@ -551,7 +551,7 @@ PrivateNetwork=false self.config.save_to_path(config) if selinux is not None: selinux.restorecon(config) - sys.stdout.write("Created sandbox config %s\n" % config) + sys.stdout.write(_("Created sandbox config %s\n") % config) def __get_image_path(self): mounts = self.config.get_mounts() @@ -593,7 +593,7 @@ PrivateNetwork=false p = Popen(["/usr/bin/systemctl","disable", self.unitfile],stdout=PIPE, stderr=PIPE) p.communicate() if p.returncode and p.returncode != 0: - raise OSError("Failed to disable %s unit file " % self.unitfile) + raise OSError(_("Failed to disable %s unit file") % self.unitfile) fd = open(self.unitfile,"r") recs = fd.readlines() fd.close() @@ -628,17 +628,17 @@ PrivateNetwork=false self.__create_image() self.__gen_content() self.__umount() - sys.stdout.write("Created sandbox container image %s\n" % self.image) + sys.stdout.write(_("Created sandbox container image %s\n") % self.image) else: self.__gen_content() - sys.stdout.write("Created sandbox container dir %s\n" % self.dest) + sys.stdout.write(_("Created sandbox container dir %s\n") % self.dest) self.set_security_label() self.save_config() self.__create_system_unit() def create(self): if os.path.exists(self.dest): - raise OSError("%s already exists" % self.dest) + raise OSError(_("%s already exists") % self.dest) try: self._create() @@ -867,11 +867,11 @@ def clone(args): new_image_path = container.get_image_path(args.dest) newrec = newrec.replace(old_image_path, new_image_path) shutil.copy(old_image_path, new_image_path) - sys.stdout.write("Created sandbox container image %s\n" % new_image_path) + sys.stdout.write(_("Created sandbox container image %s\n") % new_image_path) os.mkdir(new_path) else: shutil.copytree(old_path, new_path, symlinks=True) - sys.stdout.write("Created sandbox container dir %s\n" % new_path) + sys.stdout.write(_("Created sandbox container dir %s\n") % new_path) fd = open(container.get_unit_path()) recs = fd.read() @@ -885,7 +885,7 @@ def clone(args): fd = open(new_unit,"wx") fd.write(newrec) fd.close() - sys.stdout.write("Created unit file %s\n" % new_unit) + sys.stdout.write(_("Created unit file %s\n") % new_unit) container = Container(args.dest, args.uri) if args.security: @@ -916,7 +916,7 @@ class CheckUnit(argparse.Action): if src: value = value + ".service" else: - raise OSError("Requested unit %s does not exist" % value) + raise OSError(_("Requested unit %s does not exist") % value) unitfiles = getattr(namespace, self.dest) if unitfiles: @@ -984,7 +984,7 @@ def gen_connect_args(subparser): def gen_execute_args(subparser): parser = subparser.add_parser("execute", - help=("Execute a command within a sandbox container")) + help=_("Execute a command within a sandbox container")) parser.add_argument("-N", "--noseclabel", dest="noseclabel", default=False, action="store_true", help=_("do not modify the label of the executable process. By default all commands execute with the label of the sandbox")) @@ -1025,7 +1025,7 @@ def gen_clone_args(subparser): parser.add_argument("source", help=_("source sandbox container name")) parser.add_argument("dest", - help=("dest name of the new sandbox container")) + help=_("dest name of the new sandbox container")) def gen_delete_args(subparser): parser = subparser.add_parser("delete", -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:24PM -0400, Dan Walsh wrote:
Wrap all output strings with _() to make sure we get proper translations.
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

This patch removes all __METHOD and _METHOD functions calls. Since it is not intended that virt-sandbox-service will be imported into another python module, there is limited value to using the internal indicators. Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 118 +++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 8788183..43158de 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -103,7 +103,7 @@ class Container: except GLib.GError, e: raise OSError(config + ": " + str(e)) - def __follow_units(self): + def follow_units(self): unitst="" for i, src in self.unit_file_list: unitst += "ReloadPropagatedFrom=%s\n" % i @@ -118,17 +118,17 @@ class Container: def set_unit_file_list(self, unit_file_list): self.unit_file_list = unit_file_list - def __get_sandboxed_service(self): + def get_sandboxed_service(self): return self.unit_file_list[0][0].split(".")[0] - def __get_sandbox_target(self): + def get_sandbox_target(self): if len(self.unit_file_list) > 1: raise ValueError([_("Only Valid for single units")]) - return "%s_sandbox.target" % self.__get_sandboxed_service() + return "%s_sandbox.target" % self.get_sandboxed_service() - def __target(self): + def target(self): try: - name = self.__get_sandbox_target() + name = self.get_sandbox_target() path = "/etc/systemd/system/" + name if not os.path.exists(path): fd = open(path, "w") @@ -147,12 +147,12 @@ Documentation=man:virt-sandbox-service(1) [Install] WantedBy=multi-user.target -""" % { "NAME" : self.__get_sandboxed_service() }) +""" % { "NAME" : self.get_sandboxed_service() }) return "%s" % name except OSError: return "" - def __create_system_unit(self): + def create_system_unit(self): self.unitfile = self.get_unit_path() name = self.config.get_name() unit = r""" @@ -169,7 +169,7 @@ ExecStop=/usr/bin/virt-sandbox-service stop %(NAME)s [Install] WantedBy=%(TARGET)s -""" % { 'NAME':name, 'FOLLOW':self.__follow_units(), 'TARGET':self.__target(), 'RELOAD': " -u ".join(map(lambda x: x[0], self.unit_file_list)) } +""" % { 'NAME':name, 'FOLLOW':self.follow_units(), 'TARGET':self.target(), 'RELOAD': " -u ".join(map(lambda x: x[0], self.unit_file_list)) } fd = open(self.unitfile, "w") fd.write(unit) fd.close() @@ -181,7 +181,7 @@ WantedBy=%(TARGET)s raise OSError(_("Failed to enable %s unit file") % self.unitfile) sys.stdout.write(_("Created unit file %s\n") % self.unitfile) - def __add_dir(self, newd): + def add_dir(self, newd): if newd in self.all_dirs: return for ignd in self.IGNORE_DIRS: @@ -200,7 +200,7 @@ WantedBy=%(TARGET)s self.dirs.append(newd) break; - def __add_file(self, newf): + def add_file(self, newf): if newf in self.files: return for d in self.IGNORE_DIRS: @@ -280,7 +280,7 @@ WantedBy=%(TARGET)s self.dest = "%s/%s" % (self.path, self.name) self.config = LibvirtSandbox.ConfigService.new(name) - def __extract_rpms(self): + def extract_rpms(self): self.all_dirs = [] self.dirs = [] self.files = [] @@ -288,9 +288,9 @@ WantedBy=%(TARGET)s self.ts = rpm.ts() for u, src in self.unit_file_list: - self.__extract_rpm_for_unit(src) + self.extract_rpm_for_unit(src) - def __split_filename(self, filename): + def split_filename(self, filename): if filename[-4:] == '.rpm': filename = filename[:-4] @@ -312,7 +312,7 @@ WantedBy=%(TARGET)s name = filename[epochIndex + 1:verIndex] return name, ver, rel, epoch, arch - def __extract_rpm_for_unit(self, unitfile): + def extract_rpm_for_unit(self, unitfile): mi = self.ts.dbMatch(rpm.RPMTAG_BASENAMES, unitfile) try: h = mi.next(); @@ -323,12 +323,12 @@ WantedBy=%(TARGET)s fname = fentry[0] if os.path.isdir(fname): - self.__add_dir(fname) + self.add_dir(fname) if os.path.isfile(fname): - self.__add_file(fname) + self.add_file(fname) srcrpm = h[rpm.RPMTAG_SOURCERPM] - srcrpmbits = self.__split_filename(srcrpm) + srcrpmbits = self.split_filename(srcrpm) if srcrpmbits[0] == h[rpm.RPMTAG_NAME]: return @@ -343,11 +343,11 @@ WantedBy=%(TARGET)s fname = fentry[0] if os.path.isdir(fname): - self.__add_dir(fname) + self.add_dir(fname) if os.path.isfile(fname): - self.__add_file(fname) + self.add_file(fname) - def __add_mount(self, source, dest): + def add_mount(self, source, dest): mount = LibvirtSandbox.ConfigMountHostBind.new(source, dest) self.config.add_mount(mount) @@ -376,7 +376,7 @@ WantedBy=%(TARGET)s os.symlink(self.dest + jpath, jpath) - def __gen_filesystems(self): + def gen_filesystems(self): if self.use_image: self.image = self.DEFAULT_IMAGE % self.get_name() mount = LibvirtSandbox.ConfigMountHostImage.new(self.image, self.dest) @@ -397,12 +397,12 @@ WantedBy=%(TARGET)s for d in self.BIND_SYSTEM_DIRS: if os.path.exists(d): source = "%s%s" % ( self.dest, d) - self.__add_mount(source, d) + self.add_mount(source, d) for f in self.BIND_SYSTEM_FILES: if os.path.exists(f): source = "%s%s" % ( self.dest, f) - self.__add_mount(source, f) + self.add_mount(source, f) for d in self.dirs: found = False @@ -413,12 +413,12 @@ WantedBy=%(TARGET)s break if not found: source = "%s%s" % ( self.dest, d) - self.__add_mount(source, d) + self.add_mount(source, d) - def __get_init_path(self): + def get_init_path(self): return "%s/%s/init" % (self.path, self.get_name()) - def __create_container_unit(self, src, dest, unit): + def create_container_unit(self, src, dest, unit): fd = open(dest + "/" + unit, "w") fd.write(""".include %s [Service] @@ -427,7 +427,7 @@ PrivateNetwork=false """ % src ) fd.close() - def __fix_stat(self, f): + def fix_stat(self, f): try: s = os.stat(f) path = "%s%s" % (self.dest, f) @@ -437,15 +437,15 @@ PrivateNetwork=false if not e.errno == errno.ENOENT: raise e - def __fix_protection(self): + def fix_protection(self): l = len(self.dest) for root, dirs, files in os.walk(self.dest): for f in files: dest = root + "/" + f - self.__fix_stat(dest[l:]) + self.fix_stat(dest[l:]) for d in dirs: dest = root + "/" + d - self.__fix_stat(dest[l:]) + self.fix_stat(dest[l:]) def makedirs(self, d): try: @@ -465,7 +465,7 @@ PrivateNetwork=false if not e.errno == errno.EEXIST: raise e - def __gen_content(self): + def gen_content(self): if self.copy: for d in self.dirs: shutil.copytree(d, "%s%s" % (self.dest, d), symlinks=True) @@ -505,7 +505,7 @@ PrivateNetwork=false os.symlink("/run", self.dest + "/var/run") for i, src in self.unit_file_list: - self.__create_container_unit(src, self.dest + unitdir, i) + self.create_container_unit(src, self.dest + unitdir, i) os.symlink("../" + i, self.dest + tgtdir + "/" + i) tgtfile = unitdir + "/multi-user.target" @@ -522,15 +522,15 @@ PrivateNetwork=false profile = "/etc/skel/" + p shutil.copy(profile, self.dest + "/root/") - self.__fix_protection() + self.fix_protection() - def __umount(self): + def umount(self): p = Popen(["/bin/umount", self.dest]) p.communicate() if p.returncode and p.returncode != 0: raise OSError(_("Failed to unmount image %s from %s") % (self.image, self.dest)) - def __create_image(self): + def create_image(self): fd = open(self.image, "w") fd.truncate(self.size) fd.close() @@ -553,7 +553,7 @@ PrivateNetwork=false selinux.restorecon(config) sys.stdout.write(_("Created sandbox config %s\n") % config) - def __get_image_path(self): + def get_image_path(self): mounts = self.config.get_mounts() for m in mounts: if type(m) != LibvirtSandbox.ConfigMountHostImage: @@ -563,7 +563,7 @@ PrivateNetwork=false return m.get_source() return None - def _delete(self): + def delete(self): # Should be stored in config try: fd=open(self.dest + self.MACHINE_ID, "r") @@ -577,7 +577,7 @@ PrivateNetwork=false if os.path.exists(self.dest): shutil.rmtree(self.dest) - mount_path = self.__get_image_path() + mount_path = self.get_image_path() if mount_path: os.remove(mount_path) @@ -615,36 +615,36 @@ PrivateNetwork=false except: pass - self._delete() + self.delete() - def _create(self): - self.__connect() + def create_service(self): + self.connect() self.config.set_shell(True) self.config.set_boot_target("multi-user.target") - self.__extract_rpms() - self.__gen_filesystems() + self.extract_rpms() + self.gen_filesystems() os.mkdir(self.dest) if self.image: - self.__create_image() - self.__gen_content() - self.__umount() + self.create_image() + self.gen_content() + self.umount() sys.stdout.write(_("Created sandbox container image %s\n") % self.image) else: - self.__gen_content() + self.gen_content() sys.stdout.write(_("Created sandbox container dir %s\n") % self.dest) self.set_security_label() self.save_config() - self.__create_system_unit() + self.create_system_unit() def create(self): if os.path.exists(self.dest): raise OSError(_("%s already exists") % self.dest) try: - self._create() + self.create_service() except Exception, e: try: - self._delete() + self.delete() except Exception, e2: pass raise e @@ -662,12 +662,12 @@ PrivateNetwork=false args.command = [ "systemctl", "reload" ] + map(lambda x: x[0], unitfiles) execute(args) - def __connect(self): + def connect(self): if not self.conn: self.conn=LibvirtGObject.Connection.new(self.uri) self.conn.open(None) - def __disconnect(self): + def disconnect(self): if self.conn: self.conn.close() self.conn = None @@ -676,10 +676,10 @@ PrivateNetwork=false def closed(obj, error): self.loop.quit() try: - self.__connect() + self.connect() context = LibvirtSandbox.ContextService.new(self.conn, self.config) context.attach() - self.__disconnect() + self.disconnect() return 1 except GLib.GError, e: return 0 @@ -689,7 +689,7 @@ PrivateNetwork=false self.loop.quit() try: - self.__connect() + self.connect() context = LibvirtSandbox.ContextService.new(self.conn, self.config) context.start() console = context.get_log_console() @@ -710,7 +710,7 @@ PrivateNetwork=false def stop(self): try: - self.__connect() + self.connect() context = LibvirtSandbox.ContextService.new(self.conn, self.config) context.attach() context.stop() @@ -722,7 +722,7 @@ PrivateNetwork=false self.loop.quit() try: - self.__connect() + self.connect() context = LibvirtSandbox.ContextService.new(self.conn, self.config) context.attach() console = context.get_shell_console() @@ -742,7 +742,7 @@ PrivateNetwork=false self.loop.quit() try: - self.__connect() + self.connect() context = LibvirtSandbox.ContextService.new(self.conn, self.config) context.attach() console = context.get_shell_console() -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:25PM -0400, Dan Walsh wrote:
This patch removes all __METHOD and _METHOD functions calls. Since it is not intended that virt-sandbox-service will be imported into another python module, there is limited value to using the internal indicators.
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 118 +++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 59 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

This patch moves CONFIG_PATH external from the Container Class. This will eliminate the need to create a container to get this constant. Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 43158de..df88284 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -50,11 +50,17 @@ except IOError: import __builtin__ __builtin__.__dict__['_'] = unicode +CONFIG_PATH = "/etc/libvirt-sandbox/services/" +def get_config_path(name): + return CONFIG_PATH + name + ".sandbox" + +def read_config(name): + return LibvirtSandbox.Config.load_from_path(get_config_path(name)) + class Container: IGNORE_DIRS = [ "/var/run/", "/etc/logrotate.d/", "/etc/pam.d" ] DEFAULT_DIRS = [ "/etc", "/var" ] PROFILE_FILES = [ ".bashrc", ".bash_profile" ] - CONFIG_PATH = "/etc/libvirt-sandbox/services/" MACHINE_ID = "/etc/machine-id" HOSTNAME = "/etc/hostname" FUNCTIONS = "/etc/rc.d/init.d/functions" @@ -214,7 +220,7 @@ WantedBy=%(TARGET)s def get_config_path(self, name = None): if not name: name = self.get_name() - return self.CONFIG_PATH + name + ".sandbox" + return get_config_path() def get_filesystem_path(self, name = None): if not name: @@ -790,8 +796,7 @@ def usage(parser, msg): def sandbox_list(args): import glob - container = Container() - g = glob.glob(container.CONFIG_PATH + "*.sandbox") + g = glob.glob(CONFIG_PATH + "*.sandbox") g.sort() for gc in g: try: -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:26PM -0400, Dan Walsh wrote:
This patch moves CONFIG_PATH external from the Container Class. This will eliminate the need to create a container to get this constant.
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

GlibGerror can be raised by virt-sandbox-service, this patch will catch the exception and write the error to stderr. Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index df88284..f4df262 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -1084,3 +1084,7 @@ if __name__ == '__main__': sys.stderr.write("%s: %s\n" % (sys.argv[0], e)) sys.stderr.flush() sys.exit(1) + except GLib.GError, e: + sys.stderr.write("%s: %s\n" % (sys.argv[0], e)) + sys.stderr.flush() + sys.exit(1) -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:27PM -0400, Dan Walsh wrote:
GlibGerror can be raised by virt-sandbox-service, this patch will catch the exception and write the error to stderr.
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 4 ++++ 1 file changed, 4 insertions(+)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

save_config uses an internal variable to indicate the path to the virt-sandbox configuration file, this path renames this variable to prevent confusion. Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index f4df262..91ac914 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -551,13 +551,13 @@ PrivateNetwork=false raise OSError(_("Failed to mount image %s on %s") % (self.image, self.dest)) def save_config(self): - config = self.get_config_path() - if os.path.exists(config): - os.remove(config) - self.config.save_to_path(config) + config_path = self.get_config_path() + if os.path.exists(config_path): + os.remove(config_path) + self.config.save_to_path(config_path) if selinux is not None: - selinux.restorecon(config) - sys.stdout.write(_("Created sandbox config %s\n") % config) + selinux.restorecon(config_path) + sys.stdout.write(_("Created sandbox config %s\n") % config_path) def get_image_path(self): mounts = self.config.get_mounts() -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:28PM -0400, Dan Walsh wrote:
save_config uses an internal variable to indicate the path to the virt-sandbox configuration file, this path renames this variable to prevent confusion.
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

This way we can share common methods between the ServiceContainer and the InteractiveContainer (Patch to be added) --- bin/virt-sandbox-service | 754 ++++++++++++++++++++++++----------------------- 1 file changed, 385 insertions(+), 369 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 91ac914..8a1d268 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -58,6 +58,318 @@ def read_config(name): return LibvirtSandbox.Config.load_from_path(get_config_path(name)) class Container: + DEFAULT_PATH = "/var/lib/libvirt/filesystems" + DEFAULT_IMAGE = "/var/lib/libvirt/images/%s.raw" + SELINUX_FILE_TYPE = "svirt_lxc_file_t" + + def __init__(self, name=None, uri = "lxc:///", path = DEFAULT_PATH, config=None, create=False): + self.uri = uri + self.use_image = False + self.size = 10 * MB + self.path = path + self.config = None + if self.config: + self.name = self.config.get_name() + else: + self.name = name + self.dest = "%s/%s" % (self.path, self.name) + self.file_type = self.SELINUX_FILE_TYPE + self.conn = None + self.image = None + self.uid = 0 + + def get_file_type(self): + return self.file_type + + def set_file_type(self, file_type): + self.file_type = file_type + + def set_uid(self, uid): + self.uid = uid + + def get_uid(self): + return self.uid + + def get_config_path(self, name = None): + if not name: + name = self.name + return get_config_path(name) + + def get_filesystem_path(self, name = None): + if not name: + name = self.get_name() + return self.DEFAULT_PATH + "/" + name + + def get_image_path(self, name = None): + if not name: + name = self.get_name() + return self.DEFAULT_IMAGE % name + + def set_image(self, size): + self.use_image = True + self.size = size * MB + + def set_path(self, path): + self.path = path + self.dest = "%s/%s" % (self.path, self.name) + + def get_name(self): + return self.name + + def set_name(self, name): + if self.config: + raise ValueError([_("Cannot modify Name")]) + self.name = name + self.dest = "%s/%s" % (self.path, self.name) + + def set_security(self, val): + return self.config.set_security_opts(val) + + def add_network(self, val): + return self.config.add_network_opts(val) + + def get_security_dynamic(self): + return self.config.get_security_dynamic() + + def get_security_label(self): + return self.config.get_security_label() + + def set_security_label(self): + if selinux is None: + return + + if self.image or self.get_security_dynamic(): + return + + selabel = self.get_security_label() + if selabel is None: + raise ValueError([_("Missing security label configuration")]) + parts = selabel.split(":") + selinux.chcon(self.dest, "system_u:object_r:%s:%s" % ( + self.get_file_type(), ":".join(parts[3:])), True) + + def gen_filesystems(self): + if self.use_image: + self.image = self.DEFAULT_IMAGE % self.get_name() + mount = LibvirtSandbox.ConfigMountHostImage.new(self.image, self.dest) + self.config.add_mount(mount) + + # 10 MB /run + mount = LibvirtSandbox.ConfigMountRam.new("/run", 10 * 1024 * 1024); + self.config.add_mount(mount) + + # 100 MB /tmp + mount = LibvirtSandbox.ConfigMountRam.new("/tmp", 100 * 1024 * 1024); + self.config.add_mount(mount) + + # 100 MB /tmp + mount = LibvirtSandbox.ConfigMountRam.new("/dev/shm", 100 * 1024 * 1024); + self.config.add_mount(mount) + + def fix_stat(self, f): + try: + s = os.stat(f) + path = "%s%s" % (self.dest, f) + os.chown(path, s.st_uid, s.st_gid) + os.chmod(path, s.st_mode) + except OSError, e: + if not e.errno == errno.ENOENT: + raise e + + def fix_protection(self): + l = len(self.dest) + for root, dirs, files in os.walk(self.dest): + for f in files: + dest = root + "/" + f + self.fix_stat(dest[l:]) + for d in dirs: + dest = root + "/" + d + self.fix_stat(dest[l:]) + + def makedirs(self, d): + try: + path = "%s%s" % (self.dest, d) + os.makedirs(path) + except OSError, e: + if not e.errno == errno.EEXIST: + raise e + + def makefile(self, f): + self.makedirs(os.path.dirname(f)) + try: + path = "%s%s" % (self.dest, f) + fd=open(path, "w") + fd.close() + except OSError, e: + if not e.errno == errno.EEXIST: + raise e + + def umount(self): + p = Popen(["/bin/umount", self.dest]) + p.communicate() + if p.returncode and p.returncode != 0: + raise OSError(_("Failed to unmount image %s from %s") % (self.image, self.dest)) + + def create_image(self): + fd = open(self.image, "w") + fd.truncate(self.size) + fd.close() + p = Popen(["/sbin/mkfs","-F", "-t", "ext4", self.image],stdout=PIPE, stderr=PIPE) + p.communicate() + if p.returncode and p.returncode != 0: + raise OSError(_("Failed to build image %s") % self.image ) + + p = Popen(["/bin/mount", self.image, self.dest]) + p.communicate() + if p.returncode and p.returncode != 0: + raise OSError(_("Failed to mount image %s on %s") % (self.image, self.dest)) + + def save_config(self): + config_path = self.get_config_path() + if os.path.exists(config_path): + os.remove(config_path) + self.config.save_to_path(config_path) + if selinux is not None: + selinux.restorecon(config_path) + sys.stdout.write(_("Created sandbox config %s\n") % config_path) + + def delete(self): + # Stop service if it is running + try: + self.stop() + except: + pass + + config = self.get_config_path() + if os.path.exists(config): + os.remove(config) + + print (_("You need to manually remove the '%s' content") % self.name) + return + + # Not sure we should remove content + if os.path.exists(self.dest): + shutil.rmtree(self.dest) + mount_path = self.get_image_path() + if mount_path: + os.remove(mount_path) + + image = self.get_image_path() + if os.path.exists(image): + os.remove(image) + + def create(self): + self.connect() + self.config.set_shell(True) + os.mkdir(self.dest) + + def connect(self): + if not self.conn: + self.conn=LibvirtGObject.Connection.new(self.uri) + self.conn.open(None) + + def disconnect(self): + if self.conn: + self.conn.close() + self.conn = None + + def running(self): + def closed(obj, error): + self.loop.quit() + try: + self.connect() + context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context.attach() + self.disconnect() + return 1 + except GLib.GError, e: + return 0 + + def start(self): + def closed(obj, error): + self.loop.quit() + + try: + self.connect() + context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context.start() + console = context.get_log_console() + console.connect("closed", closed) + console.attach_stderr() + self.loop = GLib.MainLoop() + self.loop.run() + try: + console.detach() + except: + pass + try: + context.stop() + except: + pass + except GLib.GError, e: + raise OSError(str(e)) + + def stop(self): + try: + self.connect() + context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context.attach() + context.stop() + except GLib.GError, e: + raise OSError(str(e)) + + def connect(self): + def closed(obj, error): + self.loop.quit() + + try: + self.connect() + context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context.attach() + console = context.get_shell_console() + console.connect("closed", closed) + console.attach_stdio() + self.loop = GLib.MainLoop() + self.loop.run() + try: + console.detach() + except: + pass + except GLib.GError, e: + raise OSError(str(e)) + + def execute(self, command): + def closed(obj, error): + self.loop.quit() + + try: + self.connect() + context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context.attach() + console = context.get_shell_console() + console.connect("closed", closed) + console.attach_stdio() + print "not currently implemented" + console.detach() + return + self.loop = GLib.MainLoop() + self.loop.run() + try: + console.detach() + except: + pass + except GLib.GError, e: + raise OSError(str(e)) + + def add_bind_mount(self, source, dest): + mount = LibvirtSandbox.ConfigMountHostBind.new(source, dest) + self.config.add_mount(mount) + + def add_ram_mount(self, dest, size): + mount = LibvirtSandbox.ConfigMountRam.new(dest, size); + self.config.add_mount(mount) + +class ServiceContainer(Container): IGNORE_DIRS = [ "/var/run/", "/etc/logrotate.d/", "/etc/pam.d" ] DEFAULT_DIRS = [ "/etc", "/var" ] PROFILE_FILES = [ ".bashrc", ".bash_profile" ] @@ -73,41 +385,16 @@ class Container: BIND_SYSTEM_FILES = [ MACHINE_ID, "/etc/fstab", HOSTNAME ] LOCAL_LINK_FILES = { SYSINIT_WANTS_PATH : [ "systemd-tmpfiles-setup.service" ] , SOCKET_WANTS_PATH : [ "dbus.socket", "systemd-journald.socket", "systemd-shutdownd.socket" ] } - SELINUX_FILE_TYPE = "svirt_lxc_file_t" - DEFAULT_PATH = "/var/lib/libvirt/filesystems" - DEFAULT_IMAGE = "/var/lib/libvirt/images/%s.raw" DEFAULT_UNIT = "/etc/systemd/system/%s_sandbox.service" - def __init__(self, name=None, uri = "lxc:///", path = DEFAULT_PATH, config=None, create=False): - self.uri = uri + def __init__(self, name=None, uri = "lxc:///", path = Container.DEFAULT_PATH, config=None, create=False): + Container.__init__(self, name, uri, path, config, create) self.copy = False - self.use_image = False - self.path = path - self.conn = None - self.image = None - self.size = 10 * MB - self.config = None - self.unitfile = None self.unit_file_list = [] - self.name = name - - if name: - config = self.get_config_path(name) - self.dest = "%s/%s" % (self.path, name) - if create: - if config and os.path.exists(config): - raise ValueError([_("Container already exists")]) - self.config = LibvirtSandbox.ConfigService.new(name) - return - - if config: - try: - self.config = LibvirtSandbox.Config.load_from_path(config) - self.unitfile = self.get_unit_path() - except GLib.GError, e: - raise OSError(config + ": " + str(e)) + else: + self.unitfile = self.get_unit_path() def follow_units(self): unitst="" @@ -128,14 +415,11 @@ class Container: return self.unit_file_list[0][0].split(".")[0] def get_sandbox_target(self): - if len(self.unit_file_list) > 1: - raise ValueError([_("Only Valid for single units")]) return "%s_sandbox.target" % self.get_sandboxed_service() - def target(self): + def create_target(self, name): try: - name = self.get_sandbox_target() - path = "/etc/systemd/system/" + name + path = "/etc/systemd/system/%s_sandbox.target" % name if not os.path.exists(path): fd = open(path, "w") fd.write(""" @@ -151,16 +435,18 @@ class Container: Description=%(NAME)s Sandbox Container Target Documentation=man:virt-sandbox-service(1) -[Install] -WantedBy=multi-user.target """ % { "NAME" : self.get_sandboxed_service() }) - return "%s" % name + except ValueError: + return "" except OSError: return "" + path += ".wants" + if not os.path.exists(path): + os.makedirs(path) + os.symlink(self.get_unit_path(), path + "/" + os.path.basename(self.get_unit_path())) def create_system_unit(self): self.unitfile = self.get_unit_path() - name = self.config.get_name() unit = r""" [Unit] Description=Secure Sandbox Container %(NAME)s @@ -175,17 +461,16 @@ ExecStop=/usr/bin/virt-sandbox-service stop %(NAME)s [Install] WantedBy=%(TARGET)s -""" % { 'NAME':name, 'FOLLOW':self.follow_units(), 'TARGET':self.target(), 'RELOAD': " -u ".join(map(lambda x: x[0], self.unit_file_list)) } +""" % { 'NAME':self.name, 'FOLLOW':self.follow_units(), 'TARGET':self.get_sandbox_target(), 'RELOAD': " -u ".join(map(lambda x: x[0], self.unit_file_list)) } + fd = open(self.unitfile, "w") fd.write(unit) fd.close() if selinux is not None: selinux.restorecon(self.unitfile) - p = Popen(["/usr/bin/systemctl","enable", self.unitfile],stdout=PIPE, stderr=PIPE) - p.communicate() - if p.returncode and p.returncode != 0: - raise OSError(_("Failed to enable %s unit file") % self.unitfile) sys.stdout.write(_("Created unit file %s\n") % self.unitfile) + for i, src in self.unit_file_list: + self.create_target(i.split(".service")[0]) def add_dir(self, newd): if newd in self.all_dirs: @@ -201,90 +486,32 @@ WantedBy=%(TARGET)s if newd.startswith(d): return if not d.startswith(newd): - tmp_dirs.append(d) - self.dirs = tmp_dirs - self.dirs.append(newd) - break; - - def add_file(self, newf): - if newf in self.files: - return - for d in self.IGNORE_DIRS: - if newf.startswith(d): - return - for d in self.DEFAULT_DIRS: - if newf.startswith(d): - self.files.append(newf) - break; - - def get_config_path(self, name = None): - if not name: - name = self.get_name() - return get_config_path() - - def get_filesystem_path(self, name = None): - if not name: - name = self.get_name() - return self.DEFAULT_PATH + "/" + name - - def get_image_path(self, name = None): - if not name: - name = self.get_name() - return self.DEFAULT_IMAGE % name - - def get_name(self): - if self.config: - return self.config.get_name() - raise ValueError([_("Name not configured")]) - - def set_copy(self, copy): - self.copy = copy - - def set_security(self, val): - return self.config.set_security_opts(val) - - def add_network(self, val): - return self.config.add_network_opts(val) - - def get_security_dynamic(self): - return self.config.get_security_dynamic() - - def get_security_label(self): - return self.config.get_security_label() - - def set_security_label(self): - if selinux is None: - return - - if self.image or self.get_security_dynamic(): - return - - selabel = self.get_security_label() - if selabel is None: - raise ValueError([_("Missing security label configuration")]) - parts = selabel.split(":") - if len(parts) != 5 and len(parts) != 4: - raise ValueError([_("Expected 5 parts in SELinux security label %s") % parts]) + tmp_dirs.append(d) + self.dirs = tmp_dirs + self.dirs.append(newd) + break; - if len(parts) == 5: - selinux.chcon(self.dest, "system_u:object_r:%s:%s:%s" % ( - self.SELINUX_FILE_TYPE, parts[3], parts[4]), True) - else: - selinux.chcon(self.dest, "system_u:object_r:%s:%s" % ( - self.SELINUX_FILE_TYPE, parts[3]), True) + def add_file(self, newf): + if newf in self.files: + return + for d in self.IGNORE_DIRS: + if newf.startswith(d): + return + for d in self.DEFAULT_DIRS: + if newf.startswith(d): + self.files.append(newf) + break; - def set_image(self, size): - self.use_image = True - self.size = size * MB + def get_name(self): + if self.config: + return self.config.get_name() + raise ValueError([_("Name not configured")]) - def set_path(self, path): - self.path = path + def set_copy(self, copy): + self.copy = copy - def set_name(self, name): - if self.config: - raise ValueError([_("Cannot modify Name")]) - self.dest = "%s/%s" % (self.path, self.name) - self.config = LibvirtSandbox.ConfigService.new(name) + def get_security_dynamic(self): + return self.config.get_security_dynamic() def extract_rpms(self): self.all_dirs = [] @@ -353,10 +580,6 @@ WantedBy=%(TARGET)s if os.path.isfile(fname): self.add_file(fname) - def add_mount(self, source, dest): - mount = LibvirtSandbox.ConfigMountHostBind.new(source, dest) - self.config.add_mount(mount) - def gen_hostname(self): fd=open(self.dest + self.HOSTNAME, "w") fd.write("%s\n" % self.name ) @@ -383,32 +606,16 @@ WantedBy=%(TARGET)s os.symlink(self.dest + jpath, jpath) def gen_filesystems(self): - if self.use_image: - self.image = self.DEFAULT_IMAGE % self.get_name() - mount = LibvirtSandbox.ConfigMountHostImage.new(self.image, self.dest) - self.config.add_mount(mount) - - # 10 MB /run - mount = LibvirtSandbox.ConfigMountRam.new("/run", 10 * 1024 * 1024); - self.config.add_mount(mount) - - # 100 MB /tmp - mount = LibvirtSandbox.ConfigMountRam.new("/tmp", 100 * 1024 * 1024); - self.config.add_mount(mount) - - # 100 MB /tmp - mount = LibvirtSandbox.ConfigMountRam.new("/dev/shm", 100 * 1024 * 1024); - self.config.add_mount(mount) - + Container.gen_filesystems(self) for d in self.BIND_SYSTEM_DIRS: if os.path.exists(d): source = "%s%s" % ( self.dest, d) - self.add_mount(source, d) + self.add_bind_mount(source, d) for f in self.BIND_SYSTEM_FILES: if os.path.exists(f): source = "%s%s" % ( self.dest, f) - self.add_mount(source, f) + self.add_bind_mount(source, f) for d in self.dirs: found = False @@ -419,10 +626,7 @@ WantedBy=%(TARGET)s break if not found: source = "%s%s" % ( self.dest, d) - self.add_mount(source, d) - - def get_init_path(self): - return "%s/%s/init" % (self.path, self.get_name()) + self.add_bind_mount(source, d) def create_container_unit(self, src, dest, unit): fd = open(dest + "/" + unit, "w") @@ -433,44 +637,6 @@ PrivateNetwork=false """ % src ) fd.close() - def fix_stat(self, f): - try: - s = os.stat(f) - path = "%s%s" % (self.dest, f) - os.chown(path, s.st_uid, s.st_gid) - os.chmod(path, s.st_mode) - except OSError, e: - if not e.errno == errno.ENOENT: - raise e - - def fix_protection(self): - l = len(self.dest) - for root, dirs, files in os.walk(self.dest): - for f in files: - dest = root + "/" + f - self.fix_stat(dest[l:]) - for d in dirs: - dest = root + "/" + d - self.fix_stat(dest[l:]) - - def makedirs(self, d): - try: - path = "%s%s" % (self.dest, d) - os.makedirs(path) - except OSError, e: - if not e.errno == errno.EEXIST: - raise e - - def makefile(self, f): - self.makedirs(os.path.dirname(f)) - try: - path = "%s%s" % (self.dest, f) - fd=open(path, "w") - fd.close() - except OSError, e: - if not e.errno == errno.EEXIST: - raise e - def gen_content(self): if self.copy: for d in self.dirs: @@ -494,7 +660,6 @@ PrivateNetwork=false shutil.copy(self.FUNCTIONS, "%s%s" % (self.dest, self.FUNCTIONS)) self.gen_machine_id() - self.gen_hostname() for k in self.LOCAL_LINK_FILES: @@ -530,47 +695,10 @@ PrivateNetwork=false self.fix_protection() - def umount(self): - p = Popen(["/bin/umount", self.dest]) - p.communicate() - if p.returncode and p.returncode != 0: - raise OSError(_("Failed to unmount image %s from %s") % (self.image, self.dest)) - - def create_image(self): - fd = open(self.image, "w") - fd.truncate(self.size) - fd.close() - p = Popen(["/sbin/mkfs","-F", "-t", "ext4", self.image],stdout=PIPE, stderr=PIPE) - p.communicate() - if p.returncode and p.returncode != 0: - raise OSError(_("Failed to build image %s") % self.image ) - - p = Popen(["/bin/mount", self.image, self.dest]) - p.communicate() - if p.returncode and p.returncode != 0: - raise OSError(_("Failed to mount image %s on %s") % (self.image, self.dest)) - - def save_config(self): - config_path = self.get_config_path() - if os.path.exists(config_path): - os.remove(config_path) - self.config.save_to_path(config_path) - if selinux is not None: - selinux.restorecon(config_path) - sys.stdout.write(_("Created sandbox config %s\n") % config_path) - - def get_image_path(self): - mounts = self.config.get_mounts() - for m in mounts: - if type(m) != LibvirtSandbox.ConfigMountHostImage: - continue - - if m.get_target() == self.dest: - return m.get_source() - return None - def delete(self): - # Should be stored in config + # + # Delete a ServiceContainer + # try: fd=open(self.dest + self.MACHINE_ID, "r") uuid = fd.read().rstrip() @@ -579,21 +707,10 @@ PrivateNetwork=false if os.path.exists(jpath): os.remove(jpath) except Exception, e: - pass - - if os.path.exists(self.dest): - shutil.rmtree(self.dest) - mount_path = self.get_image_path() - if mount_path: - os.remove(mount_path) - - config = self.get_config_path() - if os.path.exists(config): - os.remove(config) + sys.stderr.write("%s: %s\n" % (sys.argv[0], e)) + sys.stderr.flush() - image = self.get_image_path() - if os.path.exists(image): - os.remove(image) + Container.delete(self) if self.unitfile is not None and os.path.exists(self.unitfile): p = Popen(["/usr/bin/systemctl","disable", self.unitfile],stdout=PIPE, stderr=PIPE) @@ -614,22 +731,13 @@ PrivateNetwork=false if not os.path.exists(target + ".wants"): os.remove(target) - def delete(self): - # Stop service if it is running - try: - self.stop() - except: - pass - - self.delete() - def create_service(self): - self.connect() - self.config.set_shell(True) - self.config.set_boot_target("multi-user.target") + # + # Create a ServiceContainer + # self.extract_rpms() + Container.create(self) self.gen_filesystems() - os.mkdir(self.dest) if self.image: self.create_image() self.gen_content() @@ -639,8 +747,9 @@ PrivateNetwork=false self.gen_content() sys.stdout.write(_("Created sandbox container dir %s\n") % self.dest) self.set_security_label() - self.save_config() self.create_system_unit() + self.config.set_boot_target("multi-user.target") + self.save_config() def create(self): if os.path.exists(self.dest): @@ -657,7 +766,7 @@ PrivateNetwork=false def reload(self, unitfiles): # - # Reload Container + # Reload a ServiceContainer # class Args: command = [] @@ -668,119 +777,22 @@ PrivateNetwork=false args.command = [ "systemctl", "reload" ] + map(lambda x: x[0], unitfiles) execute(args) - def connect(self): - if not self.conn: - self.conn=LibvirtGObject.Connection.new(self.uri) - self.conn.open(None) - - def disconnect(self): - if self.conn: - self.conn.close() - self.conn = None - - def running(self): - def closed(obj, error): - self.loop.quit() - try: - self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) - context.attach() - self.disconnect() - return 1 - except GLib.GError, e: - return 0 - - def start(self): - def closed(obj, error): - self.loop.quit() - - try: - self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) - context.start() - console = context.get_log_console() - console.connect("closed", closed) - console.attach_stderr() - self.loop = GLib.MainLoop() - self.loop.run() - try: - console.detach() - except: - pass - try: - context.stop() - except: - pass - except GLib.GError, e: - raise OSError(str(e)) - - def stop(self): - try: - self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) - context.attach() - context.stop() - except GLib.GError, e: - raise OSError(str(e)) - - def connect(self): - def closed(obj, error): - self.loop.quit() - - try: - self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) - context.attach() - console = context.get_shell_console() - console.connect("closed", closed) - console.attach_stdio() - self.loop = GLib.MainLoop() - self.loop.run() - try: - console.detach() - except: - pass - except GLib.GError, e: - raise OSError(str(e)) - - def execute(self, command): - def closed(obj, error): - self.loop.quit() - - try: - self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) - context.attach() - console = context.get_shell_console() - console.connect("closed", closed) - console.attach_stdio() - print "not currently implemented" - console.detach() - return - self.loop = GLib.MainLoop() - self.loop.run() - try: - console.detach() - except: - pass - except GLib.GError, e: - raise OSError(str(e)) - MB = int(1000000) def delete(args): - container = Container(args.name) + config = read_config(args.name) + container = ServiceContainer(uri=args.uri, config = config) container.delete() def create(args): - container = Container(name = args.name, create = True) + container = ServiceContainer(name = args.name, uri=args.uri, create = True) container.set_copy(args.copy) - if args.network: - for net in args.network: - container.add_network(net) + for net in args.network: + container.add_network(net) if args.security: container.set_security(args.security) container.set_unit_file_list(args.unitfiles) + container.set_path(args.path) if args.imagesize: container.set_image(args.imagesize) @@ -800,7 +812,7 @@ def sandbox_list(args): g.sort() for gc in g: try: - c = Container(config = gc) + c = LibvirtSandbox.Config.load_from_path(gc) if args.running: if c.running(): print c.get_name() @@ -813,17 +825,19 @@ def sandbox_list(args): def sandbox_reload(args): config = read_config(args.name) - container = Container(uri = args.uri, config = config) + container = ServiceContainer(uri = args.uri, config = config) container.reload(args.unitfiles) def start(args): os.execl("/usr/libexec/virt-sandbox-service-util", "virt-sandbox-service-util","-s", args.name) -# container = Container(args.name, args.uri) +# config = read_config(args.name) +# container = Container(uri = args.uri, config=config) # container.start() def stop(args): os.execl("/usr/libexec/virt-sandbox-service-util", "virt-sandbox-service-util","-S", args.name) -# container = Container(args.name, args.uri) +# config = read_config(args.name) +# container = Container(uri = args.uri, config=config) # container.stop() def connect(args): @@ -832,7 +846,8 @@ Connected to %s. Type 'Ctrl + ]' to detach from the console. """ % ( args.name ) os.execl("/usr/libexec/virt-sandbox-service-util", "virt-sandbox-service-util","-a", args.name) -# container = Container(args.name, args.uri) +# config = read_config(args.name) +# container = Container(uri = args.uri, config=config) # container.connect() # @@ -859,7 +874,8 @@ def execute(args): # os.execv("/usr/libexec/virt-sandbox-service-util", myexec) def clone(args): - container = Container(args.source, args.uri) + config = read_config(args.source) + container = Container(uri = args.uri, config=config) fd = open(container.get_config_path(),"r") recs = fd.read() fd.close() @@ -892,7 +908,7 @@ def clone(args): fd.close() sys.stdout.write(_("Created unit file %s\n") % new_unit) - container = Container(args.dest, args.uri) + container = ServiceContainer(name=args.dest, uri=args.uri, create=True) if args.security: container.set_security(args.security) container.gen_machine_id() @@ -1021,7 +1037,7 @@ def gen_reload_args(subparser): def gen_clone_args(subparser): parser = subparser.add_parser("clone", - help=_("Clone an existing sandbox container")) + help=_("Clone an existing sandbox container")) parser.set_defaults(func=clone) parser.add_argument("-s", "--security", dest="security", default=default_security_opts(), -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:29PM -0400, Dan Walsh wrote:
This way we can share common methods between the ServiceContainer and the InteractiveContainer (Patch to be added) --- bin/virt-sandbox-service | 754 ++++++++++++++++++++++++----------------------- 1 file changed, 385 insertions(+), 369 deletions(-)
container.set_copy(args.copy) - if args.network: - for net in args.network: - container.add_network(net) + for net in args.network: + container.add_network(net)
Hmm, I had the 'if args.network' because this would raise an error about 'args.network' not existing, if no --network args were provided on the command line. Are you sure this still works when no --network args are used ? ACK if this issue is not a problem anymore, or if this chunk is reverted. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 04/05/2013 07:10 AM, Daniel P. Berrange wrote:
On Wed, Apr 03, 2013 at 07:17:29PM -0400, Dan Walsh wrote:
This way we can share common methods between the ServiceContainer and the InteractiveContainer (Patch to be added) --- bin/virt-sandbox-service | 754 ++++++++++++++++++++++++----------------------- 1 file changed, 385 insertions(+), 369 deletions(-)
container.set_copy(args.copy) - if args.network: - for net in args.network: - container.add_network(net) + for net in args.network: + container.add_network(net)
Hmm, I had the 'if args.network' because this would raise an error about 'args.network' not existing, if no --network args were provided on the command line. Are you sure this still works when no --network args are used ?
ACK if this issue is not a problem anymore, or if this chunk is reverted.
Daniel
This command initializes the "network" to [], the previous code did not specify a default which implies default=None. My code added a default to an empty list which is why the code above works. - - parser.add_argument("-N", "--network", dest="network", - - action=SetNet, - - help=_("Specify the network configuration")) + parser.add_argument("-n", "--network", dest="network", + action=SetNet, default=[], + help=_("Specify the network configuration")) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.13 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlFf+4gACgkQrlYvE4MpobMM1ACfZAawIVppXng3pGd3KBxUTEHI B5cAniiPBz6DAglamMzv+wSYK296jj/E =v9ro -----END PGP SIGNATURE-----

First use case will be OpenShift Differentiate on create based on whether one or more unit files specified (ServiceContainer), or a command is specified (Interactive Container). Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 165 ++++++++++++++++++++-------- bin/virt-sandbox-service-bash-completion.sh | 16 +-- bin/virt-sandbox-service-create.pod | 15 ++- 3 files changed, 136 insertions(+), 60 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 8a1d268..8571374 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -67,7 +67,7 @@ class Container: self.use_image = False self.size = 10 * MB self.path = path - self.config = None + self.config = config if self.config: self.name = self.config.get_name() else: @@ -273,12 +273,18 @@ class Container: self.conn.close() self.conn = None + def context(self): + if isinstance(self.config, gi.repository.LibvirtSandbox.ConfigInteractive): + return LibvirtSandbox.ContextInteractive.new(self.conn, self.config) + + return LibvirtSandbox.ContextService.new(self.conn, self.config) + def running(self): def closed(obj, error): self.loop.quit() try: self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context = self.context() context.attach() self.disconnect() return 1 @@ -291,7 +297,7 @@ class Container: try: self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context = self.context() context.start() console = context.get_log_console() console.connect("closed", closed) @@ -312,19 +318,19 @@ class Container: def stop(self): try: self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context = self.context() context.attach() context.stop() except GLib.GError, e: raise OSError(str(e)) - def connect(self): + def console(self): def closed(obj, error): self.loop.quit() try: self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context = self.context() context.attach() console = context.get_shell_console() console.connect("closed", closed) @@ -344,7 +350,7 @@ class Container: try: self.connect() - context = LibvirtSandbox.ContextService.new(self.conn, self.config) + context = self.context() context.attach() console = context.get_shell_console() console.connect("closed", closed) @@ -369,6 +375,45 @@ class Container: mount = LibvirtSandbox.ConfigMountRam.new(dest, size); self.config.add_mount(mount) +class InteractiveContainer(Container): + def __init__(self, name=None, uri = "lxc:///", path = Container.DEFAULT_PATH, config=None, create=False): + Container.__init__(self, name, uri, path, config, create) + + if create: + self.config = LibvirtSandbox.ConfigInteractive.new(name) + + def gen_filesystems(self): + Container.gen_filesystems(self) + self.add_bind_mount(self.dest, self.path) + + def create_interactive(self): + # + # Create an InteractiveContainer + # + Container.create(self) + self.gen_filesystems() + + if self.image: + self.create_image() + self.umount() + sys.stdout.write(_("Created sandbox container image %s\n") % self.image) + else: + sys.stdout.write(_("Created sandbox container dir %s\n") % self.dest) + self.save_config() + + def create(self): + try: + self.create_interactive() + except Exception, e: + try: + self.delete() + except Exception, e2: + pass + raise e + + def set_command(self, command): + self.config.set_command(command) + class ServiceContainer(Container): IGNORE_DIRS = [ "/var/run/", "/etc/logrotate.d/", "/etc/pam.d" ] DEFAULT_DIRS = [ "/etc", "/var" ] @@ -781,19 +826,32 @@ MB = int(1000000) def delete(args): config = read_config(args.name) - container = ServiceContainer(uri=args.uri, config = config) + if isinstance(config, gi.repository.LibvirtSandbox.ConfigInteractive): + container = InteractiveContainer(uri=args.uri, config = config) + else: + container = ServiceContainer(uri=args.uri, config = config) container.delete() def create(args): - container = ServiceContainer(name = args.name, uri=args.uri, create = True) - container.set_copy(args.copy) + if len(args.command) > 0 and len(args.unitfiles) > 0: + raise ValueError([_("Commands can not be specified with unit files")]) + + if len(args.command) == 0 and len(args.unitfiles) == 0: + raise ValueError([_("You must specify a command or a unit file")]) + + if len(args.command) > 0: + container = InteractiveContainer(name = args.name, uri=args.uri, create = True) + container.set_command(args.command) + else: + container = ServiceContainer(name = args.name, uri=args.uri, create = True) + container.set_copy(args.copy) + container.set_unit_file_list(args.unitfiles) for net in args.network: container.add_network(net) if args.security: container.set_security(args.security) - container.set_unit_file_list(args.unitfiles) container.set_path(args.path) - + container.set_file_type(args.file_type) if args.imagesize: container.set_image(args.imagesize) @@ -814,7 +872,12 @@ def sandbox_list(args): try: c = LibvirtSandbox.Config.load_from_path(gc) if args.running: - if c.running(): + if isinstance(c, gi.repository.LibvirtSandbox.ConfigInteractive): + container = InteractiveContainer(uri=args.uri, config=c) + else: + container = ServiceContainer(uri=args.uri, config=c) + + if container.running(): print c.get_name() else: print c.get_name() @@ -822,9 +885,10 @@ def sandbox_list(args): except OSError, e: print "Invalid container %s: %s", (gc, e) - def sandbox_reload(args): config = read_config(args.name) + if isinstance(config, gi.repository.LibvirtSandbox.ConfigInteractive): + raise ValueError(_("Interactive Containers do not support reload")) container = ServiceContainer(uri = args.uri, config = config) container.reload(args.unitfiles) @@ -848,7 +912,7 @@ Type 'Ctrl + ]' to detach from the console. os.execl("/usr/libexec/virt-sandbox-service-util", "virt-sandbox-service-util","-a", args.name) # config = read_config(args.name) # container = Container(uri = args.uri, config=config) -# container.connect() +# container.console() # # Search Path for command to execute within the container. @@ -894,25 +958,27 @@ def clone(args): shutil.copytree(old_path, new_path, symlinks=True) sys.stdout.write(_("Created sandbox container dir %s\n") % new_path) - fd = open(container.get_unit_path()) - recs = fd.read() - fd.close() - - fd = open(container.get_unit_path(args.dest), "wx") - fd.write(recs.replace(args.source, args.dest)) - fd.close() + if isinstance(config, gi.repository.LibvirtSandbox.ConfigInteractive): + container = InteractiveContainer(name=args.dest, uri=args.uri, create=True) + else: + fd = open(container.get_unit_path()) + recs = fd.read() + fd.close() + fd = open(container.get_unit_path(args.dest), "wx") + fd.write(recs.replace(args.source, args.dest)) + fd.close() + new_unit = container.get_config_path(args.dest) + fd = open(new_unit,"wx") + fd.write(newrec) + fd.close() + sys.stdout.write(_("Created unit file %s\n") % new_unit) - new_unit = container.get_config_path(args.dest) - fd = open(new_unit,"wx") - fd.write(newrec) - fd.close() - sys.stdout.write(_("Created unit file %s\n") % new_unit) + container = ServiceContainer(name=args.dest, uri=args.uri, create=True) + container.gen_machine_id() + container.gen_hostname() - container = ServiceContainer(name=args.dest, uri=args.uri, create=True) if args.security: container.set_security(args.security) - container.gen_machine_id() - container.gen_hostname() container.set_security_label() container.save_config() @@ -969,31 +1035,34 @@ def default_security_opts(): def gen_create_args(subparser): parser = subparser.add_parser("create", - help=_("create a sandbox container")) + help=_("Create a sandbox container.")) - parser.add_argument("-u", "--unitfile", required=True, - action=CheckUnit, - dest="unitfiles", - help=_("Systemd Unit file to run within the sandbox container")) - parser.add_argument("-p", "--path", dest="path", default=None, - help=_("select path to store sandbox content. Default: %s") % c.DEFAULT_PATH) + parser.add_argument("-C", "--copy", default=False, + action="store_true", + help=_("copy content from the hosts /etc and /var directories that will be mounted within the sandbox")) + parser.add_argument("-f", "--filetype", dest="file_type", + default=c.get_file_type(), + help=_("SELinux file type to assign to content within the sandbox. Default: %s") % c.get_file_type()) + parser.add_argument("-i", "--imagesize", dest="imagesize", default = None, + action=SizeAction, + help=_("create image of this many megabytes.")) + parser.add_argument("-n", "--network", dest="network", + action=SetNet, default=[], + help=_("Specify the network configuration")) + parser.add_argument("-p", "--path", dest="path", default=c.DEFAULT_PATH, + help=_("select path to store sandbox content. Default: %s") % c.DEFAULT_PATH) parser.add_argument("-s", "--security", dest="security", default=default_security_opts(), help=_("Specify the security model configuration for the sandbox: Defaults to dynamic")) - parser.add_argument("-N", "--network", dest="network", - action=SetNet, - help=_("Specify the network configuration")) - - image = parser.add_argument_group("Create On Disk Image File") + parser.add_argument("-u", "--unitfile", + action=CheckUnit, + dest="unitfiles", + help=_("Systemd Unit file to run within the Service sandbox container. Commands can not be specified with unit files.")) - image.add_argument("-i", "--imagesize", dest="imagesize", default = None, - action=SizeAction, - help=_("create image of this many megabytes.")) - parser.add_argument("-C", "--copy", default=False, - action="store_true", - help=_("copy content from /etc and /var directories that will be mounted within the sandbox")) requires_name(parser) + parser.add_argument("command", default=[], nargs="*", + help=_("Command to run within the Interactive sandbox container. Commands can not be specified with unit files.")) parser.set_defaults(func=create) diff --git a/bin/virt-sandbox-service-bash-completion.sh b/bin/virt-sandbox-service-bash-completion.sh index ce14a7d..92b34b1 100755 --- a/bin/virt-sandbox-service-bash-completion.sh +++ b/bin/virt-sandbox-service-bash-completion.sh @@ -35,8 +35,8 @@ __get_all_running_containers () { virt-sandbox-service list --running } -__get_all_types () { - seinfo -asvirt_lxc_domain -x 2>/dev/null | tail -n +2 +__get_all_file_types () { + seinfo -afile_type -x 2>/dev/null | tail -n +2 } _virt_sandbox_service () { @@ -55,7 +55,7 @@ _virt_sandbox_service () { ) local -A OPTS=( [ALL]='-h --help' - [CREATE]='-u --unitfile -p --path -t --type -l --level -d --dynamic -n --clone -i --image -s --size' + [CREATE]='-u --unitfile -p --path -f --filetype -C --copy -i --imagesize -n --network -s --security' [LIST]='-r --running' [RELOAD]='-u --unitfile' [EXECUTE]='-N --noseclabel' @@ -109,12 +109,14 @@ _virt_sandbox_service () { elif test "$prev" = "-u" || test "$prev" = "--unitfile" ; then COMPREPLY=( $(compgen -W "$( __get_all_unit_files ) " -- "$cur") ) return 0 - elif test "$prev" = "-t" || test "$prev" = "--type" ; then - COMPREPLY=( $(compgen -W "$( __get_all_types ) " -- "$cur") ) + elif test "$prev" = "-f" || test "$prev" = "--filetype" ; then + COMPREPLY=( $(compgen -W "$( __get_all_file_types ) " -- "$cur") ) return 0 - elif test "$prev" = "-l" || test "$prev" = "--level" ; then + elif test "$prev" = "-s" || test "$prev" = "--security" ; then return 0 - elif test "$prev" = "-s" || test "$prev" = "--size" ; then + elif test "$prev" = "-n" || test "$prev" = "--network" ; then + return 0 + elif test "$prev" = "-i" || test "$prev" = "--imagesize" ; then return 0 elif __contains_word "$command" ${VERBS[CREATE]} ; then COMPREPLY=( $(compgen -W "${OPTS[ALL]} ${OPTS[CREATE]}" -- "$cur") ) diff --git a/bin/virt-sandbox-service-create.pod b/bin/virt-sandbox-service-create.pod index 3fb8ae0..e888de9 100644 --- a/bin/virt-sandbox-service-create.pod +++ b/bin/virt-sandbox-service-create.pod @@ -4,7 +4,7 @@ virt-sandbox-service create - Create a Security container =head1 SYNOPSIS - virt-sandbox-service [-c URI] create [-h] -u UNIT_FILE [ --copy ] [-p PATH] [-N NETWORK-OPTS] [-s SECURITY-OPTS] [-i SIZE] [-n] NAME + virt-sandbox-service [-c URI] create [-h] [ -u UNIT_FILE ] [ --copy ] [-p PATH] [-N NETWORK-OPTS] [-s SECURITY-OPTS] [-i SIZE] [-n] NAME [ COMMAND ] =head1 DESCRIPTION @@ -14,7 +14,7 @@ technology such as LinuX Containers (LXC), or optionally QEMU/KVM. The container / virtual machines will be secured by SELinux and resource separated using cgroups. -The create command will setup a sandbox for running one or more systemd unit files +The create command can setup a sandbox for running one or more systemd unit files. It can also setup a sandbox for running a command in an InteractiveContainer. Specify a unit file to create the ServiceContainer and the command to create an InteractiveContainer. =head1 OPTIONS @@ -31,8 +31,7 @@ supported currently). =item B<-u UNIT_FILE>, B<--unitfile UNIT_FILE> -Name of the systemd unit file to be to run within the container. Can be repeated -if multiple unit files are required within the sandbox. +Name of the systemd unit file to be to run within the Service Container. Can be repeated if multiple unit files are required within the sandbox. Can not be specified if you are using a COMMAND. =item B<-C>, B<--copy> @@ -128,13 +127,19 @@ systemd Unit file to run within the container =head1 EXAMPLE -Create httpd1 container +Create httpd1 Service container # virt-sandbox-service create -C -u httpd.service httpd1 Created container dir /var/lib/libvirt/filesystems/httpd1 Created sandbox config /etc/libvirt-sandbox/httpd1.sandbox Created unit file /etc/systemd/system/httpd@httpd1.service +Create foobar1 Service container + + # virt-sandbox-service create foobar1 -- /usr/bin/foobar -a -b + Created container dir /var/lib/libvirt/filesystems/foobar1 + Created sandbox config /etc/libvirt-sandbox/foobar1.sandbox + =head1 SEE ALSO C<libvirt(8)>, C<selinux(8)>, C<systemd(8)>, C<virt-sandbox-service(1)> -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:30PM -0400, Dan Walsh wrote:
First use case will be OpenShift
Differentiate on create based on whether one or more unit files specified (ServiceContainer), or a command is specified (Interactive Container).
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 165 ++++++++++++++++++++-------- bin/virt-sandbox-service-bash-completion.sh | 16 +-- bin/virt-sandbox-service-create.pod | 15 ++- 3 files changed, 136 insertions(+), 60 deletions(-)
+ parser.add_argument("-n", "--network", dest="network", + action=SetNet, default=[], + help=_("Specify the network configuration"))
- parser.add_argument("-N", "--network", dest="network", - action=SetNet, - help=_("Specify the network configuration")) - - image = parser.add_argument_group("Create On Disk Image File")
You're still changing -N into -n here. ACK if you remove that change before pushing. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 8571374..8c9ea76 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -928,7 +928,7 @@ def fullpath(cmd): return cmd def execute(args): - myexec = [ "virsh", "-c", "lxc:///", "lxc-enter-namespace" ] + myexec = [ "virsh", "-c", args.uri, "lxc-enter-namespace" ] # myexec = [ "virt-sandbox-service-util", "execute" ] if args.noseclabel: myexec.append("--noseclabel") -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:31PM -0400, Dan Walsh wrote:
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 8571374..8c9ea76 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -928,7 +928,7 @@ def fullpath(cmd): return cmd
def execute(args): - myexec = [ "virsh", "-c", "lxc:///", "lxc-enter-namespace" ] + myexec = [ "virsh", "-c", args.uri, "lxc-enter-namespace" ] # myexec = [ "virt-sandbox-service-util", "execute" ] if args.noseclabel: myexec.append("--noseclabel")
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

virt-sandbox-service execute is not supported on qemu sandboxes. Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 8c9ea76..7b0410a 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -928,6 +928,9 @@ def fullpath(cmd): return cmd def execute(args): + if args.uri != "lxc:///": + raise ValueError(_("Can only execute commands inside of linux containers.")) + myexec = [ "virsh", "-c", args.uri, "lxc-enter-namespace" ] # myexec = [ "virt-sandbox-service-util", "execute" ] if args.noseclabel: @@ -1074,7 +1077,7 @@ def gen_connect_args(subparser): def gen_execute_args(subparser): parser = subparser.add_parser("execute", - help=_("Execute a command within a sandbox container")) + help=_("Execute a command within a sandbox container. Only available for lxc:///")) parser.add_argument("-N", "--noseclabel", dest="noseclabel", default=False, action="store_true", help=_("do not modify the label of the executable process. By default all commands execute with the label of the sandbox")) -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:32PM -0400, Dan Walsh wrote:
virt-sandbox-service execute is not supported on qemu sandboxes.
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

We need to prevent SYSVInit scripts from running by default in the ServiceContainer. The so we recreate all of the directories under /etc/rc.d and copy the functions file over. Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 7b0410a..5aa49f7 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -420,12 +420,12 @@ class ServiceContainer(Container): PROFILE_FILES = [ ".bashrc", ".bash_profile" ] MACHINE_ID = "/etc/machine-id" HOSTNAME = "/etc/hostname" - FUNCTIONS = "/etc/rc.d/init.d/functions" + SYSVINIT_PATH = "/etc/rc.d" ANACONDA_WANTS_PATH = "/usr/lib/systemd/system/anaconda.target.wants" MULTI_USER_WANTS_PATH = "/usr/lib/systemd/system/multi-user.target.wants" SYSINIT_WANTS_PATH = "/usr/lib/systemd/system/sysinit.target.wants" SOCKET_WANTS_PATH = "/usr/lib/systemd/system/sockets.target.wants" - MAKE_SYSTEM_DIRS = [ "/var/lib/dhclient", "/var/lib/dbus", "/var/log", "/var/spool", "/var/cache", "/var/tmp", "/var/lib/nfs/rpc_pipefs", "/etc/rc.d/init.d"] + MAKE_SYSTEM_DIRS = [ "/var/lib/dhclient", "/var/lib/dbus", "/var/log", "/var/spool", "/var/cache", "/var/tmp", "/var/lib/nfs/rpc_pipefs", SYSVINIT_PATH ] BIND_SYSTEM_DIRS = [ "/var", "/home", "/root", "/etc/systemd/system", "/etc/rc.d", "/usr/lib/systemd/system/basic.target.wants", "/usr/lib/systemd/system/local-fs.target.wants", ANACONDA_WANTS_PATH, MULTI_USER_WANTS_PATH, SYSINIT_WANTS_PATH, SOCKET_WANTS_PATH ] BIND_SYSTEM_FILES = [ MACHINE_ID, "/etc/fstab", HOSTNAME ] LOCAL_LINK_FILES = { SYSINIT_WANTS_PATH : [ "systemd-tmpfiles-setup.service" ] , SOCKET_WANTS_PATH : [ "dbus.socket", "systemd-journald.socket", "systemd-shutdownd.socket" ] } @@ -702,7 +702,11 @@ PrivateNetwork=false for f in self.BIND_SYSTEM_FILES: self.makefile(f) - shutil.copy(self.FUNCTIONS, "%s%s" % (self.dest, self.FUNCTIONS)) + destpath = self.dest + self.SYSVINIT_PATH + for i in range(7): + os.mkdir(destpath+("/rc%s.d" % i)) + os.mkdir(destpath+"/init.d") + shutil.copy(self.SYSVINIT_PATH + "/init.d/functions" , destpath + "/init.d") self.gen_machine_id() self.gen_hostname() -- 1.8.2

On Wed, Apr 03, 2013 at 07:17:33PM -0400, Dan Walsh wrote:
We need to prevent SYSVInit scripts from running by default in the ServiceContainer. The so we recreate all of the directories under /etc/rc.d and copy the functions file over.
Signed-off-by: Dan Walsh <dwalsh@redhat.com> --- bin/virt-sandbox-service | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (3)
-
Dan Walsh
-
Daniel J Walsh
-
Daniel P. Berrange