Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / config / __init__.py @ 50a32c37

History | View | Annotate | Download (15.7 kB)

1 e3f01d64 Stavros Sachtouris
# Copyright 2011-2013 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 c5997814 Stavros Sachtouris
from sys import stdout, stderr
37 7493ccb6 Stavros Sachtouris
38 7493ccb6 Stavros Sachtouris
from collections import defaultdict
39 29be4062 Stavros Sachtouris
from ConfigParser import RawConfigParser, NoOptionError, NoSectionError, Error
40 3f0eae61 Stavros Sachtouris
from re import match
41 7493ccb6 Stavros Sachtouris
42 ce9ccb40 Stavros Sachtouris
from kamaki.cli.errors import CLISyntaxError
43 144b3551 Stavros Sachtouris
from kamaki import __version__
44 ce9ccb40 Stavros Sachtouris
45 7493ccb6 Stavros Sachtouris
try:
46 7493ccb6 Stavros Sachtouris
    from collections import OrderedDict
47 7493ccb6 Stavros Sachtouris
except ImportError:
48 1792ed1d Stavros Sachtouris
    from kamaki.clients.utils.ordereddict import OrderedDict
49 7493ccb6 Stavros Sachtouris
50 7493ccb6 Stavros Sachtouris
51 29be4062 Stavros Sachtouris
class InvalidCloudNameError(Error):
52 c5997814 Stavros Sachtouris
    """A valid cloud name must pass through this regex: ([~@#$:.-\w]+)"""
53 29be4062 Stavros Sachtouris
54 29be4062 Stavros Sachtouris
55 3f0eae61 Stavros Sachtouris
log = getLogger(__name__)
56 3f0eae61 Stavros Sachtouris
57 7493ccb6 Stavros Sachtouris
# Path to the file that stores the configuration
58 7493ccb6 Stavros Sachtouris
CONFIG_PATH = os.path.expanduser('~/.kamakirc')
59 9f1d1fcf Stavros Sachtouris
HISTORY_PATH = os.path.expanduser('~/.kamaki.history')
60 6144f3d4 Stavros Sachtouris
CLOUD_PREFIX = 'cloud'
61 7493ccb6 Stavros Sachtouris
62 7493ccb6 Stavros Sachtouris
# Name of a shell variable to bypass the CONFIG_PATH value
63 7493ccb6 Stavros Sachtouris
CONFIG_ENV = 'KAMAKI_CONFIG'
64 7493ccb6 Stavros Sachtouris
65 144b3551 Stavros Sachtouris
version = ''
66 144b3551 Stavros Sachtouris
for c in '%s' % __version__:
67 144b3551 Stavros Sachtouris
    if c not in '0.123456789':
68 144b3551 Stavros Sachtouris
        break
69 144b3551 Stavros Sachtouris
    version += c
70 c825ddc9 Stavros Sachtouris
HEADER = '# Kamaki configuration file v%s\n' % version
71 7493ccb6 Stavros Sachtouris
72 7493ccb6 Stavros Sachtouris
DEFAULTS = {
73 7493ccb6 Stavros Sachtouris
    'global': {
74 144b3551 Stavros Sachtouris
        'default_cloud': '',
75 4f6a21f6 Stavros Sachtouris
        'colors': 'off',
76 edf00ab3 Stavros Sachtouris
        'log_file': os.path.expanduser('~/.kamaki.log'),
77 c5b9380c Stavros Sachtouris
        'log_token': 'off',
78 c5b9380c Stavros Sachtouris
        'log_data': 'off',
79 64a3c0de Stavros Sachtouris
        'log_pid': 'off',
80 3f0eae61 Stavros Sachtouris
        'history_file': HISTORY_PATH,
81 50a32c37 Stavros Sachtouris
        'history_limit': 0,
82 3f0eae61 Stavros Sachtouris
        'user_cli': 'astakos',
83 25f9a991 Stavros Sachtouris
        'quota_cli': 'astakos',
84 25f9a991 Stavros Sachtouris
        'resource_cli': 'astakos',
85 c308d73f Stavros Sachtouris
        'project_cli': 'astakos',
86 9d84caa4 Stavros Sachtouris
        'membership_cli': 'astakos',
87 3f0eae61 Stavros Sachtouris
        'file_cli': 'pithos',
88 7b109aa7 Stavros Sachtouris
        'container_cli': 'pithos',
89 bfd0f8db Stavros Sachtouris
        'sharer_cli': 'pithos',
90 bfd0f8db Stavros Sachtouris
        'group_cli': 'pithos',
91 3f0eae61 Stavros Sachtouris
        'server_cli': 'cyclades',
92 3f0eae61 Stavros Sachtouris
        'flavor_cli': 'cyclades',
93 e864cd9e Stavros Sachtouris
        'network_cli': 'network',
94 e864cd9e Stavros Sachtouris
        'subnet_cli': 'network',
95 e864cd9e Stavros Sachtouris
        'port_cli': 'network',
96 d1bced10 Stavros Sachtouris
        'ip_cli': 'network',
97 3f0eae61 Stavros Sachtouris
        'image_cli': 'image',
98 5c5eb675 Stavros Sachtouris
        'imagecompute_cli': 'image',
99 3f0eae61 Stavros Sachtouris
        'config_cli': 'config',
100 3f0eae61 Stavros Sachtouris
        'history_cli': 'history'
101 f5c28bfa Stavros Sachtouris
        #  Optional command specs:
102 25f9a991 Stavros Sachtouris
        #  'service_cli': 'astakos'
103 25f9a991 Stavros Sachtouris
        #  'endpoint_cli': 'astakos'
104 25f9a991 Stavros Sachtouris
        #  'commission_cli': 'astakos'
105 7493ccb6 Stavros Sachtouris
    },
106 9f5cbafe Stavros Sachtouris
    CLOUD_PREFIX: {
107 144b3551 Stavros Sachtouris
        #'default': {
108 144b3551 Stavros Sachtouris
        #    'url': '',
109 144b3551 Stavros Sachtouris
        #    'token': ''
110 5e4a0bb9 Stavros Sachtouris
        #    'pithos_container': 'THIS IS DANGEROUS'
111 144b3551 Stavros Sachtouris
        #    'pithos_type': 'object-store',
112 144b3551 Stavros Sachtouris
        #    'pithos_version': 'v1',
113 144b3551 Stavros Sachtouris
        #    'cyclades_type': 'compute',
114 144b3551 Stavros Sachtouris
        #    'cyclades_version': 'v2.0',
115 144b3551 Stavros Sachtouris
        #    'plankton_type': 'image',
116 144b3551 Stavros Sachtouris
        #    'plankton_version': '',
117 144b3551 Stavros Sachtouris
        #    'astakos_type': 'identity',
118 144b3551 Stavros Sachtouris
        #    'astakos_version': 'v2.0'
119 144b3551 Stavros Sachtouris
        #}
120 7493ccb6 Stavros Sachtouris
    }
121 7493ccb6 Stavros Sachtouris
}
122 7493ccb6 Stavros Sachtouris
123 7493ccb6 Stavros Sachtouris
124 7493ccb6 Stavros Sachtouris
class Config(RawConfigParser):
125 c5997814 Stavros Sachtouris
126 3f0eae61 Stavros Sachtouris
    def __init__(self, path=None, with_defaults=True):
127 7493ccb6 Stavros Sachtouris
        RawConfigParser.__init__(self, dict_type=OrderedDict)
128 7493ccb6 Stavros Sachtouris
        self.path = path or os.environ.get(CONFIG_ENV, CONFIG_PATH)
129 7493ccb6 Stavros Sachtouris
        self._overrides = defaultdict(dict)
130 3f0eae61 Stavros Sachtouris
        if with_defaults:
131 3f0eae61 Stavros Sachtouris
            self._load_defaults()
132 7493ccb6 Stavros Sachtouris
        self.read(self.path)
133 7493ccb6 Stavros Sachtouris
134 ce9ccb40 Stavros Sachtouris
        for section in self.sections():
135 144b3551 Stavros Sachtouris
            r = self._cloud_name(section)
136 ce9ccb40 Stavros Sachtouris
            if r:
137 ce9ccb40 Stavros Sachtouris
                for k, v in self.items(section):
138 144b3551 Stavros Sachtouris
                    self.set_cloud(r, k, v)
139 ce9ccb40 Stavros Sachtouris
                self.remove_section(section)
140 14b9a185 Stavros Sachtouris
141 3f0eae61 Stavros Sachtouris
    @staticmethod
142 144b3551 Stavros Sachtouris
    def _cloud_name(full_section_name):
143 29be4062 Stavros Sachtouris
        if not full_section_name.startswith(CLOUD_PREFIX + ' '):
144 29be4062 Stavros Sachtouris
            return None
145 c5997814 Stavros Sachtouris
        matcher = match(CLOUD_PREFIX + ' "([~@#$.:\-\w]+)"', full_section_name)
146 29be4062 Stavros Sachtouris
        if matcher:
147 29be4062 Stavros Sachtouris
            return matcher.groups()[0]
148 29be4062 Stavros Sachtouris
        else:
149 29be4062 Stavros Sachtouris
            icn = full_section_name[len(CLOUD_PREFIX) + 1:]
150 29be4062 Stavros Sachtouris
            raise InvalidCloudNameError('Invalid Cloud Name %s' % icn)
151 3f0eae61 Stavros Sachtouris
152 c5997814 Stavros Sachtouris
    def rescue_old_file(self, err=stderr):
153 ce9ccb40 Stavros Sachtouris
        lost_terms = []
154 ce9ccb40 Stavros Sachtouris
        global_terms = DEFAULTS['global'].keys()
155 ce9ccb40 Stavros Sachtouris
        translations = dict(
156 ce9ccb40 Stavros Sachtouris
            config=dict(serv='', cmd='config'),
157 ce9ccb40 Stavros Sachtouris
            history=dict(serv='', cmd='history'),
158 ce9ccb40 Stavros Sachtouris
            pithos=dict(serv='pithos', cmd='file'),
159 ce9ccb40 Stavros Sachtouris
            file=dict(serv='pithos', cmd='file'),
160 ce9ccb40 Stavros Sachtouris
            store=dict(serv='pithos', cmd='file'),
161 ce9ccb40 Stavros Sachtouris
            storage=dict(serv='pithos', cmd='file'),
162 ce9ccb40 Stavros Sachtouris
            image=dict(serv='plankton', cmd='image'),
163 ce9ccb40 Stavros Sachtouris
            plankton=dict(serv='plankton', cmd='image'),
164 ce9ccb40 Stavros Sachtouris
            compute=dict(serv='compute', cmd=''),
165 ce9ccb40 Stavros Sachtouris
            cyclades=dict(serv='compute', cmd='server'),
166 ce9ccb40 Stavros Sachtouris
            server=dict(serv='compute', cmd='server'),
167 ce9ccb40 Stavros Sachtouris
            flavor=dict(serv='compute', cmd='flavor'),
168 a4986073 Stavros Sachtouris
            network=dict(serv='network', cmd='network'),
169 ce9ccb40 Stavros Sachtouris
            astakos=dict(serv='astakos', cmd='user'),
170 ce9ccb40 Stavros Sachtouris
            user=dict(serv='astakos', cmd='user'),
171 ce9ccb40 Stavros Sachtouris
        )
172 ce9ccb40 Stavros Sachtouris
173 a4986073 Stavros Sachtouris
        dc = 'default_' + CLOUD_PREFIX
174 a4986073 Stavros Sachtouris
        self.set('global', dc, self.get('global', dc) or 'default')
175 ce9ccb40 Stavros Sachtouris
        for s in self.sections():
176 c5997814 Stavros Sachtouris
            if s in ('global', ):
177 ce9ccb40 Stavros Sachtouris
                # global.url, global.token -->
178 144b3551 Stavros Sachtouris
                # cloud.default.url, cloud.default.token
179 ce9ccb40 Stavros Sachtouris
                for term in set(self.keys(s)).difference(global_terms):
180 ce9ccb40 Stavros Sachtouris
                    if term not in ('url', 'token'):
181 ce9ccb40 Stavros Sachtouris
                        lost_terms.append('%s.%s = %s' % (
182 ce9ccb40 Stavros Sachtouris
                            s, term, self.get(s, term)))
183 ce9ccb40 Stavros Sachtouris
                        self.remove_option(s, term)
184 ce9ccb40 Stavros Sachtouris
                        continue
185 ce9ccb40 Stavros Sachtouris
                    gval = self.get(s, term)
186 c5997814 Stavros Sachtouris
                    default_cloud = self.get(
187 c5997814 Stavros Sachtouris
                        'global', 'default_cloud') or 'default'
188 c825ddc9 Stavros Sachtouris
                    try:
189 c5997814 Stavros Sachtouris
                        cval = self.get_cloud(default_cloud, term)
190 c825ddc9 Stavros Sachtouris
                    except KeyError:
191 c825ddc9 Stavros Sachtouris
                        cval = ''
192 ce9ccb40 Stavros Sachtouris
                    if gval and cval and (
193 ce9ccb40 Stavros Sachtouris
                        gval.lower().strip('/') != cval.lower().strip('/')):
194 ce9ccb40 Stavros Sachtouris
                            raise CLISyntaxError(
195 c5997814 Stavros Sachtouris
                                'Conflicting values for default %s' % (
196 c5997814 Stavros Sachtouris
                                    term),
197 ce9ccb40 Stavros Sachtouris
                                importance=2, details=[
198 ce9ccb40 Stavros Sachtouris
                                    ' global.%s:  %s' % (term, gval),
199 c5997814 Stavros Sachtouris
                                    ' %s.%s.%s:  %s' % (
200 c5997814 Stavros Sachtouris
                                        CLOUD_PREFIX,
201 c5997814 Stavros Sachtouris
                                        default_cloud,
202 c5997814 Stavros Sachtouris
                                        term,
203 c5997814 Stavros Sachtouris
                                        cval),
204 ce9ccb40 Stavros Sachtouris
                                    'Please remove one of them manually:',
205 ce9ccb40 Stavros Sachtouris
                                    ' /config delete global.%s' % term,
206 ce9ccb40 Stavros Sachtouris
                                    ' or'
207 c5997814 Stavros Sachtouris
                                    ' /config delete %s.%s.%s' % (
208 c5997814 Stavros Sachtouris
                                        CLOUD_PREFIX, default_cloud, term),
209 ce9ccb40 Stavros Sachtouris
                                    'and try again'])
210 ce9ccb40 Stavros Sachtouris
                    elif gval:
211 c5997814 Stavros Sachtouris
                        err.write(u'... rescue %s.%s => %s.%s.%s\n' % (
212 c5997814 Stavros Sachtouris
                            s, term, CLOUD_PREFIX, default_cloud, term))
213 c5997814 Stavros Sachtouris
                        err.flush()
214 144b3551 Stavros Sachtouris
                        self.set_cloud('default', term, gval)
215 ce9ccb40 Stavros Sachtouris
                    self.remove_option(s, term)
216 a4986073 Stavros Sachtouris
                print 'CHECK'
217 a4986073 Stavros Sachtouris
                for term, wrong, right in (
218 a4986073 Stavros Sachtouris
                        ('ip', 'cyclades', 'network'),
219 a4986073 Stavros Sachtouris
                        ('network', 'cyclades', 'network'),):
220 a4986073 Stavros Sachtouris
                    k = '%s_cli' % term
221 a4986073 Stavros Sachtouris
                    v = self.get(s, k)
222 a4986073 Stavros Sachtouris
                    if v in (wrong, ):
223 a4986073 Stavros Sachtouris
                        err.write('... change %s.%s value: `%s` => `%s`\n' % (
224 a4986073 Stavros Sachtouris
                            s, k, wrong, right))
225 a4986073 Stavros Sachtouris
                        err.flush()
226 a4986073 Stavros Sachtouris
                        self.set(s, k, right)
227 ce9ccb40 Stavros Sachtouris
            # translation for <service> or <command> settings
228 ce9ccb40 Stavros Sachtouris
            # <service> or <command group> settings --> translation --> global
229 ce9ccb40 Stavros Sachtouris
            elif s in translations:
230 ce9ccb40 Stavros Sachtouris
231 ce9ccb40 Stavros Sachtouris
                if s in ('history',):
232 ce9ccb40 Stavros Sachtouris
                    k = 'file'
233 ce9ccb40 Stavros Sachtouris
                    v = self.get(s, k)
234 ce9ccb40 Stavros Sachtouris
                    if v:
235 c5997814 Stavros Sachtouris
                        err.write(u'... rescue %s.%s => global.%s_%s\n' % (
236 ce9ccb40 Stavros Sachtouris
                            s, k, s, k))
237 c5997814 Stavros Sachtouris
                        err.flush()
238 ce9ccb40 Stavros Sachtouris
                        self.set('global', '%s_%s' % (s, k), v)
239 ce9ccb40 Stavros Sachtouris
                        self.remove_option(s, k)
240 ce9ccb40 Stavros Sachtouris
241 ce9ccb40 Stavros Sachtouris
                trn = translations[s]
242 ce9ccb40 Stavros Sachtouris
                for k, v in self.items(s, False):
243 ce9ccb40 Stavros Sachtouris
                    if v and k in ('cli',):
244 c5997814 Stavros Sachtouris
                        err.write(u'... rescue %s.%s => global.%s_cli\n' % (
245 ce9ccb40 Stavros Sachtouris
                            s, k, trn['cmd']))
246 c5997814 Stavros Sachtouris
                        err.flush()
247 144b3551 Stavros Sachtouris
                        self.set('global', '%s_cli' % trn['cmd'], v)
248 144b3551 Stavros Sachtouris
                    elif k in ('container',) and trn['serv'] in ('pithos',):
249 c5997814 Stavros Sachtouris
                        err.write(
250 c5997814 Stavros Sachtouris
                            u'... rescue %s.%s => %s.default.pithos_%s\n' % (
251 c5997814 Stavros Sachtouris
                                s, k, CLOUD_PREFIX, k))
252 c5997814 Stavros Sachtouris
                        err.flush()
253 144b3551 Stavros Sachtouris
                        self.set_cloud('default', 'pithos_%s' % k, v)
254 144b3551 Stavros Sachtouris
                    else:
255 ce9ccb40 Stavros Sachtouris
                        lost_terms.append('%s.%s = %s' % (s, k, v))
256 ce9ccb40 Stavros Sachtouris
                self.remove_section(s)
257 ce9ccb40 Stavros Sachtouris
        #  self.pretty_print()
258 ce9ccb40 Stavros Sachtouris
        return lost_terms
259 ce9ccb40 Stavros Sachtouris
260 c5997814 Stavros Sachtouris
    def pretty_print(self, out=stdout):
261 ce9ccb40 Stavros Sachtouris
        for s in self.sections():
262 c5997814 Stavros Sachtouris
            out.write(s)
263 c5997814 Stavros Sachtouris
            out.flush()
264 ce9ccb40 Stavros Sachtouris
            for k, v in self.items(s):
265 ce9ccb40 Stavros Sachtouris
                if isinstance(v, dict):
266 c5997814 Stavros Sachtouris
                    out.write(u'\t%s => {\n' % k)
267 c5997814 Stavros Sachtouris
                    out.flush()
268 ce9ccb40 Stavros Sachtouris
                    for ki, vi in v.items():
269 c5997814 Stavros Sachtouris
                        out.write(u'\t\t%s => %s\n' % (ki, vi))
270 c5997814 Stavros Sachtouris
                        out.flush()
271 c5997814 Stavros Sachtouris
                    out.write(u'\t}\n')
272 ce9ccb40 Stavros Sachtouris
                else:
273 c5997814 Stavros Sachtouris
                    out.write(u'\t %s => %s\n' % (k, v))
274 c5997814 Stavros Sachtouris
                out.flush()
275 14b9a185 Stavros Sachtouris
276 3f0eae61 Stavros Sachtouris
    def guess_version(self):
277 144b3551 Stavros Sachtouris
        """
278 3564be49 Stavros Sachtouris
        :returns: (float) version of the config file or 0.9 if unrecognized
279 144b3551 Stavros Sachtouris
        """
280 3f0eae61 Stavros Sachtouris
        checker = Config(self.path, with_defaults=False)
281 3f0eae61 Stavros Sachtouris
        sections = checker.sections()
282 f1d06d74 Stavros Sachtouris
        log.debug('Config file heuristic 1: old global section ?')
283 3f0eae61 Stavros Sachtouris
        if 'global' in sections:
284 3f0eae61 Stavros Sachtouris
            if checker.get('global', 'url') or checker.get('global', 'token'):
285 f1d06d74 Stavros Sachtouris
                log.debug('..... config file has an old global section')
286 c825ddc9 Stavros Sachtouris
                return 0.8
287 f1d06d74 Stavros Sachtouris
        log.debug('........ nope')
288 f1d06d74 Stavros Sachtouris
        log.debug('Config file heuristic 2: Any cloud sections ?')
289 6144f3d4 Stavros Sachtouris
        if CLOUD_PREFIX in sections:
290 6144f3d4 Stavros Sachtouris
            for r in self.keys(CLOUD_PREFIX):
291 f1d06d74 Stavros Sachtouris
                log.debug('... found cloud "%s"' % r)
292 a4986073 Stavros Sachtouris
            ipv = self.get('global', 'ip_cli')
293 a4986073 Stavros Sachtouris
            if ipv in ('cyclades', ):
294 a4986073 Stavros Sachtouris
                    return 0.11
295 a4986073 Stavros Sachtouris
            netv = self.get('global', 'network_cli')
296 a4986073 Stavros Sachtouris
            if netv in ('cyclades', ):
297 a4986073 Stavros Sachtouris
                return 0.10
298 a4986073 Stavros Sachtouris
            return 0.12
299 f1d06d74 Stavros Sachtouris
        log.debug('........ nope')
300 f1d06d74 Stavros Sachtouris
        log.debug('All heuristics failed, cannot decide')
301 a4986073 Stavros Sachtouris
        return 0.12
302 3f0eae61 Stavros Sachtouris
303 144b3551 Stavros Sachtouris
    def get_cloud(self, cloud, option):
304 ce9ccb40 Stavros Sachtouris
        """
305 144b3551 Stavros Sachtouris
        :param cloud: (str) cloud alias
306 ce9ccb40 Stavros Sachtouris

307 144b3551 Stavros Sachtouris
        :param option: (str) option in cloud section
308 ce9ccb40 Stavros Sachtouris

309 ce9ccb40 Stavros Sachtouris
        :returns: (str) the value assigned on this option
310 ce9ccb40 Stavros Sachtouris

311 144b3551 Stavros Sachtouris
        :raises KeyError: if cloud or cloud's option does not exist
312 ce9ccb40 Stavros Sachtouris
        """
313 c22183b9 Stavros Sachtouris
        r = self.get(CLOUD_PREFIX, cloud) if cloud else None
314 ce9ccb40 Stavros Sachtouris
        if not r:
315 144b3551 Stavros Sachtouris
            raise KeyError('Cloud "%s" does not exist' % cloud)
316 ce9ccb40 Stavros Sachtouris
        return r[option]
317 ce9ccb40 Stavros Sachtouris
318 144b3551 Stavros Sachtouris
    def set_cloud(self, cloud, option, value):
319 ce9ccb40 Stavros Sachtouris
        try:
320 6144f3d4 Stavros Sachtouris
            d = self.get(CLOUD_PREFIX, cloud) or dict()
321 ce9ccb40 Stavros Sachtouris
        except KeyError:
322 844a6bdb Stavros Sachtouris
            d = dict()
323 ce9ccb40 Stavros Sachtouris
        d[option] = value
324 6144f3d4 Stavros Sachtouris
        self.set(CLOUD_PREFIX, cloud, d)
325 362adf50 Stavros Sachtouris
326 7493ccb6 Stavros Sachtouris
    def _load_defaults(self):
327 7493ccb6 Stavros Sachtouris
        for section, options in DEFAULTS.items():
328 7493ccb6 Stavros Sachtouris
            for option, val in options.items():
329 7493ccb6 Stavros Sachtouris
                self.set(section, option, val)
330 7493ccb6 Stavros Sachtouris
331 f724cd35 Stavros Sachtouris
    def _get_dict(self, section, include_defaults=True):
332 f724cd35 Stavros Sachtouris
        try:
333 f724cd35 Stavros Sachtouris
            d = dict(DEFAULTS[section]) if include_defaults else {}
334 f724cd35 Stavros Sachtouris
        except KeyError:
335 f724cd35 Stavros Sachtouris
            d = {}
336 f724cd35 Stavros Sachtouris
        try:
337 f724cd35 Stavros Sachtouris
            d.update(RawConfigParser.items(self, section))
338 f724cd35 Stavros Sachtouris
        except NoSectionError:
339 f724cd35 Stavros Sachtouris
            pass
340 f724cd35 Stavros Sachtouris
        return d
341 f724cd35 Stavros Sachtouris
342 8eb8c540 Stavros Sachtouris
    def reload(self):
343 8eb8c540 Stavros Sachtouris
        self = self.__init__(self.path)
344 8eb8c540 Stavros Sachtouris
345 7493ccb6 Stavros Sachtouris
    def get(self, section, option):
346 114e19da Stavros Sachtouris
        """
347 144b3551 Stavros Sachtouris
        :param section: (str) HINT: for clouds, use cloud.<section>
348 114e19da Stavros Sachtouris

349 114e19da Stavros Sachtouris
        :param option: (str)
350 114e19da Stavros Sachtouris

351 114e19da Stavros Sachtouris
        :returns: (str) the value stored at section: {option: value}
352 114e19da Stavros Sachtouris
        """
353 7493ccb6 Stavros Sachtouris
        value = self._overrides.get(section, {}).get(option)
354 7493ccb6 Stavros Sachtouris
        if value is not None:
355 7493ccb6 Stavros Sachtouris
            return value
356 6144f3d4 Stavros Sachtouris
        prefix = CLOUD_PREFIX + '.'
357 144b3551 Stavros Sachtouris
        if section.startswith(prefix):
358 144b3551 Stavros Sachtouris
            return self.get_cloud(section[len(prefix):], option)
359 7493ccb6 Stavros Sachtouris
        try:
360 7493ccb6 Stavros Sachtouris
            return RawConfigParser.get(self, section, option)
361 7493ccb6 Stavros Sachtouris
        except (NoSectionError, NoOptionError):
362 7493ccb6 Stavros Sachtouris
            return DEFAULTS.get(section, {}).get(option)
363 7493ccb6 Stavros Sachtouris
364 7493ccb6 Stavros Sachtouris
    def set(self, section, option, value):
365 114e19da Stavros Sachtouris
        """
366 144b3551 Stavros Sachtouris
        :param section: (str) HINT: for remotes use cloud.<section>
367 114e19da Stavros Sachtouris

368 114e19da Stavros Sachtouris
        :param option: (str)
369 114e19da Stavros Sachtouris

370 114e19da Stavros Sachtouris
        :param value: str
371 114e19da Stavros Sachtouris
        """
372 6144f3d4 Stavros Sachtouris
        prefix = CLOUD_PREFIX + '.'
373 144b3551 Stavros Sachtouris
        if section.startswith(prefix):
374 29be4062 Stavros Sachtouris
            cloud = self._cloud_name(
375 29be4062 Stavros Sachtouris
                CLOUD_PREFIX + ' "' + section[len(prefix):] + '"')
376 29be4062 Stavros Sachtouris
            return self.set_cloud(cloud, option, value)
377 7493ccb6 Stavros Sachtouris
        if section not in RawConfigParser.sections(self):
378 7493ccb6 Stavros Sachtouris
            self.add_section(section)
379 8556d269 Stavros Sachtouris
        return RawConfigParser.set(self, section, option, value)
380 7493ccb6 Stavros Sachtouris
381 3fe56be4 Stavros Sachtouris
    def remove_option(self, section, option, also_remove_default=False):
382 7493ccb6 Stavros Sachtouris
        try:
383 3fe56be4 Stavros Sachtouris
            if also_remove_default:
384 3fe56be4 Stavros Sachtouris
                DEFAULTS[section].pop(option)
385 7493ccb6 Stavros Sachtouris
            RawConfigParser.remove_option(self, section, option)
386 8556d269 Stavros Sachtouris
        except (NoSectionError, KeyError):
387 7493ccb6 Stavros Sachtouris
            pass
388 7493ccb6 Stavros Sachtouris
389 a7aacf12 Stavros Sachtouris
    def remove_from_cloud(self, cloud, option):
390 6144f3d4 Stavros Sachtouris
        d = self.get(CLOUD_PREFIX, cloud)
391 844a6bdb Stavros Sachtouris
        if isinstance(d, dict):
392 844a6bdb Stavros Sachtouris
            d.pop(option)
393 844a6bdb Stavros Sachtouris
394 f724cd35 Stavros Sachtouris
    def keys(self, section, include_defaults=True):
395 f724cd35 Stavros Sachtouris
        d = self._get_dict(section, include_defaults)
396 f724cd35 Stavros Sachtouris
        return d.keys()
397 f724cd35 Stavros Sachtouris
398 57ecec97 Stavros Sachtouris
    def items(self, section, include_defaults=True):
399 f724cd35 Stavros Sachtouris
        d = self._get_dict(section, include_defaults)
400 7493ccb6 Stavros Sachtouris
        return d.items()
401 7493ccb6 Stavros Sachtouris
402 7493ccb6 Stavros Sachtouris
    def override(self, section, option, value):
403 7493ccb6 Stavros Sachtouris
        self._overrides[section][option] = value
404 7493ccb6 Stavros Sachtouris
405 7493ccb6 Stavros Sachtouris
    def write(self):
406 35d47a6c Stavros Sachtouris
        cld_bu = self._get_dict(CLOUD_PREFIX)
407 6144f3d4 Stavros Sachtouris
        try:
408 6144f3d4 Stavros Sachtouris
            for r, d in self.items(CLOUD_PREFIX):
409 6144f3d4 Stavros Sachtouris
                for k, v in d.items():
410 6144f3d4 Stavros Sachtouris
                    self.set(CLOUD_PREFIX + ' "%s"' % r, k, v)
411 6144f3d4 Stavros Sachtouris
            self.remove_section(CLOUD_PREFIX)
412 6144f3d4 Stavros Sachtouris
413 6144f3d4 Stavros Sachtouris
            with open(self.path, 'w') as f:
414 6144f3d4 Stavros Sachtouris
                os.chmod(self.path, 0600)
415 6144f3d4 Stavros Sachtouris
                f.write(HEADER.lstrip())
416 6144f3d4 Stavros Sachtouris
                f.flush()
417 6144f3d4 Stavros Sachtouris
                RawConfigParser.write(self, f)
418 6144f3d4 Stavros Sachtouris
        finally:
419 6144f3d4 Stavros Sachtouris
            if CLOUD_PREFIX not in self.sections():
420 6144f3d4 Stavros Sachtouris
                self.add_section(CLOUD_PREFIX)
421 35d47a6c Stavros Sachtouris
            for cloud, d in cld_bu.items():
422 35d47a6c Stavros Sachtouris
                self.set(CLOUD_PREFIX, cloud, d)