[libvirt] Add UID/GID support to virt-sandbox-service

This patch set is adding support for UID/GID/USERNAME/USERDIR for use with openshift containers Also fixes virt-sandbox-service to not complain if the destdir has been precreated. Finally we also do not want excess processes running withing containers (/bin/sh). [sandbox PATCH 1/3] Add UID/GID support for use with interactive [sandbox PATCH 2/3] Only create the destination path if it does not [sandbox PATCH 3/3] Do not run a shell within a lxc container by

From: Dan Walsh <dwalsh@redhat.com> Openshift Containers will be run with a unique UID and GID --- bin/virt-sandbox-service | 43 +++++++++++++++++++++-- bin/virt-sandbox-service-bash-completion.sh | 8 +++-- bin/virt-sandbox-service-create.pod | 53 ++++++++++++++++++++++++----- 3 files changed, 90 insertions(+), 14 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index a99fe7e..31aa6a1 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -28,6 +28,7 @@ import exceptions import rpm from subprocess import Popen, PIPE, STDOUT import gettext +import pwd if os.path.exists("/sys/fs/selinux"): import selinux @@ -83,10 +84,28 @@ class Container: self.file_type = file_type def set_uid(self, uid): - self.uid = uid + self.config.set_userid(uid) def get_uid(self): - return self.uid + return self.config.get_userid(uid) + + def set_gid(self, gid): + self.config.set_groupid(gid) + + def get_gid(self): + return self.config.get_groupid(gid) + + def set_username(self, username): + self.config.set_username(username) + + def get_username(self): + return self.config.get_username() + + def set_homedir(self, homedir): + self.config.set_homedir(homedir) + + def get_homedir(self): + return self.config.get_homedir() def get_config_path(self, name = None): if not name: @@ -755,6 +774,16 @@ def create(args): container.add_network(net) if args.security: container.set_security(args.security) + container.set_uid(args.uid) + if not args.homedir: + args.homedir = pwd.getpwuid(args.uid).pw_dir + container.set_homedir(args.homedir) + if not args.username: + args.username = pwd.getpwuid(args.uid).pw_name + container.set_username(args.username) + if not args.gid: + args.gid = pwd.getpwuid(args.uid).pw_gid + container.set_gid(args.gid) container.set_path(args.path) container.set_file_type(args.file_type) if args.imagesize: @@ -952,6 +981,11 @@ def gen_create_args(subparser): 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("--homedir", dest="homedir", + help=_("Specify the homedir for the container. Default: UID homedir.")) + parser.add_argument("-G", "--gid", dest="gid", + default=None, type=int, + help=_("Specify the login gid for the container. Default: login GID of the UID.")) parser.add_argument("-i", "--imagesize", dest="imagesize", default = None, action=SizeAction, help=_("create image of this many megabytes.")) @@ -967,6 +1001,11 @@ def gen_create_args(subparser): action=CheckUnit, dest="unitfiles", default=[], help=_("Systemd Unit file to run within the systemd sandbox container. Commands cannot be specified with unit files.")) + parser.add_argument("--username", dest="username", + help=_("Specify the username for the container. Default: UID username.")) + parser.add_argument("-U", "--uid", dest="uid", + default=os.getuid(),type=int, + help=_("Specify the uid for the container: Default to current UID.")) requires_name(parser) parser.add_argument("command", default=[], nargs="*", diff --git a/bin/virt-sandbox-service-bash-completion.sh b/bin/virt-sandbox-service-bash-completion.sh index 874ee56..8f2b6d0 100755 --- a/bin/virt-sandbox-service-bash-completion.sh +++ b/bin/virt-sandbox-service-bash-completion.sh @@ -1,6 +1,6 @@ # This file is part of libvirt-sandbox. # -# Copyright 2012 Dan Walsh +# Copyright (C) 2012-2013 Red Hat, Inc. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -14,7 +14,9 @@ # # You should have received a copy of the GNU General Public License # along with systemd; If not, see <http://www.gnu.org/licenses/>. - +# +# Authors: Dan Walsh <dwalsh@redhat.com> +# __contains_word () { local word=$1; shift for w in $*; do [[ $w = $word ]] && return 0; done @@ -55,7 +57,7 @@ _virt_sandbox_service () { ) local -A OPTS=( [ALL]='-h --help' - [CREATE]='-u --unitfile -p --path -f --filetype -C --copy -i --imagesize -N --network -s --security' + [CREATE]='-C --copy -f --filetype -G --gid -i --imagesize --homedir -N --network -p --path -s --security -u --unitfile --username -U -uid' [LIST]='-r --running' [RELOAD]='-u --unitfile' [EXECUTE]='-N --noseclabel' diff --git a/bin/virt-sandbox-service-create.pod b/bin/virt-sandbox-service-create.pod index fdc44bb..af942cb 100644 --- a/bin/virt-sandbox-service-create.pod +++ b/bin/virt-sandbox-service-create.pod @@ -4,7 +4,12 @@ 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 [ COMMAND ] + virt-sandbox-service [-c URI] create [-h] [-C] [-f FILE_TYPE] + [--homedir HOMEDIR] [-G GID] [-i IMAGESIZE] + [-N NETWORK] [-p PATH] [-s SECURITY] + [-u UNITFILES] [--username USERNAME] + [-U UID] + name [command [command ...]] =head1 DESCRIPTION @@ -14,7 +19,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 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. +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 GenericContainer. Specify a unit file to create the SystemdContainer and the command to create an GenericContainer. =head1 OPTIONS @@ -24,25 +29,43 @@ The create command can setup a sandbox for running one or more systemd unit file Display help message -=item B<-c> URI, B<--connect URI> +=item B<-c URI>, B<--connect URI> The connection URI for the hypervisor (only LXC or QEMU are supported currently). =item B<-u UNIT_FILE>, B<--unitfile UNIT_FILE> -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. Cannot be specified if you are using a COMMAND. +Name of the systemd unit file to be to run within the Systemd Container. Can be repeated if multiple unit files are required within the sandbox. Cannot be specified if you are using a COMMAND. =item B<-C>, B<--copy> Copy content from /etc and /var directories that will be mounted within the container. +=item B<-G GID>, B<--gid GID> + +Set login gid to use within the container. + +Default: C<Login GID of UID>. + +=item B<-f FILETYPE>, B<--filetype FILETYPE> + +Set SELinux file type to use within container. + +Default: C<svirt_lxc_file_t>. + =item B<-p PATH>, B<--path PATH> -Select path to store container content. +Set path to store container content. Default: C</var/lib/libvirt/filesystems>. +=item B<--homedir HOMEDIR> + +Set homedir path to use within container. + +Default: C<UID's Homedir>. + =item B<-N NETWORK-OPTIONS>, B<--network NETWORK-OPTIONS> Add a network interface to the sandbox. By default the sandbox will @@ -119,24 +142,36 @@ static,label=system_u:system_r:svirt_t:s0:c412,c355 Create file system image file of this size to store container content. -=item B<-u unitfile>, B<--unitfile unitfile> +=item B<-u UNITFILE>, B<--unitfile UNITFILE> systemd Unit file to run within the container +=item B<-U UID>, B<--uid UID> + +Set uid to use within container. + +Default: C<CURRENT UID>. + +=item B<--username USERNAME> + +Set username to use within container. + +Default: C<UID's Username>. + =back =head1 EXAMPLE -Create httpd1 Service container +Create httpd1 Systemd 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 +Create foobar1 Generic container - # virt-sandbox-service create foobar1 -- /usr/bin/foobar -a -b + # virt-sandbox-service create -U 1234 foobar1 -- /usr/bin/foobar -a -b Created container dir /var/lib/libvirt/filesystems/foobar1 Created sandbox config /etc/libvirt-sandbox/foobar1.sandbox -- 1.8.2

On Mon, Apr 22, 2013 at 12:26:29PM -0400, dwalsh@redhat.com wrote:
From: Dan Walsh <dwalsh@redhat.com>
Openshift Containers will be run with a unique UID and GID --- bin/virt-sandbox-service | 43 +++++++++++++++++++++-- bin/virt-sandbox-service-bash-completion.sh | 8 +++-- bin/virt-sandbox-service-create.pod | 53 ++++++++++++++++++++++++----- 3 files changed, 90 insertions(+), 14 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 :|

From: Dan Walsh <dwalsh@redhat.com> OpenShift will be creating the path within its management layer. --- bin/virt-sandbox-service | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 31aa6a1..dd30993 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -272,7 +272,8 @@ class Container: def create(self): self.connect() self.config.set_shell(True) - os.mkdir(self.dest) + if not os.path.exists(self.dest): + os.mkdir(self.dest) def connect(self): if not self.conn: @@ -331,6 +332,9 @@ class GenericContainer(Container): self.save_config() def create(self): + config_path = self.get_config_path() + if os.path.exists(config_path): + raise ValueError([_("%s already exists") % config_path ]) try: self.create_generic() except Exception, e: -- 1.8.2

On Mon, Apr 22, 2013 at 12:26:30PM -0400, dwalsh@redhat.com wrote:
From: Dan Walsh <dwalsh@redhat.com>
OpenShift will be creating the path within its management layer. --- bin/virt-sandbox-service | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 31aa6a1..dd30993 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -272,7 +272,8 @@ class Container: def create(self): self.connect() self.config.set_shell(True) - os.mkdir(self.dest) + if not os.path.exists(self.dest): + os.mkdir(self.dest)
def connect(self): if not self.conn:
ACK to this chunk.
@@ -331,6 +332,9 @@ class GenericContainer(Container): self.save_config()
def create(self): + config_path = self.get_config_path() + if os.path.exists(config_path): + raise ValueError([_("%s already exists") % config_path ])
This appears to be unrelated to the subject of this patch. Please move it to a separate commit. 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 :|

From: Dan Walsh <dwalsh@redhat.com> We want to make sure we use as little overhead as possible. If a user connects to a lxc container, it will be the same as executing a shell within the container. --- bin/virt-sandbox-service | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index dd30993..4d2d1cd 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -271,7 +271,8 @@ class Container: def create(self): self.connect() - self.config.set_shell(True) + if self.uri != "lxc:///": + self.config.set_shell(True) if not os.path.exists(self.dest): os.mkdir(self.dest) @@ -843,6 +844,18 @@ def stop(args): "-S", args.name) def connect(args): + if args.uri == "lxc:///": + class Args: + command = [] + noseclabel = None + name = args.name + uri = args.uri + + args = Args() + args.command = [ "/bin/sh" ] + execute(args) + return + print """\ Connected to %s. Type 'Ctrl + ]' to detach from the console. -- 1.8.2

On Mon, Apr 22, 2013 at 12:26:31PM -0400, dwalsh@redhat.com wrote:
From: Dan Walsh <dwalsh@redhat.com>
We want to make sure we use as little overhead as possible. If a user connects to a lxc container, it will be the same as executing a shell within the container. --- bin/virt-sandbox-service | 15 ++++++++++++++- 1 file changed, 14 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 :|
participants (2)
-
Daniel P. Berrange
-
dwalsh@redhat.com