Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / config.py @ 14b9a185

History | View | Annotate | Download (6.8 kB)

1 7493ccb6 Stavros Sachtouris
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 7493ccb6 Stavros Sachtouris
#
3 7493ccb6 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 7493ccb6 Stavros Sachtouris
# without modification, are permitted provided that the following
5 7493ccb6 Stavros Sachtouris
# conditions are met:
6 7493ccb6 Stavros Sachtouris
#
7 7493ccb6 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 7493ccb6 Stavros Sachtouris
#      disclaimer.
10 7493ccb6 Stavros Sachtouris
#
11 7493ccb6 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 7493ccb6 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 7493ccb6 Stavros Sachtouris
#      provided with the distribution.
15 7493ccb6 Stavros Sachtouris
#
16 7493ccb6 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 7493ccb6 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 7493ccb6 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 7493ccb6 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 7493ccb6 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 7493ccb6 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 7493ccb6 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 7493ccb6 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 7493ccb6 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 7493ccb6 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 7493ccb6 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 7493ccb6 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 7493ccb6 Stavros Sachtouris
#
29 7493ccb6 Stavros Sachtouris
# The views and conclusions contained in the software and
30 7493ccb6 Stavros Sachtouris
# documentation are those of the authors and should not be
31 7493ccb6 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 7493ccb6 Stavros Sachtouris
# or implied, of GRNET S.A.
33 7493ccb6 Stavros Sachtouris
34 7493ccb6 Stavros Sachtouris
import os
35 3f0eae61 Stavros Sachtouris
from logging import getLogger
36 7493ccb6 Stavros Sachtouris
37 7493ccb6 Stavros Sachtouris
from collections import defaultdict
38 7493ccb6 Stavros Sachtouris
from ConfigParser import RawConfigParser, NoOptionError, NoSectionError
39 3f0eae61 Stavros Sachtouris
from re import match
40 7493ccb6 Stavros Sachtouris
41 7493ccb6 Stavros Sachtouris
try:
42 7493ccb6 Stavros Sachtouris
    from collections import OrderedDict
43 7493ccb6 Stavros Sachtouris
except ImportError:
44 1792ed1d Stavros Sachtouris
    from kamaki.clients.utils.ordereddict import OrderedDict
45 7493ccb6 Stavros Sachtouris
46 7493ccb6 Stavros Sachtouris
47 3f0eae61 Stavros Sachtouris
log = getLogger(__name__)
48 3f0eae61 Stavros Sachtouris
49 7493ccb6 Stavros Sachtouris
# Path to the file that stores the configuration
50 7493ccb6 Stavros Sachtouris
CONFIG_PATH = os.path.expanduser('~/.kamakirc')
51 9f1d1fcf Stavros Sachtouris
HISTORY_PATH = os.path.expanduser('~/.kamaki.history')
52 7493ccb6 Stavros Sachtouris
53 7493ccb6 Stavros Sachtouris
# Name of a shell variable to bypass the CONFIG_PATH value
54 7493ccb6 Stavros Sachtouris
CONFIG_ENV = 'KAMAKI_CONFIG'
55 7493ccb6 Stavros Sachtouris
56 7493ccb6 Stavros Sachtouris
HEADER = """
57 f5c28bfa Stavros Sachtouris
# Kamaki configuration file v3 (kamaki >= v0.9)
58 7493ccb6 Stavros Sachtouris
"""
59 7493ccb6 Stavros Sachtouris
60 7493ccb6 Stavros Sachtouris
DEFAULTS = {
61 7493ccb6 Stavros Sachtouris
    'global': {
62 4f6a21f6 Stavros Sachtouris
        'colors': 'off',
63 edf00ab3 Stavros Sachtouris
        'log_file': os.path.expanduser('~/.kamaki.log'),
64 c5b9380c Stavros Sachtouris
        'log_token': 'off',
65 c5b9380c Stavros Sachtouris
        'log_data': 'off',
66 05e144e2 Stavros Sachtouris
        'max_threads': 7,
67 3f0eae61 Stavros Sachtouris
        'history_file': HISTORY_PATH,
68 3f0eae61 Stavros Sachtouris
        'user_cli': 'astakos',
69 3f0eae61 Stavros Sachtouris
        'file_cli': 'pithos',
70 3f0eae61 Stavros Sachtouris
        'server_cli': 'cyclades',
71 3f0eae61 Stavros Sachtouris
        'flavor_cli': 'cyclades',
72 3f0eae61 Stavros Sachtouris
        'network_cli': 'cyclades',
73 3f0eae61 Stavros Sachtouris
        'image_cli': 'image',
74 3f0eae61 Stavros Sachtouris
        'config_cli': 'config',
75 3f0eae61 Stavros Sachtouris
        'history_cli': 'history'
76 f5c28bfa Stavros Sachtouris
        #  Optional command specs:
77 f5c28bfa Stavros Sachtouris
        #  'livetest': 'livetest',
78 f5c28bfa Stavros Sachtouris
        #  'astakos': 'snf-astakos'
79 7493ccb6 Stavros Sachtouris
    },
80 3f0eae61 Stavros Sachtouris
    'remotes':
81 3f0eae61 Stavros Sachtouris
    {
82 3f0eae61 Stavros Sachtouris
        'default': {
83 3f0eae61 Stavros Sachtouris
            'url': '',
84 3f0eae61 Stavros Sachtouris
            'token': ''
85 3f0eae61 Stavros Sachtouris
            #'pithos_type': 'object-store',
86 3f0eae61 Stavros Sachtouris
            #'pithos_version': 'v1',
87 3f0eae61 Stavros Sachtouris
            #'cyclades_type': 'compute',
88 3f0eae61 Stavros Sachtouris
            #'cyclades_version': 'v2.0',
89 3f0eae61 Stavros Sachtouris
            #'plankton_type': 'image',
90 3f0eae61 Stavros Sachtouris
            #'plankton_version': '',
91 3f0eae61 Stavros Sachtouris
            #'astakos_type': 'identity',
92 3f0eae61 Stavros Sachtouris
            #'astakos_version': 'v2.0'
93 3f0eae61 Stavros Sachtouris
        }
94 7493ccb6 Stavros Sachtouris
    }
95 7493ccb6 Stavros Sachtouris
}
96 7493ccb6 Stavros Sachtouris
97 7493ccb6 Stavros Sachtouris
98 7493ccb6 Stavros Sachtouris
class Config(RawConfigParser):
99 3f0eae61 Stavros Sachtouris
    def __init__(self, path=None, with_defaults=True):
100 7493ccb6 Stavros Sachtouris
        RawConfigParser.__init__(self, dict_type=OrderedDict)
101 7493ccb6 Stavros Sachtouris
        self.path = path or os.environ.get(CONFIG_ENV, CONFIG_PATH)
102 7493ccb6 Stavros Sachtouris
        self._overrides = defaultdict(dict)
103 3f0eae61 Stavros Sachtouris
        if with_defaults:
104 3f0eae61 Stavros Sachtouris
            self._load_defaults()
105 7493ccb6 Stavros Sachtouris
        self.read(self.path)
106 7493ccb6 Stavros Sachtouris
107 14b9a185 Stavros Sachtouris
        assert False, 'Config.__init__: translate remotes to dict first'
108 14b9a185 Stavros Sachtouris
109 3f0eae61 Stavros Sachtouris
    @staticmethod
110 3f0eae61 Stavros Sachtouris
    def _remote_name(full_section_name):
111 3f0eae61 Stavros Sachtouris
        matcher = match('remote "(\w+)"', full_section_name)
112 3f0eae61 Stavros Sachtouris
        return matcher.groups()[0] if matcher else None
113 3f0eae61 Stavros Sachtouris
114 14b9a185 Stavros Sachtouris
    def rescue_old_file(self):
115 14b9a185 Stavros Sachtouris
        pass
116 14b9a185 Stavros Sachtouris
        # global.url, global.token --> remote.default.url, remote.default.token
117 14b9a185 Stavros Sachtouris
        # remove global.url, global.token
118 14b9a185 Stavros Sachtouris
        # translation for <service> or <command> settings
119 14b9a185 Stavros Sachtouris
        # <service> or <command group> settings --> translation --> global
120 14b9a185 Stavros Sachtouris
121 3f0eae61 Stavros Sachtouris
    def guess_version(self):
122 3f0eae61 Stavros Sachtouris
        checker = Config(self.path, with_defaults=False)
123 3f0eae61 Stavros Sachtouris
        sections = checker.sections()
124 3f0eae61 Stavros Sachtouris
        log.warning('Config file heuristic 1: global section ?')
125 3f0eae61 Stavros Sachtouris
        if 'global' in sections:
126 3f0eae61 Stavros Sachtouris
            if checker.get('global', 'url') or checker.get('global', 'token'):
127 3f0eae61 Stavros Sachtouris
                log.warning('..... config file has an old global section')
128 14b9a185 Stavros Sachtouris
                return 2.0
129 14b9a185 Stavros Sachtouris
        log.warning('........ nope')
130 3f0eae61 Stavros Sachtouris
        log.warning('Config file heuristic 2: at least 1 remote section ?')
131 3f0eae61 Stavros Sachtouris
        for section in sections:
132 3f0eae61 Stavros Sachtouris
            if self._remote_name(section):
133 3f0eae61 Stavros Sachtouris
                log.warning('... found %s section' % section)
134 14b9a185 Stavros Sachtouris
                return 3.0
135 14b9a185 Stavros Sachtouris
        log.warning('........ nope')
136 3f0eae61 Stavros Sachtouris
        log.warning('All heuristics failed, cannot decide')
137 14b9a185 Stavros Sachtouris
        return 0.0
138 3f0eae61 Stavros Sachtouris
139 7493ccb6 Stavros Sachtouris
    def _load_defaults(self):
140 7493ccb6 Stavros Sachtouris
        for section, options in DEFAULTS.items():
141 7493ccb6 Stavros Sachtouris
            for option, val in options.items():
142 7493ccb6 Stavros Sachtouris
                self.set(section, option, val)
143 7493ccb6 Stavros Sachtouris
144 f724cd35 Stavros Sachtouris
    def _get_dict(self, section, include_defaults=True):
145 f724cd35 Stavros Sachtouris
        try:
146 f724cd35 Stavros Sachtouris
            d = dict(DEFAULTS[section]) if include_defaults else {}
147 f724cd35 Stavros Sachtouris
        except KeyError:
148 f724cd35 Stavros Sachtouris
            d = {}
149 f724cd35 Stavros Sachtouris
        try:
150 f724cd35 Stavros Sachtouris
            d.update(RawConfigParser.items(self, section))
151 f724cd35 Stavros Sachtouris
        except NoSectionError:
152 f724cd35 Stavros Sachtouris
            pass
153 f724cd35 Stavros Sachtouris
        return d
154 f724cd35 Stavros Sachtouris
155 8eb8c540 Stavros Sachtouris
    def reload(self):
156 8eb8c540 Stavros Sachtouris
        self = self.__init__(self.path)
157 8eb8c540 Stavros Sachtouris
158 7493ccb6 Stavros Sachtouris
    def get(self, section, option):
159 7493ccb6 Stavros Sachtouris
        value = self._overrides.get(section, {}).get(option)
160 7493ccb6 Stavros Sachtouris
        if value is not None:
161 7493ccb6 Stavros Sachtouris
            return value
162 7493ccb6 Stavros Sachtouris
163 7493ccb6 Stavros Sachtouris
        try:
164 7493ccb6 Stavros Sachtouris
            return RawConfigParser.get(self, section, option)
165 7493ccb6 Stavros Sachtouris
        except (NoSectionError, NoOptionError):
166 7493ccb6 Stavros Sachtouris
            return DEFAULTS.get(section, {}).get(option)
167 7493ccb6 Stavros Sachtouris
168 7493ccb6 Stavros Sachtouris
    def set(self, section, option, value):
169 7493ccb6 Stavros Sachtouris
        if section not in RawConfigParser.sections(self):
170 7493ccb6 Stavros Sachtouris
            self.add_section(section)
171 7493ccb6 Stavros Sachtouris
        RawConfigParser.set(self, section, option, value)
172 7493ccb6 Stavros Sachtouris
173 3fe56be4 Stavros Sachtouris
    def remove_option(self, section, option, also_remove_default=False):
174 7493ccb6 Stavros Sachtouris
        try:
175 3fe56be4 Stavros Sachtouris
            if also_remove_default:
176 3fe56be4 Stavros Sachtouris
                DEFAULTS[section].pop(option)
177 7493ccb6 Stavros Sachtouris
            RawConfigParser.remove_option(self, section, option)
178 7493ccb6 Stavros Sachtouris
        except NoSectionError:
179 7493ccb6 Stavros Sachtouris
            pass
180 7493ccb6 Stavros Sachtouris
181 f724cd35 Stavros Sachtouris
    def keys(self, section, include_defaults=True):
182 f724cd35 Stavros Sachtouris
        d = self._get_dict(section, include_defaults)
183 f724cd35 Stavros Sachtouris
        return d.keys()
184 f724cd35 Stavros Sachtouris
185 57ecec97 Stavros Sachtouris
    def items(self, section, include_defaults=True):
186 f724cd35 Stavros Sachtouris
        d = self._get_dict(section, include_defaults)
187 7493ccb6 Stavros Sachtouris
        return d.items()
188 7493ccb6 Stavros Sachtouris
189 7493ccb6 Stavros Sachtouris
    def override(self, section, option, value):
190 7493ccb6 Stavros Sachtouris
        self._overrides[section][option] = value
191 7493ccb6 Stavros Sachtouris
192 7493ccb6 Stavros Sachtouris
    def write(self):
193 7493ccb6 Stavros Sachtouris
        with open(self.path, 'w') as f:
194 7493ccb6 Stavros Sachtouris
            os.chmod(self.path, 0600)
195 7493ccb6 Stavros Sachtouris
            f.write(HEADER.lstrip())
196 8eb8c540 Stavros Sachtouris
            f.flush()
197 14b9a185 Stavros Sachtouris
            assert False, 'Config.write: Trasnlate remotes to file first'
198 7493ccb6 Stavros Sachtouris
            RawConfigParser.write(self, f)