summaryrefslogtreecommitdiffstats
path: root/ipaclient/remote_plugins/__init__.py
blob: b783c32819e58f49532531b6d7f3a594c17bae16 (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
#
# Copyright (C) 2016  FreeIPA Contributors see COPYING for license
#

import collections
import errno
import json
import locale
import os
import time

from . import compat
from . import schema
from ipaclient.plugins.rpcclient import rpcclient
from ipaplatform.paths import paths
from ipapython.dnsutil import DNSName
from ipapython.ipa_log_manager import log_mgr

logger = log_mgr.get_logger(__name__)


class ServerInfo(collections.MutableMapping):
    _DIR = os.path.join(paths.USER_CACHE_PATH, 'ipa', 'servers')

    def __init__(self, api):
        hostname = DNSName(api.env.server).ToASCII()
        self._path = os.path.join(self._DIR, hostname)
        self._force_check = api.env.force_schema_check
        self._dict = {}

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

        self._read()

    def _read(self):
        try:
            with open(self._path, 'r') as sc:
                self._dict = json.load(sc)
        except EnvironmentError as e:
            if e.errno != errno.ENOENT:
                logger.warning('Failed to read server info: {}'.format(e))

    def _write(self):
        try:
            try:
                os.makedirs(self._DIR)
            except EnvironmentError as e:
                if e.errno != errno.EEXIST:
                    raise
            with open(self._path, 'w') as sc:
                json.dump(self._dict, sc)
        except EnvironmentError as e:
            logger.warning('Failed to write server info: {}'.format(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=None):
        if ttl is None:
            ttl = 3600
        self['expiration'] = time.time() + 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 < time.time():
            # validity passed
            return False

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

        return True


def get_package(api):
    if api.env.in_tree:
        from ipaserver import plugins
    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