Update charmhelpers sync to include smarter write_file()

This patchset is a speculative merge to demonstrate that the
charm-helpers change (clean-up-render) has no unexpected side-effects.

Change-Id: Ifa42d9dade761e9b86e4a51ffffe355e933ffade
This commit is contained in:
Alex Kavanagh 2017-08-11 12:25:18 +01:00
parent aac009bb87
commit 6f757a4cbe
5 changed files with 81 additions and 38 deletions

View File

@ -41,9 +41,9 @@ from charmhelpers.core.hookenv import (
charm_name,
DEBUG,
INFO,
WARNING,
ERROR,
status_set,
network_get_primary_address
)
from charmhelpers.core.sysctl import create as sysctl_create
@ -80,6 +80,9 @@ from charmhelpers.contrib.openstack.neutron import (
from charmhelpers.contrib.openstack.ip import (
resolve_address,
INTERNAL,
ADMIN,
PUBLIC,
ADDRESS_MAP,
)
from charmhelpers.contrib.network.ip import (
get_address_in_network,
@ -87,7 +90,6 @@ from charmhelpers.contrib.network.ip import (
get_ipv6_addr,
get_netmask_for_address,
format_ipv6_addr,
is_address_in_network,
is_bridge_member,
is_ipv6_disabled,
)
@ -736,11 +738,17 @@ class ApacheSSLContext(OSContextGenerator):
return sorted(list(set(cns)))
def get_network_addresses(self):
"""For each network configured, return corresponding address and vip
(if available).
"""For each network configured, return corresponding address and
hostnamr or vip (if available).
Returns a list of tuples of the form:
[(address_in_net_a, hostname_in_net_a),
(address_in_net_b, hostname_in_net_b),
...]
or, if no hostnames(s) available:
[(address_in_net_a, vip_in_net_a),
(address_in_net_b, vip_in_net_b),
...]
@ -752,32 +760,27 @@ class ApacheSSLContext(OSContextGenerator):
...]
"""
addresses = []
if config('vip'):
vips = config('vip').split()
else:
vips = []
for net_type in ['os-internal-network', 'os-admin-network',
'os-public-network']:
addr = get_address_in_network(config(net_type),
unit_get('private-address'))
if len(vips) > 1 and is_clustered():
if not config(net_type):
log("Multiple networks configured but net_type "
"is None (%s)." % net_type, level=WARNING)
continue
for vip in vips:
if is_address_in_network(config(net_type), vip):
addresses.append((addr, vip))
break
elif is_clustered() and config('vip'):
addresses.append((addr, config('vip')))
for net_type in [INTERNAL, ADMIN, PUBLIC]:
net_config = config(ADDRESS_MAP[net_type]['config'])
# NOTE(jamespage): Fallback must always be private address
# as this is used to bind services on the
# local unit.
fallback = unit_get("private-address")
if net_config:
addr = get_address_in_network(net_config,
fallback)
else:
addresses.append((addr, addr))
try:
addr = network_get_primary_address(
ADDRESS_MAP[net_type]['binding']
)
except NotImplementedError:
addr = fallback
return sorted(addresses)
endpoint = resolve_address(net_type)
addresses.append((addr, endpoint))
return sorted(set(addresses))
def __call__(self):
if isinstance(self.external_ports, six.string_types):
@ -804,7 +807,7 @@ class ApacheSSLContext(OSContextGenerator):
self.configure_cert(cn)
addresses = self.get_network_addresses()
for address, endpoint in sorted(set(addresses)):
for address, endpoint in addresses:
for api_port in self.external_ports:
ext_port = determine_apache_port(api_port,
singlenode_mode=True)
@ -1419,14 +1422,26 @@ class NeutronAPIContext(OSContextGenerator):
'rel_key': 'report-interval',
'default': 30,
},
'enable_qos': {
'rel_key': 'enable-qos',
'default': False,
},
}
ctxt = self.get_neutron_options({})
for rid in relation_ids('neutron-plugin-api'):
for unit in related_units(rid):
rdata = relation_get(rid=rid, unit=unit)
# The l2-population key is used by the context as a way of
# checking if the api service on the other end is sending data
# in a recent format.
if 'l2-population' in rdata:
ctxt.update(self.get_neutron_options(rdata))
if ctxt['enable_qos']:
ctxt['extension_drivers'] = 'qos'
else:
ctxt['extension_drivers'] = ''
return ctxt
def get_neutron_options(self, rdata):

View File

@ -20,7 +20,8 @@ from charmhelpers.fetch import apt_install, apt_update
from charmhelpers.core.hookenv import (
log,
ERROR,
INFO
INFO,
TRACE
)
from charmhelpers.contrib.openstack.utils import OPENSTACK_CODENAMES
@ -80,8 +81,10 @@ def get_loader(templates_dir, os_release):
loaders.insert(0, FileSystemLoader(tmpl_dir))
if rel == os_release:
break
# demote this log to the lowest level; we don't really need to see these
# lots in production even when debugging.
log('Creating choice loader with dirs: %s' %
[l.searchpath for l in loaders], level=INFO)
[l.searchpath for l in loaders], level=TRACE)
return ChoiceLoader(loaders)

View File

@ -186,7 +186,7 @@ SWIFT_CODENAMES = OrderedDict([
('ocata',
['2.11.0', '2.12.0', '2.13.0']),
('pike',
['2.13.0']),
['2.13.0', '2.15.0']),
])
# >= Liberty version->codename mapping

View File

@ -43,6 +43,7 @@ ERROR = "ERROR"
WARNING = "WARNING"
INFO = "INFO"
DEBUG = "DEBUG"
TRACE = "TRACE"
MARKER = object()
cache = {}

View File

@ -34,7 +34,7 @@ import six
from contextlib import contextmanager
from collections import OrderedDict
from .hookenv import log
from .hookenv import log, DEBUG
from .fstab import Fstab
from charmhelpers.osplatform import get_platform
@ -487,13 +487,37 @@ def mkdir(path, owner='root', group='root', perms=0o555, force=False):
def write_file(path, content, owner='root', group='root', perms=0o444):
"""Create or overwrite a file with the contents of a byte string."""
log("Writing file {} {}:{} {:o}".format(path, owner, group, perms))
uid = pwd.getpwnam(owner).pw_uid
gid = grp.getgrnam(group).gr_gid
with open(path, 'wb') as target:
os.fchown(target.fileno(), uid, gid)
os.fchmod(target.fileno(), perms)
target.write(content)
# lets see if we can grab the file and compare the context, to avoid doing
# a write.
existing_content = None
existing_uid, existing_gid = None, None
try:
with open(path, 'rb') as target:
existing_content = target.read()
stat = os.stat(path)
existing_uid, existing_gid = stat.st_uid, stat.st_gid
except:
pass
if content != existing_content:
log("Writing file {} {}:{} {:o}".format(path, owner, group, perms),
level=DEBUG)
with open(path, 'wb') as target:
os.fchown(target.fileno(), uid, gid)
os.fchmod(target.fileno(), perms)
target.write(content)
return
# the contents were the same, but we might still need to change the
# ownership.
if existing_uid != uid:
log("Changing uid on already existing content: {} -> {}"
.format(existing_uid, uid), level=DEBUG)
os.chown(path, uid, -1)
if existing_gid != gid:
log("Changing gid on already existing content: {} -> {}"
.format(existing_gid, gid), level=DEBUG)
os.chown(path, -1, gid)
def fstab_remove(mp):