Sync charm-helpers
Change-Id: I296f081e9de99da2fefe5a581dfc2ffe5fba4429
This commit is contained in:
parent
cd8b510f95
commit
4c5204ee19
|
@ -110,7 +110,12 @@ def get_address_in_network(network, fallback=None, fatal=False):
|
||||||
_validate_cidr(network)
|
_validate_cidr(network)
|
||||||
network = netaddr.IPNetwork(network)
|
network = netaddr.IPNetwork(network)
|
||||||
for iface in netifaces.interfaces():
|
for iface in netifaces.interfaces():
|
||||||
addresses = netifaces.ifaddresses(iface)
|
try:
|
||||||
|
addresses = netifaces.ifaddresses(iface)
|
||||||
|
except ValueError:
|
||||||
|
# If an instance was deleted between
|
||||||
|
# netifaces.interfaces() run and now, its interfaces are gone
|
||||||
|
continue
|
||||||
if network.version == 4 and netifaces.AF_INET in addresses:
|
if network.version == 4 and netifaces.AF_INET in addresses:
|
||||||
for addr in addresses[netifaces.AF_INET]:
|
for addr in addresses[netifaces.AF_INET]:
|
||||||
cidr = netaddr.IPNetwork("%s/%s" % (addr['addr'],
|
cidr = netaddr.IPNetwork("%s/%s" % (addr['addr'],
|
||||||
|
|
|
@ -92,7 +92,7 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||||
return 'endpoint not found'
|
return 'endpoint not found'
|
||||||
|
|
||||||
def validate_v3_endpoint_data(self, endpoints, admin_port, internal_port,
|
def validate_v3_endpoint_data(self, endpoints, admin_port, internal_port,
|
||||||
public_port, expected):
|
public_port, expected, expected_num_eps=3):
|
||||||
"""Validate keystone v3 endpoint data.
|
"""Validate keystone v3 endpoint data.
|
||||||
|
|
||||||
Validate the v3 endpoint data which has changed from v2. The
|
Validate the v3 endpoint data which has changed from v2. The
|
||||||
|
@ -138,7 +138,7 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||||
if ret:
|
if ret:
|
||||||
return 'unexpected endpoint data - {}'.format(ret)
|
return 'unexpected endpoint data - {}'.format(ret)
|
||||||
|
|
||||||
if len(found) != 3:
|
if len(found) != expected_num_eps:
|
||||||
return 'Unexpected number of endpoints found'
|
return 'Unexpected number of endpoints found'
|
||||||
|
|
||||||
def validate_svc_catalog_endpoint_data(self, expected, actual):
|
def validate_svc_catalog_endpoint_data(self, expected, actual):
|
||||||
|
|
|
@ -1637,18 +1637,84 @@ class InternalEndpointContext(OSContextGenerator):
|
||||||
endpoints by default so this allows admins to optionally use internal
|
endpoints by default so this allows admins to optionally use internal
|
||||||
endpoints.
|
endpoints.
|
||||||
"""
|
"""
|
||||||
def __init__(self, ost_rel_check_pkg_name):
|
def __call__(self):
|
||||||
self.ost_rel_check_pkg_name = ost_rel_check_pkg_name
|
return {'use_internal_endpoints': config('use-internal-endpoints')}
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeAPIContext(InternalEndpointContext):
|
||||||
|
"""Volume API context.
|
||||||
|
|
||||||
|
This context provides information regarding the volume endpoint to use
|
||||||
|
when communicating between services. It determines which version of the
|
||||||
|
API is appropriate for use.
|
||||||
|
|
||||||
|
This value will be determined in the resulting context dictionary
|
||||||
|
returned from calling the VolumeAPIContext object. Information provided
|
||||||
|
by this context is as follows:
|
||||||
|
|
||||||
|
volume_api_version: the volume api version to use, currently
|
||||||
|
'v2' or 'v3'
|
||||||
|
volume_catalog_info: the information to use for a cinder client
|
||||||
|
configuration that consumes API endpoints from the keystone
|
||||||
|
catalog. This is defined as the type:name:endpoint_type string.
|
||||||
|
"""
|
||||||
|
# FIXME(wolsen) This implementation is based on the provider being able
|
||||||
|
# to specify the package version to check but does not guarantee that the
|
||||||
|
# volume service api version selected is available. In practice, it is
|
||||||
|
# quite likely the volume service *is* providing the v3 volume service.
|
||||||
|
# This should be resolved when the service-discovery spec is implemented.
|
||||||
|
def __init__(self, pkg):
|
||||||
|
"""
|
||||||
|
Creates a new VolumeAPIContext for use in determining which version
|
||||||
|
of the Volume API should be used for communication. A package codename
|
||||||
|
should be supplied for determining the currently installed OpenStack
|
||||||
|
version.
|
||||||
|
|
||||||
|
:param pkg: the package codename to use in order to determine the
|
||||||
|
component version (e.g. nova-common). See
|
||||||
|
charmhelpers.contrib.openstack.utils.PACKAGE_CODENAMES for more.
|
||||||
|
"""
|
||||||
|
super(VolumeAPIContext, self).__init__()
|
||||||
|
self._ctxt = None
|
||||||
|
if not pkg:
|
||||||
|
raise ValueError('package name must be provided in order to '
|
||||||
|
'determine current OpenStack version.')
|
||||||
|
self.pkg = pkg
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ctxt(self):
|
||||||
|
if self._ctxt is not None:
|
||||||
|
return self._ctxt
|
||||||
|
self._ctxt = self._determine_ctxt()
|
||||||
|
return self._ctxt
|
||||||
|
|
||||||
|
def _determine_ctxt(self):
|
||||||
|
"""Determines the Volume API endpoint information.
|
||||||
|
|
||||||
|
Determines the appropriate version of the API that should be used
|
||||||
|
as well as the catalog_info string that would be supplied. Returns
|
||||||
|
a dict containing the volume_api_version and the volume_catalog_info.
|
||||||
|
"""
|
||||||
|
rel = os_release(self.pkg, base='icehouse')
|
||||||
|
version = '2'
|
||||||
|
if CompareOpenStackReleases(rel) >= 'pike':
|
||||||
|
version = '3'
|
||||||
|
|
||||||
|
service_type = 'volumev{version}'.format(version=version)
|
||||||
|
service_name = 'cinderv{version}'.format(version=version)
|
||||||
|
endpoint_type = 'publicURL'
|
||||||
|
if config('use-internal-endpoints'):
|
||||||
|
endpoint_type = 'internalURL'
|
||||||
|
catalog_info = '{type}:{name}:{endpoint}'.format(
|
||||||
|
type=service_type, name=service_name, endpoint=endpoint_type)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'volume_api_version': version,
|
||||||
|
'volume_catalog_info': catalog_info,
|
||||||
|
}
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
ctxt = {'use_internal_endpoints': config('use-internal-endpoints')}
|
return self.ctxt
|
||||||
rel = os_release(self.ost_rel_check_pkg_name, base='icehouse')
|
|
||||||
if CompareOpenStackReleases(rel) >= 'pike':
|
|
||||||
ctxt['volume_api_version'] = '3'
|
|
||||||
else:
|
|
||||||
ctxt['volume_api_version'] = '2'
|
|
||||||
|
|
||||||
return ctxt
|
|
||||||
|
|
||||||
|
|
||||||
class AppArmorContext(OSContextGenerator):
|
class AppArmorContext(OSContextGenerator):
|
||||||
|
|
|
@ -20,7 +20,8 @@ from charmhelpers.core import hookenv
|
||||||
|
|
||||||
|
|
||||||
def render(source, target, context, owner='root', group='root',
|
def render(source, target, context, owner='root', group='root',
|
||||||
perms=0o444, templates_dir=None, encoding='UTF-8', template_loader=None):
|
perms=0o444, templates_dir=None, encoding='UTF-8',
|
||||||
|
template_loader=None, config_template=None):
|
||||||
"""
|
"""
|
||||||
Render a template.
|
Render a template.
|
||||||
|
|
||||||
|
@ -32,6 +33,9 @@ def render(source, target, context, owner='root', group='root',
|
||||||
The context should be a dict containing the values to be replaced in the
|
The context should be a dict containing the values to be replaced in the
|
||||||
template.
|
template.
|
||||||
|
|
||||||
|
config_template may be provided to render from a provided template instead
|
||||||
|
of loading from a file.
|
||||||
|
|
||||||
The `owner`, `group`, and `perms` options will be passed to `write_file`.
|
The `owner`, `group`, and `perms` options will be passed to `write_file`.
|
||||||
|
|
||||||
If omitted, `templates_dir` defaults to the `templates` folder in the charm.
|
If omitted, `templates_dir` defaults to the `templates` folder in the charm.
|
||||||
|
@ -65,14 +69,19 @@ def render(source, target, context, owner='root', group='root',
|
||||||
if templates_dir is None:
|
if templates_dir is None:
|
||||||
templates_dir = os.path.join(hookenv.charm_dir(), 'templates')
|
templates_dir = os.path.join(hookenv.charm_dir(), 'templates')
|
||||||
template_env = Environment(loader=FileSystemLoader(templates_dir))
|
template_env = Environment(loader=FileSystemLoader(templates_dir))
|
||||||
try:
|
|
||||||
source = source
|
# load from a string if provided explicitly
|
||||||
template = template_env.get_template(source)
|
if config_template is not None:
|
||||||
except exceptions.TemplateNotFound as e:
|
template = template_env.from_string(config_template)
|
||||||
hookenv.log('Could not load template %s from %s.' %
|
else:
|
||||||
(source, templates_dir),
|
try:
|
||||||
level=hookenv.ERROR)
|
source = source
|
||||||
raise e
|
template = template_env.get_template(source)
|
||||||
|
except exceptions.TemplateNotFound as e:
|
||||||
|
hookenv.log('Could not load template %s from %s.' %
|
||||||
|
(source, templates_dir),
|
||||||
|
level=hookenv.ERROR)
|
||||||
|
raise e
|
||||||
content = template.render(context)
|
content = template.render(context)
|
||||||
if target is not None:
|
if target is not None:
|
||||||
target_dir = os.path.dirname(target)
|
target_dir = os.path.dirname(target)
|
||||||
|
|
|
@ -92,7 +92,7 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||||
return 'endpoint not found'
|
return 'endpoint not found'
|
||||||
|
|
||||||
def validate_v3_endpoint_data(self, endpoints, admin_port, internal_port,
|
def validate_v3_endpoint_data(self, endpoints, admin_port, internal_port,
|
||||||
public_port, expected):
|
public_port, expected, expected_num_eps=3):
|
||||||
"""Validate keystone v3 endpoint data.
|
"""Validate keystone v3 endpoint data.
|
||||||
|
|
||||||
Validate the v3 endpoint data which has changed from v2. The
|
Validate the v3 endpoint data which has changed from v2. The
|
||||||
|
@ -138,7 +138,7 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||||
if ret:
|
if ret:
|
||||||
return 'unexpected endpoint data - {}'.format(ret)
|
return 'unexpected endpoint data - {}'.format(ret)
|
||||||
|
|
||||||
if len(found) != 3:
|
if len(found) != expected_num_eps:
|
||||||
return 'Unexpected number of endpoints found'
|
return 'Unexpected number of endpoints found'
|
||||||
|
|
||||||
def validate_svc_catalog_endpoint_data(self, expected, actual):
|
def validate_svc_catalog_endpoint_data(self, expected, actual):
|
||||||
|
|
|
@ -20,7 +20,8 @@ from charmhelpers.core import hookenv
|
||||||
|
|
||||||
|
|
||||||
def render(source, target, context, owner='root', group='root',
|
def render(source, target, context, owner='root', group='root',
|
||||||
perms=0o444, templates_dir=None, encoding='UTF-8', template_loader=None):
|
perms=0o444, templates_dir=None, encoding='UTF-8',
|
||||||
|
template_loader=None, config_template=None):
|
||||||
"""
|
"""
|
||||||
Render a template.
|
Render a template.
|
||||||
|
|
||||||
|
@ -32,6 +33,9 @@ def render(source, target, context, owner='root', group='root',
|
||||||
The context should be a dict containing the values to be replaced in the
|
The context should be a dict containing the values to be replaced in the
|
||||||
template.
|
template.
|
||||||
|
|
||||||
|
config_template may be provided to render from a provided template instead
|
||||||
|
of loading from a file.
|
||||||
|
|
||||||
The `owner`, `group`, and `perms` options will be passed to `write_file`.
|
The `owner`, `group`, and `perms` options will be passed to `write_file`.
|
||||||
|
|
||||||
If omitted, `templates_dir` defaults to the `templates` folder in the charm.
|
If omitted, `templates_dir` defaults to the `templates` folder in the charm.
|
||||||
|
@ -65,14 +69,19 @@ def render(source, target, context, owner='root', group='root',
|
||||||
if templates_dir is None:
|
if templates_dir is None:
|
||||||
templates_dir = os.path.join(hookenv.charm_dir(), 'templates')
|
templates_dir = os.path.join(hookenv.charm_dir(), 'templates')
|
||||||
template_env = Environment(loader=FileSystemLoader(templates_dir))
|
template_env = Environment(loader=FileSystemLoader(templates_dir))
|
||||||
try:
|
|
||||||
source = source
|
# load from a string if provided explicitly
|
||||||
template = template_env.get_template(source)
|
if config_template is not None:
|
||||||
except exceptions.TemplateNotFound as e:
|
template = template_env.from_string(config_template)
|
||||||
hookenv.log('Could not load template %s from %s.' %
|
else:
|
||||||
(source, templates_dir),
|
try:
|
||||||
level=hookenv.ERROR)
|
source = source
|
||||||
raise e
|
template = template_env.get_template(source)
|
||||||
|
except exceptions.TemplateNotFound as e:
|
||||||
|
hookenv.log('Could not load template %s from %s.' %
|
||||||
|
(source, templates_dir),
|
||||||
|
level=hookenv.ERROR)
|
||||||
|
raise e
|
||||||
content = template.render(context)
|
content = template.render(context)
|
||||||
if target is not None:
|
if target is not None:
|
||||||
target_dir = os.path.dirname(target)
|
target_dir = os.path.dirname(target)
|
||||||
|
|
2
tox.ini
2
tox.ini
|
@ -9,7 +9,7 @@ skipsdist = True
|
||||||
setenv = VIRTUAL_ENV={envdir}
|
setenv = VIRTUAL_ENV={envdir}
|
||||||
PYTHONHASHSEED=0
|
PYTHONHASHSEED=0
|
||||||
CHARM_DIR={envdir}
|
CHARM_DIR={envdir}
|
||||||
AMULET_SETUP_TIMEOUT=2700
|
AMULET_SETUP_TIMEOUT=5400
|
||||||
install_command =
|
install_command =
|
||||||
pip install --allow-unverified python-apt {opts} {packages}
|
pip install --allow-unverified python-apt {opts} {packages}
|
||||||
commands = ostestr {posargs}
|
commands = ostestr {posargs}
|
||||||
|
|
Loading…
Reference in New Issue