Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / config / __init__.py @ ab154b94

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

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

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

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

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

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

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

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