File: __init__.py

package info (click to toggle)
freeipa 4.13.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 367,240 kB
  • sloc: javascript: 562,763; python: 310,289; ansic: 49,809; sh: 7,176; makefile: 2,589; xml: 343; sed: 16
file content (135 lines) | stat: -rw-r--r-- 3,933 bytes parent folder | download | duplicates (3)
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
#
# Copyright (C) 2016  FreeIPA Contributors see COPYING for license
#

from collections.abc import MutableMapping
import errno
import json
import locale
import logging
import os
import time

from . import compat
from . import schema
from ipaclient.plugins.rpcclient import rpcclient
from ipapython.dnsutil import DNSName

logger = logging.getLogger(__name__)


class ServerInfo(MutableMapping):
    def __init__(self, api):
        self._dir = os.path.join(api.env.cache_dir, "servers")
        hostname = DNSName(api.env.server).ToASCII()
        self._filename = os.path.join(self._dir, hostname)
        self._force_check = api.env.force_schema_check
        self._now = time.time()
        self._dict = {}

        # copy-paste from ipalib/rpc.py
        try:
            self._language = locale.setlocale(
                locale.LC_MESSAGES, ''
            ).split('.', maxsplit=1)[0].lower()
        except locale.Error:
            self._language = 'en_us'

        self._read()

    def _read(self):
        try:
            with open(self._filename, 'r') as sc:
                self._dict = json.load(sc)
        except Exception as e:
            if (isinstance(e, EnvironmentError) and
                    e.errno == errno.ENOENT):  # pylint: disable=no-member
                # ignore non-existent file, this happens when the cache was
                # erased or the server is contacted for the first time
                pass
            else:
                # warn that the file is unreadable, probably corrupted
                logger.warning('Failed to read server info: %s', e)

    def _write(self):
        try:
            try:
                os.makedirs(self._dir)
            except EnvironmentError as e:
                if e.errno != errno.EEXIST:
                    raise
            with open(self._filename, 'w') as sc:
                json.dump(self._dict, sc)
        except EnvironmentError as e:
            logger.warning('Failed to write server info: %s', e)

    def __getitem__(self, key):
        return self._dict[key]

    def __setitem__(self, key, value):
        self._dict[key] = value

    def __delitem__(self, key):
        del self._dict[key]

    def __iter__(self):
        return iter(self._dict)

    def __len__(self):
        return len(self._dict)

    def update_validity(self, ttl):
        if not self.is_valid():
            self['expiration'] = self._now + ttl
            self['language'] = self._language
            self._write()

    def is_valid(self):
        if self._force_check:
            return False

        try:
            expiration = self._dict['expiration']
            language = self._dict['language']
        except KeyError:
            # if any of these is missing consider the entry expired
            return False

        if expiration < self._now:
            return False

        if language != self._language:
            # language changed since last check
            return False

        return True


def get_package(api):
    if api.env.in_tree:
        # server packages are not published on pypi.org
        # pylint: disable=useless-suppression
        # pylint: disable=import-error,ipa-forbidden-import
        from ipaserver import plugins
        # pylint: enable=import-error,ipa-forbidden-import
        # pylint: enable=useless-suppression
    else:
        try:
            plugins = api._remote_plugins
        except AttributeError:
            server_info = ServerInfo(api)

            client = rpcclient(api)
            client.finalize()

            try:
                plugins = schema.get_package(server_info, client)
            except schema.NotAvailable:
                plugins = compat.get_package(server_info, client)
            finally:
                if client.isconnected():
                    client.disconnect()

            object.__setattr__(api, '_remote_plugins', plugins)

    return plugins