Revision ce9ccb40

b/kamaki/cli/__init__.py
192 192
    kloger = logger.get_logger(__name__)
193 193

  
194 194

  
195
def _check_config_version(cnf):
196
    guess = cnf.guess_version()
197
    if guess < 3.0:
198
        print('Configuration file "%s" is not updated to v3.0' % (
199
            cnf.path))
200
        print('Calculating changes while preserving information ...')
201
        lost_terms = cnf.rescue_old_file()
202
        if lost_terms:
203
            print 'The following information will not be preserved:'
204
            print '...', '\n... '.join(lost_terms)
205
        print('... DONE')
206
        print('Kamaki is ready to transform config file to version 3.0')
207
        stdout.write('Overwrite file %s ? [Y, y] ' % cnf.path)
208
        from sys import stdin
209
        reply = stdin.readline()
210
        if reply in ('Y\n', 'y\n'):
211
            cnf.write()
212
            print('... DONE')
213
        else:
214
            print('... ABORTING')
215
            raise CLIError(
216
                'Invalid format for config file %s' % cnf.path,
217
                importance=3, details=['Please, update config file to v3.0'])
218

  
219

  
195 220
def _init_session(arguments):
196 221
    global _help
197 222
    _help = arguments['help'].value
......
202 227
    global _verbose
203 228
    _verbose = arguments['verbose'].value
204 229
    _cnf = arguments['config']
205

  
206
    guess = _cnf.value.guess_version()
207
    if guess < 3.0:
208
        print('Missing an updated configuration file')
209
        print('Updating configuration file without missing any information')
210
        #_cnf.value.rescue_old_file()
211
        print('... ... ... DONE')
212
        raise CLIError(
213
            'Invalid configuration file %s' % _cnf.value.path,
214
            importance=2, details=[
215
                'Kamaki is now using a single authentication URL and token',
216
                'To check if the single authentication URL is set:',
217
                '  /config get remote.default.token',
218
                'To check if the single authentication token is set:',
219
                '  /config get remote.default.token',
220
                'To set the default authentication URL and token:'
221
                '  /config set remote.default.url <URL>',
222
                '  /config set remote.default.token <token>'])
230
    _check_config_version(_cnf.value)
223 231
    raise CLIError(
224
        'Your file is OK, but kamaki is under contruction, sorry',
232
        'Your file is OK, but i am not ready to proceed',
225 233
        importance=3, details=['DO NOT PANIC, EXIT THE BUILDING QUIETLY'])
226 234

  
227 235
    global _colors
b/kamaki/cli/config.py
38 38
from ConfigParser import RawConfigParser, NoOptionError, NoSectionError
39 39
from re import match
40 40

  
41
from kamaki.cli.errors import CLISyntaxError
42

  
41 43
try:
42 44
    from collections import OrderedDict
43 45
except ImportError:
......
74 76
        'config_cli': 'config',
75 77
        'history_cli': 'history'
76 78
        #  Optional command specs:
77
        #  'livetest': 'livetest',
78
        #  'astakos': 'snf-astakos'
79
        #  'livetest_cli': 'livetest',
80
        #  'astakos_cli': 'snf-astakos'
79 81
    },
80 82
    'remotes':
81 83
    {
......
104 106
            self._load_defaults()
105 107
        self.read(self.path)
106 108

  
107
        assert False, 'Config.__init__: translate remotes to dict first'
109
        for section in self.sections():
110
            r = self._remote_name(section)
111
            if r:
112
                for k, v in self.items(section):
113
                    self.set_remote(r, k, v)
114
                self.remove_section(section)
108 115

  
109 116
    @staticmethod
110 117
    def _remote_name(full_section_name):
......
112 119
        return matcher.groups()[0] if matcher else None
113 120

  
114 121
    def rescue_old_file(self):
115
        pass
116
        # global.url, global.token --> remote.default.url, remote.default.token
117
        # remove global.url, global.token
118
        # translation for <service> or <command> settings
119
        # <service> or <command group> settings --> translation --> global
122
        lost_terms = []
123
        global_terms = DEFAULTS['global'].keys()
124
        translations = dict(
125
            config=dict(serv='', cmd='config'),
126
            history=dict(serv='', cmd='history'),
127
            pithos=dict(serv='pithos', cmd='file'),
128
            file=dict(serv='pithos', cmd='file'),
129
            store=dict(serv='pithos', cmd='file'),
130
            storage=dict(serv='pithos', cmd='file'),
131
            image=dict(serv='plankton', cmd='image'),
132
            plankton=dict(serv='plankton', cmd='image'),
133
            compute=dict(serv='compute', cmd=''),
134
            cyclades=dict(serv='compute', cmd='server'),
135
            server=dict(serv='compute', cmd='server'),
136
            flavor=dict(serv='compute', cmd='flavor'),
137
            network=dict(serv='compute', cmd='network'),
138
            astakos=dict(serv='astakos', cmd='user'),
139
            user=dict(serv='astakos', cmd='user'),
140
        )
141

  
142
        for s in self.sections():
143
            if s in ('global'):
144
                # global.url, global.token -->
145
                # remote.default.url, remote.default.token
146
                for term in set(self.keys(s)).difference(global_terms):
147
                    if term not in ('url', 'token'):
148
                        lost_terms.append('%s.%s = %s' % (
149
                            s, term, self.get(s, term)))
150
                        self.remove_option(s, term)
151
                        continue
152
                    gval = self.get(s, term)
153
                    cval = self.get_remote('default', term)
154
                    if gval and cval and (
155
                        gval.lower().strip('/') != cval.lower().strip('/')):
156
                            raise CLISyntaxError(
157
                                'Conflicting values for default %s' % term,
158
                                importance=2, details=[
159
                                    ' global.%s:  %s' % (term, gval),
160
                                    ' remote.default.%s:  %s' % (term, cval),
161
                                    'Please remove one of them manually:',
162
                                    ' /config delete global.%s' % term,
163
                                    ' or'
164
                                    ' /config delete remote.default.%s' % term,
165
                                    'and try again'])
166
                    elif gval:
167
                        print('... rescue %s.%s => remote.default.%s' % (
168
                            s, term, term))
169
                        self.set_remote('default', term, gval)
170
                    self.remove_option(s, term)
171
            # translation for <service> or <command> settings
172
            # <service> or <command group> settings --> translation --> global
173
            elif s in translations:
174

  
175
                if s in ('history',):
176
                    k = 'file'
177
                    v = self.get(s, k)
178
                    if v:
179
                        print('... rescue %s.%s => global.%s_%s' % (
180
                            s, k, s, k))
181
                        self.set('global', '%s_%s' % (s, k), v)
182
                        self.remove_option(s, k)
183

  
184
                trn = translations[s]
185
                for k, v in self.items(s, False):
186
                    if v and k in ('cli',):
187
                        print('... rescue %s.%s => global.%s_cli' % (
188
                            s, k, trn['cmd']))
189
                        self.set('global', 'file_cli', v)
190
                    elif v and k in ('url', 'token'):
191
                        print(
192
                            '... rescue %s.%s => remote.default.%s_%s' % (
193
                                s, k, trn['serv'], k))
194
                        self.set_remote('default', 'pithos_%s' % k, v)
195
                    elif v:
196
                        lost_terms.append('%s.%s = %s' % (s, k, v))
197
                self.remove_section(s)
198
        #  self.pretty_print()
199
        return lost_terms
200

  
201
    def pretty_print(self):
202
        for s in self.sections():
203
            print s
204
            for k, v in self.items(s):
205
                if isinstance(v, dict):
206
                    print '\t', k, '=> {'
207
                    for ki, vi in v.items():
208
                        print '\t\t', ki, '=>', vi
209
                    print('\t}')
210
                else:
211
                    print '\t', k, '=>', v
120 212

  
121 213
    def guess_version(self):
122 214
        checker = Config(self.path, with_defaults=False)
......
128 220
                return 2.0
129 221
        log.warning('........ nope')
130 222
        log.warning('Config file heuristic 2: at least 1 remote section ?')
131
        for section in sections:
132
            if self._remote_name(section):
133
                log.warning('... found %s section' % section)
223
        if 'remotes' in sections:
224
            for r in self.keys('remotes'):
225
                log.warning('... found remote "%s"' % r)
134 226
                return 3.0
135 227
        log.warning('........ nope')
136 228
        log.warning('All heuristics failed, cannot decide')
137 229
        return 0.0
138 230

  
231
    def get_remote(self, remote, option):
232
        """
233
        :param remote: (str) remote cloud alias
234

  
235
        :param option: (str) option in remote cloud section
236

  
237
        :returns: (str) the value assigned on this option
238

  
239
        :raises KeyError: if remote or remote's option does not exist
240
        """
241
        r = self.get('remotes', remote)
242
        if not r:
243
            raise KeyError('Remote "%s" does not exist' % remote)
244
        return r[option]
245

  
246
    def set_remote(self, remote, option, value):
247
        try:
248
            d = self.get('remotes', remote)
249
        except KeyError:
250
            pass
251
        d[option] = value
252
        self.set('remotes', remote, d)
253

  
139 254
    def _load_defaults(self):
140 255
        for section, options in DEFAULTS.items():
141 256
            for option, val in options.items():
......
190 305
        self._overrides[section][option] = value
191 306

  
192 307
    def write(self):
308
        for r, d in self.items('remotes'):
309
            for k, v in d.items():
310
                self.set('remote "%s"' % r, k, v)
311
        self.remove_section('remotes')
312

  
193 313
        with open(self.path, 'w') as f:
194 314
            os.chmod(self.path, 0600)
195 315
            f.write(HEADER.lstrip())
196 316
            f.flush()
197
            assert False, 'Config.write: Trasnlate remotes to file first'
198 317
            RawConfigParser.write(self, f)

Also available in: Unified diff