summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server/Plugins/Packages/Layman.py
blob: 19877d32b6f11bf688609df165f3a0533aaa8ac1 (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import os
import layman
import Bcfg2.Server.Plugin

class LaymanSource(Bcfg2.Server.Plugin.Debuggable):
    basegroups = ['portage', 'gentoo', 'emerge']
    ptype = 'layman'
    cclass = 'Portage'

    def __init__(self, basepath, xsource):
        Bcfg2.Server.Plugin.Debuggable.__init__(self)
        self.basepath = basepath
        self.xsource = xsource

        self.url = xsource.get('url', 'http://www.gentoo.org/proj/en/overlays/repositories.xml')
        self.name = xsource.get('name', '')
        self.priority = xsource.get('priority', 0)
        self.cachefile = None
        self.gpgkeys = []
        self.recommended = False
        self.essentialpkgs = set()
        self.arches = [item.text for item in xsource.findall('Arch')]

        self.url_map = [dict(version=None, component=None, arch=arch,
                             url=self.url, baseurl=self.url) for arch in self.arches]

        #: A list of the the names of packages that are blacklisted
        #: from this source
        self.blacklist = [item.text for item in xsource.findall('Blacklist')]

        #: A list of the the names of packages that are whitelisted in
        #: this source
        self.whitelist = [item.text for item in xsource.findall('Whitelist')]


        # configure layman
        base = os.path.join(basepath, 'layman')
        storage = os.path.join(base, 'overlays')
        config = layman.config.OptionConfig(options = {
            'storage': os.path.join(base, 'overlays'),
            'cache': os.path.join(base, 'cache'),
            'installed': os.path.join(base, 'installed.xml'),
            'local_list': os.path.join(base, 'overlays.xml'),
            'overlays': [self.url]
        })
        self.api = layman.LaymanAPI(config)

        # path
        self.dir = os.path.join(storage, self.name)

        # build the set of conditions to see if this source applies to
        # a given set of metadata
        self.conditions = []
        self.groups = [] # provided for some limited backwards compat
        for el in xsource.iterancestors():
            if el.tag == "Group":
                if el.get("negate", "false").lower() == "true":
                    self.conditions.append(lambda m, el=el:
                                           el.get("name") not in m.groups)
                else:
                    self.groups.append(el.get("name"))
                    self.conditions.append(lambda m, el=el:
                                           el.get("name") in m.groups)
            elif el.tag == "Client":
                if el.get("negate", "false").lower() == "true":
                    self.conditions.append(lambda m, el=el:
                                           el.get("name") != m.hostname)
                else:
                    self.conditions.append(lambda m, el=el:
                                           el.get("name") == m.hostname)

    def get_repo_name(self, url_map):
        return self.name

    def save_state(self):
        pass

    def load_state(self):
        pass

    def filter_unknown(self, unknown):
        filtered = set([u for u in unknown if u.startswith('choice')])
        unknown.difference_update(filtered)

    def get_urls(self):
        return self.url
    urls = property(get_urls)

    def setup_data(self, force_update=False):
        self.api.fetch_remote_list()
        if not self.api.is_repo(self.name):
            self.logger.error("Packages: Layman overlay '%s' not"
                              " found" % self.name)
            return False

        if not self.api.is_installed(self.name):
            self.logger.info("Packages: Adding layman overlay '%s'" %
                             self.name)
            if not self.api.add_repos(self.name):
                self.logger.error("Packages: Failed adding layman"
                                  " overlay '%s'" % self.name)
                return False

        if force_update:
            if not self.api.sync(self.name):
                self.logger.error("Packages: Failed syncing layman"
                                  " overlay '%s'" % self.name)
                return False

        return True


    def applies(self, metadata):
        """ Return true if this source applies to the given client,
        i.e., the client is in all necessary groups.

        :param metadata: The client metadata to check to see if this
                         source applies
        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata
        :returns: bool
        """
        # check arch groups
        if not self.arch_groups_match(metadata):
            return False

        # check Group/Client tags from sources.xml
        for condition in self.conditions:
            if not condition(metadata):
                return False

        return True

    def arch_groups_match(self, metadata):
        """ Returns True if the client is in an arch group that
        matches the arch of this source.

        :returns: bool
        """
        for arch in self.arches:
            if arch in metadata.groups:
                return True
        return False