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(a)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(a)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