~openstack-charmers-next/charms/precise/cinder/trunk

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/openstack/context.py

  • Committer: James Page
  • Date: 2016-05-27 11:25:30 UTC
  • Revision ID: james.page@ubuntu.com-20160527112530-znvvbn1p03itnvuu
Resync charm helpers

Add support for OpenStack Newton and Ocata.

Rework version detection code to just match on major version for
OpenStack projects using semantic versioning.

Provide fallback version detection based on major.minor versions
for swift packages.

Rework config-flags support helpers.

Fix is_ip function to correctly detect both IPv4 and IPv6 addresses.

Change-Id: Ifed0c7a742291bbc6380143be0f8b743c5b918f3

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
from subprocess import check_call, CalledProcessError
24
24
 
25
25
import six
26
 
import yaml
27
26
 
28
27
from charmhelpers.fetch import (
29
28
    apt_install,
50
49
 
51
50
from charmhelpers.core.sysctl import create as sysctl_create
52
51
from charmhelpers.core.strutils import bool_from_string
 
52
from charmhelpers.contrib.openstack.exceptions import OSContextError
53
53
 
54
54
from charmhelpers.core.host import (
55
55
    get_bond_master,
88
88
    is_address_in_network,
89
89
    is_bridge_member,
90
90
)
91
 
from charmhelpers.contrib.openstack.utils import get_host_ip
 
91
from charmhelpers.contrib.openstack.utils import (
 
92
    config_flags_parser,
 
93
    get_host_ip,
 
94
)
92
95
from charmhelpers.core.unitdata import kv
93
96
 
94
97
try:
101
104
ADDRESS_TYPES = ['admin', 'internal', 'public']
102
105
 
103
106
 
104
 
class OSContextError(Exception):
105
 
    pass
106
 
 
107
 
 
108
107
def ensure_packages(packages):
109
108
    """Install but do not upgrade required plugin packages."""
110
109
    required = filter_installed_packages(packages)
125
124
    return True
126
125
 
127
126
 
128
 
def config_flags_parser(config_flags):
129
 
    """Parses config flags string into dict.
130
 
 
131
 
    This parsing method supports a few different formats for the config
132
 
    flag values to be parsed:
133
 
 
134
 
      1. A string in the simple format of key=value pairs, with the possibility
135
 
         of specifying multiple key value pairs within the same string. For
136
 
         example, a string in the format of 'key1=value1, key2=value2' will
137
 
         return a dict of:
138
 
 
139
 
             {'key1': 'value1',
140
 
              'key2': 'value2'}.
141
 
 
142
 
      2. A string in the above format, but supporting a comma-delimited list
143
 
         of values for the same key. For example, a string in the format of
144
 
         'key1=value1, key2=value3,value4,value5' will return a dict of:
145
 
 
146
 
             {'key1', 'value1',
147
 
              'key2', 'value2,value3,value4'}
148
 
 
149
 
      3. A string containing a colon character (:) prior to an equal
150
 
         character (=) will be treated as yaml and parsed as such. This can be
151
 
         used to specify more complex key value pairs. For example,
152
 
         a string in the format of 'key1: subkey1=value1, subkey2=value2' will
153
 
         return a dict of:
154
 
 
155
 
             {'key1', 'subkey1=value1, subkey2=value2'}
156
 
 
157
 
    The provided config_flags string may be a list of comma-separated values
158
 
    which themselves may be comma-separated list of values.
159
 
    """
160
 
    # If we find a colon before an equals sign then treat it as yaml.
161
 
    # Note: limit it to finding the colon first since this indicates assignment
162
 
    # for inline yaml.
163
 
    colon = config_flags.find(':')
164
 
    equals = config_flags.find('=')
165
 
    if colon > 0:
166
 
        if colon < equals or equals < 0:
167
 
            return yaml.safe_load(config_flags)
168
 
 
169
 
    if config_flags.find('==') >= 0:
170
 
        log("config_flags is not in expected format (key=value)", level=ERROR)
171
 
        raise OSContextError
172
 
 
173
 
    # strip the following from each value.
174
 
    post_strippers = ' ,'
175
 
    # we strip any leading/trailing '=' or ' ' from the string then
176
 
    # split on '='.
177
 
    split = config_flags.strip(' =').split('=')
178
 
    limit = len(split)
179
 
    flags = {}
180
 
    for i in range(0, limit - 1):
181
 
        current = split[i]
182
 
        next = split[i + 1]
183
 
        vindex = next.rfind(',')
184
 
        if (i == limit - 2) or (vindex < 0):
185
 
            value = next
186
 
        else:
187
 
            value = next[:vindex]
188
 
 
189
 
        if i == 0:
190
 
            key = current
191
 
        else:
192
 
            # if this not the first entry, expect an embedded key.
193
 
            index = current.rfind(',')
194
 
            if index < 0:
195
 
                log("Invalid config value(s) at index %s" % (i), level=ERROR)
196
 
                raise OSContextError
197
 
            key = current[index + 1:]
198
 
 
199
 
        # Add to collection.
200
 
        flags[key.strip(post_strippers)] = value.rstrip(post_strippers)
201
 
 
202
 
    return flags
203
 
 
204
 
 
205
127
class OSContextGenerator(object):
206
128
    """Base class for all context generators."""
207
129
    interfaces = []