16
16
# You should have received a copy of the GNU General Public License
17
17
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21
19
import libertine.LxcContainer
22
20
import libertine.utils
28
from collections import Counter
29
from dbus.mainloop.glib import DBusGMainLoop
30
from gi.repository import GLib
31
25
from libertine.ContainersConfig import ContainersConfig
34
home_path = os.environ['HOME']
26
from libertine.lifecycle import *
36
29
LIBERTINE_LXC_MANAGER_NAME = libertine.LxcContainer.get_lxc_manager_dbus_name()
37
30
LIBERTINE_LXC_MANAGER_PATH = libertine.LxcContainer.get_lxc_manager_dbus_path()
40
class Service(dbus.service.Object):
33
class Service(ContainerLifecycleService):
42
35
def __init__(self):
43
self.is_pulse_setup = False
44
self.app_counter = Counter()
45
self.containers_config = ContainersConfig()
46
self.operation_counter = Counter()
48
DBusGMainLoop(set_as_default=True)
50
bus_name = dbus.service.BusName(LIBERTINE_LXC_MANAGER_NAME,
51
bus=dbus.SessionBus(),
53
except dbus.exceptions.NameExistsException:
54
libertine.utils.get_logger().error("service is already running")
56
super().__init__(bus_name, LIBERTINE_LXC_MANAGER_PATH)
58
@dbus.service.method(LIBERTINE_LXC_MANAGER_NAME,
61
def app_start(self, container_id, lxc_logfile):
62
if self.operation_counter[container_id] != 0:
63
return (False, "Libertine container operation already running: cannot launch application.")
65
(started, reason) = self._launch_lxc_container(container_id, lxc_logfile)
68
self.app_counter[container_id] += 1
70
return (started, reason)
72
@dbus.service.method(LIBERTINE_LXC_MANAGER_NAME,
74
def app_stop(self, container_id):
75
self.app_counter[container_id] -= 1
77
if self.app_counter[container_id] == 0:
78
self._stop_lxc_container(container_id)
79
del self.app_counter[container_id]
81
@dbus.service.method(LIBERTINE_LXC_MANAGER_NAME,
84
def operation_start(self, container_id, lxc_log_file):
85
if self.app_counter[container_id] != 0:
86
return (False, "Application already running in container: cannot run operation.")
88
(started, reason) = self._launch_lxc_container(container_id, lxc_log_file, launchable=False)
91
self.operation_counter[container_id] += 1
93
return (started, reason)
95
@dbus.service.method(LIBERTINE_LXC_MANAGER_NAME,
97
def operation_stop(self, container_id):
98
self.operation_counter[container_id] -= 1
100
if self.operation_counter[container_id] == 0:
101
self._stop_lxc_container(container_id)
102
del self.operation_counter[container_id]
36
super().__init__(LIBERTINE_LXC_MANAGER_NAME, LIBERTINE_LXC_MANAGER_PATH)
37
self._home = os.environ['HOME']
38
self._containers_config = ContainersConfig()
39
self._is_pulse_setup = False
41
def start(self, container_id, launchable):
42
container = libertine.LxcContainer.lxc_container(container_id)
44
if not container.defined:
45
return LifecycleResult("Container {} is not valid".format(container_id))
47
if launchable and not self._is_pulse_setup:
50
if not container.running:
52
self._dynamic_bind_mounts(container, container_id)
54
return libertine.LxcContainer.lxc_start(container)
56
return LifecycleResult()
58
def stop(self, container_id):
59
container = libertine.LxcContainer.lxc_container(container_id)
60
libertine.LxcContainer.lxc_stop(container)
62
return LifecycleResult() # no error case
104
64
def _setup_pulse(self):
105
65
pulse_socket_path = os.path.join(libertine.utils.get_libertine_runtime_dir(), 'pulse_socket')
119
79
self.is_pulse_setup = True
121
def _launch_lxc_container(self, container_id, lxc_log_file, launchable=True):
122
container = libertine.LxcContainer.lxc_container(container_id)
124
if not container.defined:
125
return (False, "Container {} is not valid".format(container_id))
127
if launchable and not self.is_pulse_setup:
130
if not container.running:
132
self._dynamic_bind_mounts(container, container_id)
134
return libertine.LxcContainer.lxc_start(container, lxc_log_file)
138
def _stop_lxc_container(self, container_id):
139
container = libertine.LxcContainer.lxc_container(container_id)
141
libertine.LxcContainer.lxc_stop(container)
143
81
def _dynamic_bind_mounts(self, container, container_id):
144
self.containers_config.refresh_database()
82
self._containers_config.refresh_database()
145
83
mounts = self._sanitize_bind_mounts(libertine.utils.get_common_xdg_user_directories() + \
146
self.containers_config.get_container_bind_mounts(container_id))
84
self._containers_config.get_container_bind_mounts(container_id))
148
86
data_dir = libertine.utils.get_libertine_container_userdata_dir_path(container_id)
149
87
for user_dir in libertine.utils.generate_binding_directories(mounts, home_path):