summaryrefslogtreecommitdiff
path: root/src/launcher.py
blob: bbd4f42278b1e0f0e64ca3fc13a387e30168c70b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import os
import shutil
import platform
import time
import threading
import ConfigParser

from leap.bitmask.app import start_app as bitmask_client
from leap.common.events import server, signal
from leap.common.events import events_pb2 as proto

import tuf.client.updater

bundles_per_platform = {
    "Linux-i386": "linux-i368",
    "Linux-i686": "linux-i368",
    "Linux-x86_64": "linux-x86_64",
}

GENERAL_SECTION = "General"
DELAY_KEY = "updater_delay"


class TUF(threading.Thread):
    def __init__(self, config):
        """
        Initialize the list of mirrors, paths and other TUF dependencies from
        the config file
        """
        if config.has_section(GENERAL_SECTION) and \
                config.has_option(GENERAL_SECTION, DELAY_KEY):
            self.delay = config.getint(GENERAL_SECTION, DELAY_KEY)
        else:
            self.delay = 60

        self._load_mirrors(config)
        if not self.mirrors:
            print("ERROR: No updater mirrors found (missing or not well "
                  "formed launcher.conf)")

        self.bundle_path = os.getcwd()
        self.source_path = self.bundle_path
        self.dest_path = os.path.join(self.bundle_path, 'tmp')
        self.update_path = os.path.join(self.bundle_path, 'updates')

        threading.Thread.__init__(self)

    def run(self):
        """
        Check for updates periodically
        """
        if not self.mirrors:
            return

        while True:
            try:
                tuf.conf.repository_directory = os.path.join(self.bundle_path,
                                                             'repo')

                updater = tuf.client.updater.Updater('leap-updater',
                                                     self.mirrors)
                updater.refresh()

                targets = updater.all_targets()
                updated_targets = updater.updated_targets(targets,
                                                          self.source_path)
                if updated_targets:
                    print "There is updates needed. Start downloading updates."
                for target in updated_targets:
                    updater.download_target(target, self.dest_path)
                    self._set_permissions(target)
                if os.path.isdir(self.dest_path):
                    if os.path.isdir(self.update_path):
                        shutil.rmtree(self.update_path)
                    shutil.move(self.dest_path, self.update_path)
                    filepath = sorted([f['filepath'] for f in updated_targets])
                    signal(proto.UPDATER_NEW_UPDATES,
                           content=", ".join(filepath))
                    print "Updates ready: ", filepath
                    return
            except NotImplemented as e:
                print "NotImplemented: ", e
                return
            except Exception as e:
                print "ERROR:", e
            finally:
                time.sleep(self.delay)

    def _load_mirrors(self, config):
        self.mirrors = {}
        for section in config.sections():
            if section[:6] != 'Mirror':
                continue
            url_prefix = config.get(section, 'url_prefix')
            metadata_path = self._repo_path() + '/metadata'
            targets_path = self._repo_path() + '/targets'
            self.mirrors[section[7:]] = {'url_prefix': url_prefix,
                                         'metadata_path': metadata_path,
                                         'targets_path': targets_path,
                                         'confined_target_dirs': ['']}

    def _set_permissions(self, target):
        file_permissions_str = target["fileinfo"]["custom"]["file_permissions"]
        file_permissions = int(file_permissions_str, 8)
        filepath = target['filepath']
        if filepath[0] == '/':
            filepath = filepath[1:]
        file_path = os.path.join(self.dest_path, filepath)
        os.chmod(file_path, file_permissions)

    def _repo_path(self):
        system = platform.system() + "-" + platform.machine()
        if system not in bundles_per_platform:
            raise NotImplementedError("Platform %s not supported" % (system,))
        return bundles_per_platform[system]


if __name__ == "__main__":
    server.ensure_server(port=8090)

    config = ConfigParser.ConfigParser()
    config.read("launcher.conf")

    tuf_thread = TUF(config)
    tuf_thread.daemon = True
    tuf_thread.start()

    bitmask_client()