~townsend/libertine/remove-X-umount

« back to all changes in this revision

Viewing changes to tools/libertine-lxc-manager

  • Committer: Tarmac
  • Author(s): Larry Price
  • Date: 2017-01-05 18:38:37 UTC
  • mfrom: (302.30.14 lxd-manager)
  • Revision ID: tarmac-20170105183837-zlcaa8xncukr51n5
Create d-bus service for lxd container management.

Approved by Christopher Townsend, Libertine CI Bot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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/>.
18
18
 
19
 
import dbus
20
 
import dbus.service
21
19
import libertine.LxcContainer
22
20
import libertine.utils
23
21
import os
24
22
import shlex
25
 
import signal
26
23
import subprocess
27
24
 
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
32
 
 
33
 
 
34
 
home_path = os.environ['HOME']
 
26
from libertine.lifecycle import *
 
27
 
35
28
 
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()
38
31
 
39
32
 
40
 
class Service(dbus.service.Object):
 
33
class Service(ContainerLifecycleService):
41
34
 
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()
47
 
 
48
 
        DBusGMainLoop(set_as_default=True)
49
 
        try:
50
 
            bus_name = dbus.service.BusName(LIBERTINE_LXC_MANAGER_NAME,
51
 
                                            bus=dbus.SessionBus(),
52
 
                                            do_not_queue=True)
53
 
        except dbus.exceptions.NameExistsException:
54
 
            libertine.utils.get_logger().error("service is already running")
55
 
            raise
56
 
        super().__init__(bus_name, LIBERTINE_LXC_MANAGER_PATH)
57
 
 
58
 
    @dbus.service.method(LIBERTINE_LXC_MANAGER_NAME,
59
 
                         in_signature='ss',
60
 
                         out_signature='(bs)')
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.")
64
 
 
65
 
        (started, reason) = self._launch_lxc_container(container_id, lxc_logfile)
66
 
 
67
 
        if started:
68
 
            self.app_counter[container_id] += 1
69
 
 
70
 
        return (started, reason)
71
 
 
72
 
    @dbus.service.method(LIBERTINE_LXC_MANAGER_NAME,
73
 
                         in_signature='s')
74
 
    def app_stop(self, container_id):
75
 
        self.app_counter[container_id] -= 1
76
 
 
77
 
        if self.app_counter[container_id] == 0:
78
 
            self._stop_lxc_container(container_id)
79
 
            del self.app_counter[container_id]
80
 
 
81
 
    @dbus.service.method(LIBERTINE_LXC_MANAGER_NAME,
82
 
                         in_signature='ss',
83
 
                         out_signature='(bs)')
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.")
87
 
 
88
 
        (started, reason) = self._launch_lxc_container(container_id, lxc_log_file, launchable=False)
89
 
 
90
 
        if started:
91
 
            self.operation_counter[container_id] += 1
92
 
 
93
 
        return (started, reason)
94
 
 
95
 
    @dbus.service.method(LIBERTINE_LXC_MANAGER_NAME,
96
 
                         in_signature='s')
97
 
    def operation_stop(self, container_id):
98
 
        self.operation_counter[container_id] -= 1
99
 
 
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
 
40
 
 
41
    def start(self, container_id, launchable):
 
42
        container = libertine.LxcContainer.lxc_container(container_id)
 
43
 
 
44
        if not container.defined:
 
45
            return LifecycleResult("Container {} is not valid".format(container_id))
 
46
 
 
47
        if launchable and not self._is_pulse_setup:
 
48
            self._setup_pulse()
 
49
 
 
50
        if not container.running:
 
51
            if launchable:
 
52
                self._dynamic_bind_mounts(container, container_id)
 
53
 
 
54
            return libertine.LxcContainer.lxc_start(container)
 
55
 
 
56
        return LifecycleResult()
 
57
 
 
58
    def stop(self, container_id):
 
59
        container = libertine.LxcContainer.lxc_container(container_id)
 
60
        libertine.LxcContainer.lxc_stop(container)
 
61
 
 
62
        return LifecycleResult() # no error case
103
63
 
104
64
    def _setup_pulse(self):
105
65
        pulse_socket_path = os.path.join(libertine.utils.get_libertine_runtime_dir(), 'pulse_socket')
118
78
 
119
79
        self.is_pulse_setup = True
120
80
 
121
 
    def _launch_lxc_container(self, container_id, lxc_log_file, launchable=True):
122
 
        container = libertine.LxcContainer.lxc_container(container_id)
123
 
 
124
 
        if not container.defined:
125
 
            return (False, "Container {} is not valid".format(container_id))
126
 
 
127
 
        if launchable and not self.is_pulse_setup:
128
 
            self._setup_pulse()
129
 
 
130
 
        if not container.running:
131
 
            if launchable:
132
 
                self._dynamic_bind_mounts(container, container_id)
133
 
 
134
 
            return libertine.LxcContainer.lxc_start(container, lxc_log_file)
135
 
 
136
 
        return (True, "")
137
 
 
138
 
    def _stop_lxc_container(self, container_id):
139
 
        container = libertine.LxcContainer.lxc_container(container_id)
140
 
 
141
 
        libertine.LxcContainer.lxc_stop(container)
142
 
 
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))
147
85
 
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):
167
105
        return [mount.replace(" ", "\\040") for mount in mounts]
168
106
 
169
107
 
170
 
def sigterm(self):
171
 
    shutdown()
172
 
 
173
 
 
174
 
def shutdown():
175
 
    GLib.MainLoop().quit()
176
 
 
177
 
 
178
 
def main():
179
 
    service = Service()
180
 
    GLib.unix_signal_add(GLib.PRIORITY_HIGH,
181
 
                         signal.SIGTERM,
182
 
                         sigterm,
183
 
                         None)
184
 
 
185
 
    try:
186
 
        GLib.MainLoop().run()
187
 
    except KeyboardInterrupt:
188
 
        shutdown()
189
 
 
190
 
 
191
108
if __name__ == '__main__':
192
 
    main()
 
109
    ContainerLifecycleServiceRunner(Service()).run()