Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / config.py @ 201baa17

History | View | Annotate | Download (5.2 kB)

1
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
import os
35

    
36
from collections import defaultdict
37
from ConfigParser import RawConfigParser, NoOptionError, NoSectionError
38

    
39
try:
40
    from collections import OrderedDict
41
except ImportError:
42
    from kamaki.clients.utils.ordereddict import OrderedDict
43

    
44

    
45
# Path to the file that stores the configuration
46
CONFIG_PATH = os.path.expanduser('~/.kamakirc')
47
HISTORY_PATH = os.path.expanduser('~/.kamaki.history')
48

    
49
# Name of a shell variable to bypass the CONFIG_PATH value
50
CONFIG_ENV = 'KAMAKI_CONFIG'
51

    
52
HEADER = """
53
# Kamaki configuration file v3 (kamaki >= v0.9)
54
"""
55

    
56
DEFAULTS = {
57
    'global': {
58
        'colors': 'off',
59
        'log_file': os.path.expanduser('~/.kamaki.log'),
60
        'log_token': 'off',
61
        'log_data': 'off',
62
        'max_threads': 7,
63
        'history_file': HISTORY_PATH
64
    },
65
    'cli': {
66
        'user': 'astakos',
67
        'file': 'pithos',
68
        'server': 'cyclades',
69
        'flavor': 'cyclades',
70
        'network': 'cyclades',
71
        'image': 'image',
72
        'config': 'config',
73
        'history': 'history'
74
        #  Optional command specs:
75
        #  'livetest': 'livetest',
76
        #  'astakos': 'snf-astakos'
77
    },
78
    'remote0': {
79
        'remote_url': '',
80
        'remote_token': ''
81
        #'pithos_type': 'object-store',
82
        #'pithos_version': 'v1',
83
        #'cyclades_type': 'compute',
84
        #'cyclades_version': 'v2.0',
85
        #'image_type': 'image',
86
        #'image_version': '',
87
        #'astakos_type': 'identity',
88
        #'astakos_version': 'v2.0'
89
    }
90
}
91

    
92

    
93
class Config(RawConfigParser):
94
    def __init__(self, path=None):
95
        RawConfigParser.__init__(self, dict_type=OrderedDict)
96
        self.path = path or os.environ.get(CONFIG_ENV, CONFIG_PATH)
97
        self._overrides = defaultdict(dict)
98
        self._load_defaults()
99
        self.read(self.path)
100

    
101
    def _load_defaults(self):
102
        for section, options in DEFAULTS.items():
103
            for option, val in options.items():
104
                self.set(section, option, val)
105

    
106
    def _get_dict(self, section, include_defaults=True):
107
        try:
108
            d = dict(DEFAULTS[section]) if include_defaults else {}
109
        except KeyError:
110
            d = {}
111
        try:
112
            d.update(RawConfigParser.items(self, section))
113
        except NoSectionError:
114
            pass
115
        return d
116

    
117
    def reload(self):
118
        self = self.__init__(self.path)
119

    
120
    def get(self, section, option):
121
        value = self._overrides.get(section, {}).get(option)
122
        if value is not None:
123
            return value
124

    
125
        try:
126
            return RawConfigParser.get(self, section, option)
127
        except (NoSectionError, NoOptionError):
128
            return DEFAULTS.get(section, {}).get(option)
129

    
130
    def set(self, section, option, value):
131
        if section not in RawConfigParser.sections(self):
132
            self.add_section(section)
133
        RawConfigParser.set(self, section, option, value)
134

    
135
    def remove_option(self, section, option, also_remove_default=False):
136
        try:
137
            if also_remove_default:
138
                DEFAULTS[section].pop(option)
139
            RawConfigParser.remove_option(self, section, option)
140
        except NoSectionError:
141
            pass
142

    
143
    def keys(self, section, include_defaults=True):
144
        d = self._get_dict(section, include_defaults)
145
        return d.keys()
146

    
147
    def items(self, section, include_defaults=True):
148
        d = self._get_dict(section, include_defaults)
149
        return d.items()
150

    
151
    def override(self, section, option, value):
152
        self._overrides[section][option] = value
153

    
154
    def write(self):
155
        with open(self.path, 'w') as f:
156
            os.chmod(self.path, 0600)
157
            f.write(HEADER.lstrip())
158
            f.flush()
159
            RawConfigParser.write(self, f)