This way we can share common methods between the ServiceContainer and the
InteractiveContainer
---
bin/virt-sandbox-service | 823 ++++++++++++++++++++++++++---------------------
1 file changed, 450 insertions(+), 373 deletions(-)
diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service
index 9f4941b..f4d0eff 100755
--- a/bin/virt-sandbox-service
+++ b/bin/virt-sandbox-service
@@ -58,56 +58,387 @@ 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_type(self):
+ try:
+ if self.config:
+ con = self.config.get_security_label().split(':')
+ return con[2]
+ except:
+ pass
+ return "svirt_lxc_net_t"
+
+ def get_security_level(self):
+ try:
+ if self.config:
+ con = self.config.get_security_label().split(':')
+ return ":".join(con[3:])
+ except:
+ pass
+ return "s0"
+
+ 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 set_security_type(self, security_type):
+ label = "system_u:system_r:%s:%s" % (security_type,
self.get_security_level())
+ try:
+ selinux.security_check_context(label)
+ self.config.set_security_label(label)
+ except OSError, e:
+ raise OSError(_("Invalid Security Type %s: %s ") % (security_type,
e))
+
+ def set_security_level(self, security_level):
+ label = "system_u:system_r:%s:%s" % (self.get_security_type(),
security_level)
+ try:
+ selinux.security_check_context(label)
+ self.config.set_security_label(label)
+ except OSError, e:
+ raise OSError(_("Invalid Security Level %s: %s ") %
(security_level, e))
+
+ 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 _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):
+ # 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" ]
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" ] }
- 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 +459,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 +479,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 +505,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:
@@ -204,87 +533,29 @@ WantedBy=%(TARGET)s
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])
-
- 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 set_image(self, size):
- self.use_image = True
- self.size = size * MB
+ break;
- def set_path(self, path):
- self.path = path
+ 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_name(self, name):
+ def get_name(self):
if self.config:
- raise ValueError([_("Cannot modify Name")])
- self.dest = "%s/%s" % (self.path, self.name)
- self.config = LibvirtSandbox.ConfigService.new(name)
+ return self.config.get_name()
+ raise ValueError([_("Name not configured")])
+
+ def set_copy(self, copy):
+ self.copy = copy
+
+ def get_security_dynamic(self):
+ return self.config.get_security_dynamic()
def _extract_rpms(self):
self.all_dirs = []
@@ -323,7 +594,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]
@@ -343,7 +614,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]
@@ -353,10 +624,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 +650,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 +670,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 +681,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:
@@ -491,10 +701,13 @@ 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()
for k in self.LOCAL_LINK_FILES:
@@ -530,70 +743,20 @@ 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()
fd.close()
- jpath = "/var/log/journal/" + uuid
- 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)
+ os.remove("/var/log/journal/" + uuid)
+ except OSError, e:
+ 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)
@@ -624,12 +787,13 @@ PrivateNetwork=false
self._delete()
def _create(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 +803,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):
@@ -667,119 +832,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)
@@ -788,7 +856,6 @@ def create(args):
def usage(parser, msg):
parser.print_help()
-
sys.stderr.write("\n%s\n" % msg)
sys.stderr.flush()
sys.exit(1)
@@ -799,7 +866,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()
@@ -812,8 +879,6 @@ def sandbox_list(args):
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)
@@ -860,7 +925,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()
@@ -893,7 +959,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()
@@ -907,17 +973,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):
@@ -1011,7 +1088,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