From: Dan Walsh <dwalsh(a)redhat.com>
Add similar support to virt-sandbox-service that is in virt-sandbox
to add guest-bind, host-bind and host-image mount points on the command
line. Openshift wants to use this feature.
---
bin/virt-sandbox-service | 62 ++++++++++++++++++++++++++++++++-----
bin/virt-sandbox-service-create.pod | 49 ++++++++++++++++++++++++++---
2 files changed, 98 insertions(+), 13 deletions(-)
diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service
index d7f43a5..0ab6234 100755
--- a/bin/virt-sandbox-service
+++ b/bin/virt-sandbox-service
@@ -76,6 +76,7 @@ class Container:
self.conn = None
self.image = None
self.uid = 0
+ self.mounts = None
def get_file_type(self):
return self.file_type
@@ -107,6 +108,21 @@ class Container:
def get_homedir(self):
return self.config.get_homedir()
+ def set_mounts(self, mounts):
+ self.mounts = mounts
+
+ def get_mounts(self):
+ return self.mounts
+
+ def add_mounts(self):
+ for m in self.mounts:
+ if m["type"] == "guest-bind":
+ self.add_guest_bind_mount(m["src"], m["dest"])
+ if m["type"] == "host-bind":
+ self.add_host_bind_mount(m["src"], m["dest"])
+ if m["type"] == "host-image":
+ self.add_host_image_mount(m["src"], m["dest"])
+
def get_config_path(self, name = None):
if not name:
name = self.name
@@ -301,10 +317,18 @@ class Container:
except GLib.GError, e:
return 0
- def add_bind_mount(self, source, dest):
+ def add_host_bind_mount(self, source, dest):
mount = LibvirtSandbox.ConfigMountHostBind.new(source, dest)
self.config.add_mount(mount)
+ def add_guest_bind_mount(self, source, dest):
+ mount = LibvirtSandbox.ConfigMountGuestBind.new(source, dest)
+ self.config.add_mount(mount)
+
+ def add_host_image_mount(self, source, dest):
+ mount = LibvirtSandbox.ConfigMountHostImage.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)
@@ -318,7 +342,7 @@ class GenericContainer(Container):
def gen_filesystems(self):
Container.gen_filesystems(self)
- self.add_bind_mount(self.dest, self.path)
+ self.add_host_bind_mount(self.dest, self.path)
def create_generic(self):
Container.create(self)
@@ -330,12 +354,10 @@ class GenericContainer(Container):
sys.stdout.write(_("Created sandbox container image %s\n") %
self.image)
else:
sys.stdout.write(_("Created sandbox container dir %s\n") %
self.dest)
+ self.add_mounts()
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:
@@ -613,12 +635,12 @@ WantedBy=%(TARGET)s
for d in self.BIND_SYSTEM_DIRS:
if os.path.exists(d):
source = "%s%s" % ( self.dest, d)
- self.add_bind_mount(source, d)
+ self.add_host_bind_mount(source, d)
for f in self.BIND_SYSTEM_FILES:
if os.path.exists(f):
source = "%s%s" % ( self.dest, f)
- self.add_bind_mount(source, f)
+ self.add_host_bind_mount(source, f)
for d in self.dirs:
found = False
@@ -629,7 +651,7 @@ WantedBy=%(TARGET)s
break
if not found:
source = "%s%s" % ( self.dest, d)
- self.add_bind_mount(source, d)
+ self.add_host_bind_mount(source, d)
def get_expanded_unit_template(self, unit):
return unit.replace('@', '@' + self.name)
@@ -764,6 +786,7 @@ PrivateNetwork=false
self.set_security_label()
self.create_system_unit()
self.config.set_boot_target("multi-user.target")
+ self.add_mounts()
self.save_config()
def create(self):
@@ -832,6 +855,7 @@ def create(args):
container.set_gid(args.gid)
container.set_path(args.path)
container.set_file_type(args.file_type)
+ container.set_mounts(args.mounts)
if args.imagesize:
container.set_image(args.imagesize)
@@ -1007,6 +1031,25 @@ class CheckUnit(argparse.Action):
unitfiles = [ (value, src) ]
setattr(namespace, self.dest, unitfiles)
+valid_mounts = { "host-bind", "host-image", "guest-bind" }
+class AddMount(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ mounts = getattr(namespace, self.dest)
+ mrec = values.split(":")
+ if mrec[0] not in valid_mounts:
+ raise ValueError([_("Invalid mount type '%s'. Valid types
%s." % ( mrec[0], ",".join(valid_mounts)))])
+ try:
+ dest,src = mrec[1].split("=");
+ mdict = {"type":mrec[0], "src": src,
"dest":dest }
+ except (IndexError, ValueError):
+ raise ValueError([_("Invalid mount '%s' specification.") %
values ])
+
+ if mounts:
+ mounts.append(mdict)
+ else:
+ mounts = [mdict]
+ setattr(namespace, self.dest, mounts)
+
class SetNet(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
nets = getattr(namespace, self.dest)
@@ -1056,6 +1099,9 @@ def gen_create_args(subparser):
parser.add_argument("-i", "--imagesize",
dest="imagesize", default = None,
action=SizeAction,
help=_("create image of this many megabytes."))
+ parser.add_argument("-m", "--mount", dest="mounts",
+ action=AddMount, default=[],
+ help=_("Mount a filesytem in the sandbox"))
parser.add_argument("-N", "--network", dest="network",
action=SetNet, default=[],
help=_("Specify the network configuration"))
diff --git a/bin/virt-sandbox-service-create.pod b/bin/virt-sandbox-service-create.pod
index 942c919..fb1cb62 100644
--- a/bin/virt-sandbox-service-create.pod
+++ b/bin/virt-sandbox-service-create.pod
@@ -5,11 +5,12 @@ virt-sandbox-service create - Create a Security container
=head1 SYNOPSIS
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] [-P package]
- name [command [command ...]]
+ [--homedir HOMEDIR] [-G GID] [-i IMAGESIZE]
+ [[-m TYPE:DST=SRC ] ...]
+ [-N NETWORK] [-p PATH] [-s SECURITY]
+ [[-u UNITFILES] ...] [--username USERNAME]
+ [-U UID] [-P package]
+ name [command [command ...]]
=head1 DESCRIPTION
@@ -67,6 +68,44 @@ Set homedir path to use within container.
Default: C<UID's Homedir>.
+=item B<-m TYPE:DST=SRC>, B<--mount TYPE:DST=SRC>
+
+Sets up a mount inside the sandbox at B<DST> backed by B<SRC>. The meaning of
B<SRC> depends on the value of "TYPE" specified:
+
+=over 4
+
+=item host-bind
+
+If B<TYPE> is B<host-bind>, then B<SRC> is interpreted as the path to a
directory on the host filesystem. If "SRC" is the empty string, then a temporary
(empty) directory is created on the host before starting the sandbox and deleted
afterwards. The "--include" option is useful for populating these temporary
directories with copies of host files.
+
+=back
+
+=over 4
+
+=item host-image
+
+If B<TYPE> is B<host-image>, then B<SRC> is interpreted as the path to
a disk image file on the host filesystem. The image should be formatted with a filesystem
that can be auto-detected by the sandbox, such as B<ext3, ext4>, etc. The disk image
itself should be a raw file, not qcow2 or any other special format
+
+=back
+
+=over 4
+
+=item guest-bind
+
+If B<TYPE> is B<guest-bind>, then B<SRC> is interpreted as the path to
another directory in the container filesystem.
+
+=back
+
+=over 4
+
+=item Some examples
+
+ -m host-bind:/tmp=/var/lib/sandbox/demo/tmp
+ -m host-image:/=/var/lib/sandbox/demo.img
+ -m guest-bind:/home=/tmp/home
+
+=back
+
=item B<-N NETWORK-OPTIONS>, B<--network NETWORK-OPTIONS>
Add a network interface to the sandbox. By default the sandbox will
--
1.8.2.1