82
84
from charmhelpers.fetch import apt_install, apt_cache, install_remote
83
85
from charmhelpers.contrib.storage.linux.utils import is_block_device, zap_disk
84
86
from charmhelpers.contrib.storage.linux.loopback import ensure_loopback_device
87
from charmhelpers.contrib.openstack.exceptions import OSContextError
86
89
CLOUD_ARCHIVE_URL = "http://ubuntu-cloud.archive.canonical.com/ubuntu"
87
90
CLOUD_ARCHIVE_KEY_ID = '5EDB1B62EC4926EA'
138
145
['2.3.0', '2.4.0', '2.5.0']),
140
147
['2.5.0', '2.6.0', '2.7.0']),
143
152
# >= Liberty version->codename mapping
144
153
PACKAGE_CODENAMES = {
145
154
'nova-common': OrderedDict([
149
160
'neutron-common': OrderedDict([
154
166
'cinder-common': OrderedDict([
158
172
'keystone': OrderedDict([
163
178
'horizon-common': OrderedDict([
167
184
'ceilometer-common': OrderedDict([
171
190
'heat-common': OrderedDict([
175
196
'glance-common': OrderedDict([
179
202
'openstack-dashboard': OrderedDict([
254
279
def get_swift_codename(version):
255
280
'''Determine OpenStack codename that corresponds to swift version.'''
256
281
codenames = [k for k, v in six.iteritems(SWIFT_CODENAMES) if version in v]
257
283
if len(codenames) > 1:
258
284
# If more than one release codename contains this version we determine
259
285
# the actual codename based on the highest available install source.
266
292
elif len(codenames) == 1:
267
293
return codenames[0]
295
# NOTE: fallback - attempt to match with just major.minor version
296
match = re.match('^(\d+)\.(\d+)', version)
298
major_minor_version = match.group(0)
299
for codename, versions in six.iteritems(SWIFT_CODENAMES):
300
for release_version in versions:
301
if release_version.startswith(major_minor_version):
304
340
vers = match.group(0)
342
# Generate a major version number for newer semantic
343
# versions of openstack projects
344
major_vers = vers.split('.')[0]
306
345
# >= Liberty independent project versions
307
346
if (package in PACKAGE_CODENAMES and
308
vers in PACKAGE_CODENAMES[package]):
309
return PACKAGE_CODENAMES[package][vers]
347
major_vers in PACKAGE_CODENAMES[package]):
348
return PACKAGE_CODENAMES[package][major_vers]
311
350
# < Liberty co-ordinated project versions
466
505
'mitaka': 'trusty-updates/mitaka',
467
506
'mitaka/updates': 'trusty-updates/mitaka',
468
507
'mitaka/proposed': 'trusty-proposed/mitaka',
508
'newton': 'xenial-updates/newton',
509
'newton/updates': 'xenial-updates/newton',
510
'newton/proposed': 'xenial-proposed/newton',
903
def git_generate_systemd_init_files(templates_dir):
905
Generate systemd init files.
907
Generates and installs systemd init units and script files based on the
908
*.init.in files contained in the templates_dir directory.
910
This code is based on the openstack-pkg-tools package and its init
911
script generation, which is used by the OpenStack packages.
913
for f in os.listdir(templates_dir):
914
if f.endswith(".init.in"):
917
service_file = "{}.service".format(init_file)
919
init_in_source = os.path.join(templates_dir, init_in_file)
920
init_source = os.path.join(templates_dir, init_file)
921
service_source = os.path.join(templates_dir, service_file)
923
init_dest = os.path.join('/etc/init.d', init_file)
924
service_dest = os.path.join('/lib/systemd/system', service_file)
926
shutil.copyfile(init_in_source, init_source)
927
with open(init_source, 'a') as outfile:
928
template = '/usr/share/openstack-pkg-tools/init-script-template'
929
with open(template) as infile:
930
outfile.write('\n\n{}'.format(infile.read()))
932
cmd = ['pkgos-gen-systemd-unit', init_in_source]
933
subprocess.check_call(cmd)
935
if os.path.exists(init_dest):
937
if os.path.exists(service_dest):
938
os.remove(service_dest)
939
shutil.move(init_source, init_dest)
940
shutil.move(service_source, service_dest)
941
os.chmod(init_dest, 0o755)
861
944
def os_workload_status(configs, required_interfaces, charm_func=None):
863
946
Decorator to set workload status based on complete contexts
1574
1657
restart_functions)
1575
1658
return wrapped_f
1662
def config_flags_parser(config_flags):
1663
"""Parses config flags string into dict.
1665
This parsing method supports a few different formats for the config
1666
flag values to be parsed:
1668
1. A string in the simple format of key=value pairs, with the possibility
1669
of specifying multiple key value pairs within the same string. For
1670
example, a string in the format of 'key1=value1, key2=value2' will
1676
2. A string in the above format, but supporting a comma-delimited list
1677
of values for the same key. For example, a string in the format of
1678
'key1=value1, key2=value3,value4,value5' will return a dict of:
1681
'key2', 'value2,value3,value4'}
1683
3. A string containing a colon character (:) prior to an equal
1684
character (=) will be treated as yaml and parsed as such. This can be
1685
used to specify more complex key value pairs. For example,
1686
a string in the format of 'key1: subkey1=value1, subkey2=value2' will
1689
{'key1', 'subkey1=value1, subkey2=value2'}
1691
The provided config_flags string may be a list of comma-separated values
1692
which themselves may be comma-separated list of values.
1694
# If we find a colon before an equals sign then treat it as yaml.
1695
# Note: limit it to finding the colon first since this indicates assignment
1697
colon = config_flags.find(':')
1698
equals = config_flags.find('=')
1700
if colon < equals or equals < 0:
1701
return yaml.safe_load(config_flags)
1703
if config_flags.find('==') >= 0:
1704
juju_log("config_flags is not in expected format (key=value)",
1706
raise OSContextError
1708
# strip the following from each value.
1709
post_strippers = ' ,'
1710
# we strip any leading/trailing '=' or ' ' from the string then
1712
split = config_flags.strip(' =').split('=')
1715
for i in range(0, limit - 1):
1718
vindex = next.rfind(',')
1719
if (i == limit - 2) or (vindex < 0):
1722
value = next[:vindex]
1727
# if this not the first entry, expect an embedded key.
1728
index = current.rfind(',')
1730
juju_log("Invalid config value(s) at index %s" % (i),
1732
raise OSContextError
1733
key = current[index + 1:]
1735
# Add to collection.
1736
flags[key.strip(post_strippers)] = value.rstrip(post_strippers)