From: Dan Walsh <dwalsh@xxxxxxxxxx> 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list