Remove deploy from source support

Drop support for deployment from Git repositories, as deprecated
in the 17.02 charm release.  This feature is unmaintained and has
no known users.

Change-Id: Ic054e29ef55d8890a3130af16b48f105efcf8f6a
This commit is contained in:
James Page 2017-12-21 14:32:21 +00:00
parent e1ac46f342
commit e8f1fdd8a1
18 changed files with 147 additions and 1247 deletions

View File

@ -1,5 +1,3 @@
git-reinstall:
description: Reinstall keystone from the openstack-origin-git repositories.
pause:
description: |
Pause keystone services.

View File

@ -1 +0,0 @@
git_reinstall.py

View File

@ -1,57 +0,0 @@
#!/usr/bin/python
#
# Copyright 2016 Canonical Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import traceback
from charmhelpers.contrib.openstack.utils import (
git_install_requested,
)
from charmhelpers.core.hookenv import (
action_set,
action_fail,
config,
)
from hooks.keystone_utils import (
git_install,
)
from hooks.keystone_hooks import (
config_changed,
)
def git_reinstall():
"""Reinstall from source and restart services.
If the openstack-origin-git config option was used to install openstack
from source git repositories, then this action can be used to reinstall
from updated git repositories, followed by a restart of services."""
if not git_install_requested():
action_fail('openstack-origin-git is not configured')
return
try:
git_install(config('openstack-origin-git'))
config_changed()
except:
action_set({'traceback': traceback.format_exc()})
action_fail('git-reinstall resulted in an unexpected error')
if __name__ == '__main__':
git_reinstall()

View File

@ -97,8 +97,6 @@ from charmhelpers.contrib.network.ip import (
from charmhelpers.contrib.openstack.utils import (
config_flags_parser,
get_host_ip,
git_determine_usr_bin,
git_determine_python_path,
enable_memcache,
snap_install_requested,
CompareOpenStackReleases,
@ -334,10 +332,7 @@ class IdentityServiceContext(OSContextGenerator):
self.rel_name = rel_name
self.interfaces = [self.rel_name]
def __call__(self):
log('Generating template context for ' + self.rel_name, level=DEBUG)
ctxt = {}
def _setup_pki_cache(self):
if self.service and self.service_user:
# This is required for pki token signing if we don't want /tmp to
# be used.
@ -347,6 +342,15 @@ class IdentityServiceContext(OSContextGenerator):
mkdir(path=cachedir, owner=self.service_user,
group=self.service_user, perms=0o700)
return cachedir
return None
def __call__(self):
log('Generating template context for ' + self.rel_name, level=DEBUG)
ctxt = {}
cachedir = self._setup_pki_cache()
if cachedir:
ctxt['signing_dir'] = cachedir
for rid in relation_ids(self.rel_name):
@ -385,6 +389,62 @@ class IdentityServiceContext(OSContextGenerator):
return {}
class IdentityCredentialsContext(IdentityServiceContext):
'''Context for identity-credentials interface type'''
def __init__(self,
service=None,
service_user=None,
rel_name='identity-credentials'):
super(IdentityCredentialsContext, self).__init__(service,
service_user,
rel_name)
def __call__(self):
log('Generating template context for ' + self.rel_name, level=DEBUG)
ctxt = {}
cachedir = self._setup_pki_cache()
if cachedir:
ctxt['signing_dir'] = cachedir
for rid in relation_ids(self.rel_name):
self.related = True
for unit in related_units(rid):
rdata = relation_get(rid=rid, unit=unit)
credentials_host = rdata.get('credentials_host')
credentials_host = (
format_ipv6_addr(credentials_host) or credentials_host
)
auth_host = rdata.get('auth_host')
auth_host = format_ipv6_addr(auth_host) or auth_host
svc_protocol = rdata.get('credentials_protocol') or 'http'
auth_protocol = rdata.get('auth_protocol') or 'http'
api_version = rdata.get('api_version') or '2.0'
ctxt.update({
'service_port': rdata.get('credentials_port'),
'service_host': credentials_host,
'auth_host': auth_host,
'auth_port': rdata.get('auth_port'),
'admin_tenant_name': rdata.get('credentials_project'),
'admin_tenant_id': rdata.get('credentials_project_id'),
'admin_user': rdata.get('credentials_username'),
'admin_password': rdata.get('credentials_password'),
'service_protocol': svc_protocol,
'auth_protocol': auth_protocol,
'api_version': api_version
})
if float(api_version) > 2:
ctxt.update({'admin_domain_name':
rdata.get('domain')})
if self.context_complete(ctxt):
return ctxt
return {}
class AMQPContext(OSContextGenerator):
def __init__(self, ssl_dir=None, rel_name='amqp', relation_prefix=None):
@ -1323,8 +1383,6 @@ class WSGIWorkerConfigContext(WorkerConfigContext):
"public_processes": int(math.ceil(self.public_process_weight *
total_processes)),
"threads": 1,
"usr_bin": git_determine_usr_bin(),
"python_path": git_determine_python_path(),
}
return ctxt

View File

@ -15,9 +15,6 @@ Listen {{ public_port }}
{% if port -%}
<VirtualHost *:{{ port }}>
WSGIDaemonProcess {{ service_name }} processes={{ processes }} threads={{ threads }} user={{ service_name }} group={{ service_name }} \
{% if python_path -%}
python-path={{ python_path }} \
{% endif -%}
display-name=%{GROUP}
WSGIProcessGroup {{ service_name }}
WSGIScriptAlias / {{ script }}
@ -29,7 +26,7 @@ Listen {{ public_port }}
ErrorLog /var/log/apache2/{{ service_name }}_error.log
CustomLog /var/log/apache2/{{ service_name }}_access.log combined
<Directory {{ usr_bin }}>
<Directory /usr/bin>
<IfVersion >= 2.4>
Require all granted
</IfVersion>
@ -44,9 +41,6 @@ Listen {{ public_port }}
{% if admin_port -%}
<VirtualHost *:{{ admin_port }}>
WSGIDaemonProcess {{ service_name }}-admin processes={{ admin_processes }} threads={{ threads }} user={{ service_name }} group={{ service_name }} \
{% if python_path -%}
python-path={{ python_path }} \
{% endif -%}
display-name=%{GROUP}
WSGIProcessGroup {{ service_name }}-admin
WSGIScriptAlias / {{ admin_script }}
@ -58,7 +52,7 @@ Listen {{ public_port }}
ErrorLog /var/log/apache2/{{ service_name }}_error.log
CustomLog /var/log/apache2/{{ service_name }}_access.log combined
<Directory {{ usr_bin }}>
<Directory /usr/bin>
<IfVersion >= 2.4>
Require all granted
</IfVersion>
@ -73,9 +67,6 @@ Listen {{ public_port }}
{% if public_port -%}
<VirtualHost *:{{ public_port }}>
WSGIDaemonProcess {{ service_name }}-public processes={{ public_processes }} threads={{ threads }} user={{ service_name }} group={{ service_name }} \
{% if python_path -%}
python-path={{ python_path }} \
{% endif -%}
display-name=%{GROUP}
WSGIProcessGroup {{ service_name }}-public
WSGIScriptAlias / {{ public_script }}
@ -87,7 +78,7 @@ Listen {{ public_port }}
ErrorLog /var/log/apache2/{{ service_name }}_error.log
CustomLog /var/log/apache2/{{ service_name }}_access.log combined
<Directory {{ usr_bin }}>
<Directory /usr/bin>
<IfVersion >= 2.4>
Require all granted
</IfVersion>

View File

@ -23,7 +23,6 @@ import sys
import re
import itertools
import functools
import shutil
import six
import traceback
@ -47,7 +46,6 @@ from charmhelpers.core.hookenv import (
related_units,
relation_ids,
relation_set,
service_name,
status_set,
hook_name,
application_version_set,
@ -68,11 +66,6 @@ from charmhelpers.contrib.network.ip import (
port_has_listener,
)
from charmhelpers.contrib.python.packages import (
pip_create_virtualenv,
pip_install,
)
from charmhelpers.core.host import (
lsb_release,
mounts,
@ -84,7 +77,6 @@ from charmhelpers.core.host import (
)
from charmhelpers.fetch import (
apt_cache,
install_remote,
import_key as fetch_import_key,
add_source as fetch_add_source,
SourceConfigError,
@ -278,27 +270,6 @@ PACKAGE_CODENAMES = {
]),
}
GIT_DEFAULT_REPOS = {
'requirements': 'git://github.com/openstack/requirements',
'cinder': 'git://github.com/openstack/cinder',
'glance': 'git://github.com/openstack/glance',
'horizon': 'git://github.com/openstack/horizon',
'keystone': 'git://github.com/openstack/keystone',
'networking-hyperv': 'git://github.com/openstack/networking-hyperv',
'neutron': 'git://github.com/openstack/neutron',
'neutron-fwaas': 'git://github.com/openstack/neutron-fwaas',
'neutron-lbaas': 'git://github.com/openstack/neutron-lbaas',
'neutron-vpnaas': 'git://github.com/openstack/neutron-vpnaas',
'nova': 'git://github.com/openstack/nova',
}
GIT_DEFAULT_BRANCHES = {
'liberty': 'stable/liberty',
'mitaka': 'stable/mitaka',
'newton': 'stable/newton',
'master': 'master',
}
DEFAULT_LOOPBACK_SIZE = '5G'
@ -530,7 +501,6 @@ def os_release(package, base='essex', reset_cache=False):
if _os_rel:
return _os_rel
_os_rel = (
git_os_codename_install_source(config('openstack-origin-git')) or
get_os_codename_package(package, fatal=False) or
get_os_codename_install_source(config('openstack-origin')) or
base)
@ -771,417 +741,6 @@ def os_requires_version(ostack_release, pkg):
return wrap
def git_install_requested():
"""
Returns true if openstack-origin-git is specified.
"""
return config('openstack-origin-git') is not None
def git_os_codename_install_source(projects_yaml):
"""
Returns OpenStack codename of release being installed from source.
"""
if git_install_requested():
projects = _git_yaml_load(projects_yaml)
if projects in GIT_DEFAULT_BRANCHES.keys():
if projects == 'master':
return 'ocata'
return projects
if 'release' in projects:
if projects['release'] == 'master':
return 'ocata'
return projects['release']
return None
def git_default_repos(projects_yaml):
"""
Returns default repos if a default openstack-origin-git value is specified.
"""
service = service_name()
core_project = service
for default, branch in six.iteritems(GIT_DEFAULT_BRANCHES):
if projects_yaml == default:
# add the requirements repo first
repo = {
'name': 'requirements',
'repository': GIT_DEFAULT_REPOS['requirements'],
'branch': branch,
}
repos = [repo]
# neutron-* and nova-* charms require some additional repos
if service in ['neutron-api', 'neutron-gateway',
'neutron-openvswitch']:
core_project = 'neutron'
if service == 'neutron-api':
repo = {
'name': 'networking-hyperv',
'repository': GIT_DEFAULT_REPOS['networking-hyperv'],
'branch': branch,
}
repos.append(repo)
for project in ['neutron-fwaas', 'neutron-lbaas',
'neutron-vpnaas', 'nova']:
repo = {
'name': project,
'repository': GIT_DEFAULT_REPOS[project],
'branch': branch,
}
repos.append(repo)
elif service in ['nova-cloud-controller', 'nova-compute']:
core_project = 'nova'
repo = {
'name': 'neutron',
'repository': GIT_DEFAULT_REPOS['neutron'],
'branch': branch,
}
repos.append(repo)
elif service == 'openstack-dashboard':
core_project = 'horizon'
# finally add the current service's core project repo
repo = {
'name': core_project,
'repository': GIT_DEFAULT_REPOS[core_project],
'branch': branch,
}
repos.append(repo)
return yaml.dump(dict(repositories=repos, release=default))
return projects_yaml
def _git_yaml_load(projects_yaml):
"""
Load the specified yaml into a dictionary.
"""
if not projects_yaml:
return None
return yaml.load(projects_yaml)
requirements_dir = None
def git_clone_and_install(projects_yaml, core_project):
"""
Clone/install all specified OpenStack repositories.
The expected format of projects_yaml is:
repositories:
- {name: keystone,
repository: 'git://git.openstack.org/openstack/keystone.git',
branch: 'stable/icehouse'}
- {name: requirements,
repository: 'git://git.openstack.org/openstack/requirements.git',
branch: 'stable/icehouse'}
directory: /mnt/openstack-git
http_proxy: squid-proxy-url
https_proxy: squid-proxy-url
The directory, http_proxy, and https_proxy keys are optional.
"""
global requirements_dir
parent_dir = '/mnt/openstack-git'
http_proxy = None
projects = _git_yaml_load(projects_yaml)
_git_validate_projects_yaml(projects, core_project)
old_environ = dict(os.environ)
if 'http_proxy' in projects.keys():
http_proxy = projects['http_proxy']
os.environ['http_proxy'] = projects['http_proxy']
if 'https_proxy' in projects.keys():
os.environ['https_proxy'] = projects['https_proxy']
if 'directory' in projects.keys():
parent_dir = projects['directory']
pip_create_virtualenv(os.path.join(parent_dir, 'venv'))
# Upgrade setuptools and pip from default virtualenv versions. The default
# versions in trusty break master OpenStack branch deployments.
for p in ['pip', 'setuptools']:
pip_install(p, upgrade=True, proxy=http_proxy,
venv=os.path.join(parent_dir, 'venv'))
constraints = None
for p in projects['repositories']:
repo = p['repository']
branch = p['branch']
depth = '1'
if 'depth' in p.keys():
depth = p['depth']
if p['name'] == 'requirements':
repo_dir = _git_clone_and_install_single(repo, branch, depth,
parent_dir, http_proxy,
update_requirements=False)
requirements_dir = repo_dir
constraints = os.path.join(repo_dir, "upper-constraints.txt")
# upper-constraints didn't exist until after icehouse
if not os.path.isfile(constraints):
constraints = None
# use constraints unless project yaml sets use_constraints to false
if 'use_constraints' in projects.keys():
if not projects['use_constraints']:
constraints = None
else:
repo_dir = _git_clone_and_install_single(repo, branch, depth,
parent_dir, http_proxy,
update_requirements=True,
constraints=constraints)
os.environ = old_environ
def _git_validate_projects_yaml(projects, core_project):
"""
Validate the projects yaml.
"""
_git_ensure_key_exists('repositories', projects)
for project in projects['repositories']:
_git_ensure_key_exists('name', project.keys())
_git_ensure_key_exists('repository', project.keys())
_git_ensure_key_exists('branch', project.keys())
if projects['repositories'][0]['name'] != 'requirements':
error_out('{} git repo must be specified first'.format('requirements'))
if projects['repositories'][-1]['name'] != core_project:
error_out('{} git repo must be specified last'.format(core_project))
_git_ensure_key_exists('release', projects)
def _git_ensure_key_exists(key, keys):
"""
Ensure that key exists in keys.
"""
if key not in keys:
error_out('openstack-origin-git key \'{}\' is missing'.format(key))
def _git_clone_and_install_single(repo, branch, depth, parent_dir, http_proxy,
update_requirements, constraints=None):
"""
Clone and install a single git repository.
"""
if not os.path.exists(parent_dir):
juju_log('Directory already exists at {}. '
'No need to create directory.'.format(parent_dir))
os.mkdir(parent_dir)
juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch))
repo_dir = install_remote(
repo, dest=parent_dir, branch=branch, depth=depth)
venv = os.path.join(parent_dir, 'venv')
if update_requirements:
if not requirements_dir:
error_out('requirements repo must be cloned before '
'updating from global requirements.')
_git_update_requirements(venv, repo_dir, requirements_dir)
juju_log('Installing git repo from dir: {}'.format(repo_dir))
if http_proxy:
pip_install(repo_dir, proxy=http_proxy, venv=venv,
constraints=constraints)
else:
pip_install(repo_dir, venv=venv, constraints=constraints)
return repo_dir
def _git_update_requirements(venv, package_dir, reqs_dir):
"""
Update from global requirements.
Update an OpenStack git directory's requirements.txt and
test-requirements.txt from global-requirements.txt.
"""
orig_dir = os.getcwd()
os.chdir(reqs_dir)
python = os.path.join(venv, 'bin/python')
cmd = [python, 'update.py', package_dir]
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError:
package = os.path.basename(package_dir)
error_out("Error updating {} from "
"global-requirements.txt".format(package))
os.chdir(orig_dir)
def git_pip_venv_dir(projects_yaml):
"""
Return the pip virtualenv path.
"""
parent_dir = '/mnt/openstack-git'
projects = _git_yaml_load(projects_yaml)
if 'directory' in projects.keys():
parent_dir = projects['directory']
return os.path.join(parent_dir, 'venv')
def git_src_dir(projects_yaml, project):
"""
Return the directory where the specified project's source is located.
"""
parent_dir = '/mnt/openstack-git'
projects = _git_yaml_load(projects_yaml)
if 'directory' in projects.keys():
parent_dir = projects['directory']
for p in projects['repositories']:
if p['name'] == project:
return os.path.join(parent_dir, os.path.basename(p['repository']))
return None
def git_yaml_value(projects_yaml, key):
"""
Return the value in projects_yaml for the specified key.
"""
projects = _git_yaml_load(projects_yaml)
if key in projects.keys():
return projects[key]
return None
def git_generate_systemd_init_files(templates_dir):
"""
Generate systemd init files.
Generates and installs systemd init units and script files based on the
*.init.in files contained in the templates_dir directory.
This code is based on the openstack-pkg-tools package and its init
script generation, which is used by the OpenStack packages.
"""
for f in os.listdir(templates_dir):
# Create the init script and systemd unit file from the template
if f.endswith(".init.in"):
init_in_file = f
init_file = f[:-8]
service_file = "{}.service".format(init_file)
init_in_source = os.path.join(templates_dir, init_in_file)
init_source = os.path.join(templates_dir, init_file)
service_source = os.path.join(templates_dir, service_file)
init_dest = os.path.join('/etc/init.d', init_file)
service_dest = os.path.join('/lib/systemd/system', service_file)
shutil.copyfile(init_in_source, init_source)
with open(init_source, 'a') as outfile:
template = ('/usr/share/openstack-pkg-tools/'
'init-script-template')
with open(template) as infile:
outfile.write('\n\n{}'.format(infile.read()))
cmd = ['pkgos-gen-systemd-unit', init_in_source]
subprocess.check_call(cmd)
if os.path.exists(init_dest):
os.remove(init_dest)
if os.path.exists(service_dest):
os.remove(service_dest)
shutil.copyfile(init_source, init_dest)
shutil.copyfile(service_source, service_dest)
os.chmod(init_dest, 0o755)
for f in os.listdir(templates_dir):
# If there's a service.in file, use it instead of the generated one
if f.endswith(".service.in"):
service_in_file = f
service_file = f[:-3]
service_in_source = os.path.join(templates_dir, service_in_file)
service_source = os.path.join(templates_dir, service_file)
service_dest = os.path.join('/lib/systemd/system', service_file)
shutil.copyfile(service_in_source, service_source)
if os.path.exists(service_dest):
os.remove(service_dest)
shutil.copyfile(service_source, service_dest)
for f in os.listdir(templates_dir):
# Generate the systemd unit if there's no existing .service.in
if f.endswith(".init.in"):
init_in_file = f
init_file = f[:-8]
service_in_file = "{}.service.in".format(init_file)
service_file = "{}.service".format(init_file)
init_in_source = os.path.join(templates_dir, init_in_file)
service_in_source = os.path.join(templates_dir, service_in_file)
service_source = os.path.join(templates_dir, service_file)
service_dest = os.path.join('/lib/systemd/system', service_file)
if not os.path.exists(service_in_source):
cmd = ['pkgos-gen-systemd-unit', init_in_source]
subprocess.check_call(cmd)
if os.path.exists(service_dest):
os.remove(service_dest)
shutil.copyfile(service_source, service_dest)
def git_determine_usr_bin():
"""Return the /usr/bin path for Apache2 config.
The /usr/bin path will be located in the virtualenv if the charm
is configured to deploy from source.
"""
if git_install_requested():
projects_yaml = config('openstack-origin-git')
projects_yaml = git_default_repos(projects_yaml)
return os.path.join(git_pip_venv_dir(projects_yaml), 'bin')
else:
return '/usr/bin'
def git_determine_python_path():
"""Return the python-path for Apache2 config.
Returns 'None' unless the charm is configured to deploy from source,
in which case the path of the virtualenv's site-packages is returned.
"""
if git_install_requested():
projects_yaml = config('openstack-origin-git')
projects_yaml = git_default_repos(projects_yaml)
return os.path.join(git_pip_venv_dir(projects_yaml),
'lib/python2.7/site-packages')
else:
return None
def os_workload_status(configs, required_interfaces, charm_func=None):
"""
Decorator to set workload status based on complete contexts
@ -1615,27 +1174,24 @@ def do_action_openstack_upgrade(package, upgrade_callback, configs):
"""
ret = False
if git_install_requested():
action_set({'outcome': 'installed from source, skipped upgrade.'})
else:
if openstack_upgrade_available(package):
if config('action-managed-upgrade'):
juju_log('Upgrading OpenStack release')
if openstack_upgrade_available(package):
if config('action-managed-upgrade'):
juju_log('Upgrading OpenStack release')
try:
upgrade_callback(configs=configs)
action_set({'outcome': 'success, upgrade completed.'})
ret = True
except Exception:
action_set({'outcome': 'upgrade failed, see traceback.'})
action_set({'traceback': traceback.format_exc()})
action_fail('do_openstack_upgrade resulted in an '
'unexpected error')
else:
action_set({'outcome': 'action-managed-upgrade config is '
'False, skipped upgrade.'})
try:
upgrade_callback(configs=configs)
action_set({'outcome': 'success, upgrade completed.'})
ret = True
except Exception:
action_set({'outcome': 'upgrade failed, see traceback.'})
action_set({'traceback': traceback.format_exc()})
action_fail('do_openstack_upgrade resulted in an '
'unexpected error')
else:
action_set({'outcome': 'no upgrade available.'})
action_set({'outcome': 'action-managed-upgrade config is '
'False, skipped upgrade.'})
else:
action_set({'outcome': 'no upgrade available.'})
return ret
@ -2045,14 +1601,25 @@ def token_cache_pkgs(source=None, release=None):
def update_json_file(filename, items):
"""Updates the json `filename` with a given dict.
:param filename: json filename (i.e.: /etc/glance/policy.json)
:param filename: path to json file (e.g. /etc/glance/policy.json)
:param items: dict of items to update
"""
if not items:
return
with open(filename) as fd:
policy = json.load(fd)
# Compare before and after and if nothing has changed don't write the file
# since that could cause unnecessary service restarts.
before = json.dumps(policy, indent=4, sort_keys=True)
policy.update(items)
after = json.dumps(policy, indent=4, sort_keys=True)
if before == after:
return
with open(filename, "w") as fd:
fd.write(json.dumps(policy, indent=4))
fd.write(after)
@cached

View File

@ -113,7 +113,7 @@ def validator(value, valid_type, valid_range=None):
assert isinstance(valid_range, list), \
"valid_range must be a list, was given {}".format(valid_range)
# If we're dealing with strings
if valid_type is six.string_types:
if isinstance(value, six.string_types):
assert value in valid_range, \
"{} is not in the list {}".format(value, valid_range)
# Integer, float should have a min and max
@ -517,7 +517,8 @@ def pool_set(service, pool_name, key, value):
:param value:
:return: None. Can raise CalledProcessError
"""
cmd = ['ceph', '--id', service, 'osd', 'pool', 'set', pool_name, key, value]
cmd = ['ceph', '--id', service, 'osd', 'pool', 'set', pool_name, key,
str(value).lower()]
try:
check_call(cmd)
except CalledProcessError:
@ -621,16 +622,24 @@ def create_erasure_profile(service, profile_name, erasure_plugin_name='jerasure'
:param durability_estimator: int
:return: None. Can raise CalledProcessError
"""
version = ceph_version()
# Ensure this failure_domain is allowed by Ceph
validator(failure_domain, six.string_types,
['chassis', 'datacenter', 'host', 'osd', 'pdu', 'pod', 'rack', 'region', 'room', 'root', 'row'])
cmd = ['ceph', '--id', service, 'osd', 'erasure-code-profile', 'set', profile_name,
'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks),
'ruleset_failure_domain=' + failure_domain]
'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks)
]
if locality is not None and durability_estimator is not None:
raise ValueError("create_erasure_profile should be called with k, m and one of l or c but not both.")
# failure_domain changed in luminous
if version and version >= '12.0.0':
cmd.append('crush-failure-domain=' + failure_domain)
else:
cmd.append('ruleset-failure-domain=' + failure_domain)
# Add plugin specific information
if locality is not None:
# For local erasure codes
@ -1064,14 +1073,24 @@ class CephBrokerRq(object):
self.ops = []
def add_op_request_access_to_group(self, name, namespace=None,
permission=None, key_name=None):
permission=None, key_name=None,
object_prefix_permissions=None):
"""
Adds the requested permissions to the current service's Ceph key,
allowing the key to access only the specified pools
allowing the key to access only the specified pools or
object prefixes. object_prefix_permissions should be a dictionary
keyed on the permission with the corresponding value being a list
of prefixes to apply that permission to.
{
'rwx': ['prefix1', 'prefix2'],
'class-read': ['prefix3']}
"""
self.ops.append({'op': 'add-permissions-to-key', 'group': name,
'namespace': namespace, 'name': key_name or service_name(),
'group-permission': permission})
self.ops.append({
'op': 'add-permissions-to-key', 'group': name,
'namespace': namespace,
'name': key_name or service_name(),
'group-permission': permission,
'object-prefix-permissions': object_prefix_permissions})
def add_op_create_pool(self, name, replica_count=3, pg_num=None,
weight=None, group=None, namespace=None):
@ -1107,7 +1126,10 @@ class CephBrokerRq(object):
def _ops_equal(self, other):
if len(self.ops) == len(other.ops):
for req_no in range(0, len(self.ops)):
for key in ['replicas', 'name', 'op', 'pg_num', 'weight']:
for key in [
'replicas', 'name', 'op', 'pg_num', 'weight',
'group', 'group-namespace', 'group-permission',
'object-prefix-permissions']:
if self.ops[req_no].get(key) != other.ops[req_no].get(key):
return False
else:

View File

@ -35,30 +35,6 @@ options:
NOTE: updating this setting to a source that is known to provide
a later version of OpenStack will trigger a software upgrade unless
action-managed-upgrade is set to True.
openstack-origin-git:
type: string
default:
description: |
Specifies a default OpenStack release name, or a YAML dictionary
listing the git repositories to install from.
.
The default Openstack release name may be one of the following, where
the corresponding OpenStack github branch will be used:
* liberty
* mitaka
* newton
* master
.
The YAML must minimally include requirements and keystone repositories,
and may also include repositories for other dependencies:
repositories:
- {name: requirements,
repository: 'git://github.com/openstack/requirements',
branch: master}
- {name: keystone,
repository: 'git://github.com/openstack/keystone',
branch: master}
release: master
action-managed-upgrade:
type: boolean
default: False

View File

@ -62,9 +62,7 @@ from charmhelpers.fetch import (
)
from charmhelpers.contrib.openstack.utils import (
config_value_changed,
configure_installation_source,
git_install_requested,
openstack_upgrade_available,
sync_db_with_multi_ipv6_addresses,
os_release,
@ -85,7 +83,6 @@ from keystone_utils import (
do_openstack_upgrade_reexec,
ensure_initial_admin,
get_admin_passwd,
git_install,
migrate_database,
save_script_rc,
post_snap_install,
@ -195,11 +192,7 @@ def install():
service_start('haproxy')
if run_in_apache():
disable_unused_apache_sites()
if not git_install_requested():
service_pause('keystone')
status_set('maintenance', 'Git install')
git_install(config('openstack-origin-git'))
service_pause('keystone')
unison.ensure_user(user=SSH_USER, group=SSH_USER)
unison.ensure_user(user=SSH_USER, group=KEYSTONE_USER)
@ -222,11 +215,7 @@ def config_changed():
if not os.path.isdir(homedir):
mkdir(homedir, SSH_USER, SSH_USER, 0o775)
if git_install_requested():
if config_value_changed('openstack-origin-git'):
status_set('maintenance', 'Running Git install')
git_install(config('openstack-origin-git'))
elif not config('action-managed-upgrade'):
if not config('action-managed-upgrade'):
if openstack_upgrade_available('keystone'):
status_set('maintenance', 'Running openstack upgrade')
do_openstack_upgrade_reexec(configs=CONFIGS)
@ -258,8 +247,7 @@ def config_changed_postupgrade():
# decorator can fire
apt_install(filter_installed_packages(determine_packages()))
# when deployed from source, init scripts aren't installed
if not git_install_requested():
service_pause('keystone')
service_pause('keystone')
disable_unused_apache_sites()
if WSGI_KEYSTONE_API_CONF in CONFIGS.templates:

View File

@ -60,18 +60,10 @@ from charmhelpers.contrib.openstack.utils import (
configure_installation_source,
error_out,
get_os_codename_install_source,
git_clone_and_install,
git_default_repos,
git_determine_usr_bin,
git_install_requested,
git_pip_venv_dir,
git_src_dir,
git_yaml_value,
os_release,
save_script_rc as _save_script_rc,
pause_unit,
resume_unit,
is_unit_paused_set,
make_assess_status_func,
os_application_version_set,
CompareOpenStackReleases,
@ -82,10 +74,6 @@ from charmhelpers.contrib.openstack.utils import (
enable_memcache,
)
from charmhelpers.contrib.python.packages import (
pip_install,
)
from charmhelpers.core.strutils import (
bool_from_string,
)
@ -97,7 +85,6 @@ from charmhelpers.core.decorators import (
)
from charmhelpers.core.hookenv import (
charm_dir,
config,
leader_get,
leader_set,
@ -123,9 +110,6 @@ from charmhelpers.fetch import (
)
from charmhelpers.core.host import (
adduser,
add_group,
add_user_to_group,
mkdir,
service_stop,
service_start,
@ -143,8 +127,6 @@ from charmhelpers.contrib.peerstorage import (
relation_set as relation_set_and_migrate_to_leader,
)
from charmhelpers.core.templating import render
import keystone_context
import keystone_ssl as ssl
@ -177,25 +159,6 @@ BASE_PACKAGES_SNAP = [
VERSION_PACKAGE = 'keystone'
BASE_GIT_PACKAGES = [
'libffi-dev',
'libmysqlclient-dev',
'libssl-dev',
'libxml2-dev',
'libxslt1-dev',
'libyaml-dev',
'python-dev',
'python-pip',
'python-setuptools',
'zlib1g-dev',
]
# ubuntu packages that should not be installed when deploying from git
GIT_PACKAGE_BLACKLIST = [
'keystone',
]
SSH_USER = 'juju_keystone'
if snap_install_requested():
SNAP_BASE_DIR = "/snap/keystone/current"
@ -547,16 +510,12 @@ def resource_map():
svcs.remove('keystone')
if 'apache2' not in svcs:
svcs.append('apache2')
admin_script = os.path.join(git_determine_usr_bin(),
"keystone-wsgi-admin")
public_script = os.path.join(git_determine_usr_bin(),
"keystone-wsgi-public")
resource_map[WSGI_KEYSTONE_API_CONF] = {
'contexts': [
context.WSGIWorkerConfigContext(
name="keystone",
admin_script=admin_script,
public_script=public_script),
admin_script='/usr/bin/keystone-wsgi-admin',
public_script='/usr/bin/keystone-wsgi-public'),
keystone_context.KeystoneContext()],
'services': ['apache2']
}
@ -664,9 +623,6 @@ def determine_packages():
return sorted(pkgs)
else:
packages = set(services()).union(BASE_PACKAGES)
if git_install_requested():
packages |= set(BASE_GIT_PACKAGES)
packages -= set(GIT_PACKAGE_BLACKLIST)
if run_in_apache():
packages.add('libapache2-mod-wsgi')
return sorted(packages)
@ -2460,23 +2416,10 @@ def is_db_ready(use_current_context=False, db_rel=None):
return not rel_has_units
def determine_usr_bin():
"""Return the /usr/bin path for Apache2 vhost config.
The /usr/bin path will be located in the virtualenv if the charm
is configured to deploy keystone from source.
"""
if git_install_requested():
projects_yaml = config('openstack-origin-git')
projects_yaml = git_default_repos(projects_yaml)
return os.path.join(git_pip_venv_dir(projects_yaml), 'bin')
else:
return '/usr/bin'
def determine_python_path():
"""Return the python-path
Determine if git or snap installed and return the appropriate python path.
Determine if snap installed and return the appropriate python path.
Returns None unless the charm if neither condition is true.
:returns: string python path or None
@ -2484,108 +2427,10 @@ def determine_python_path():
_python_path = 'lib/python2.7/site-packages'
if snap_install_requested():
return os.path.join(SNAP_BASE_DIR, _python_path)
elif git_install_requested():
projects_yaml = config('openstack-origin-git')
projects_yaml = git_default_repos(projects_yaml)
return os.path.join(git_pip_venv_dir(projects_yaml), _python_path)
else:
return None
def git_install(projects_yaml):
"""Perform setup, and install git repos specified in yaml parameter."""
if git_install_requested():
git_pre_install()
projects_yaml = git_default_repos(projects_yaml)
git_clone_and_install(projects_yaml, core_project='keystone')
git_post_install(projects_yaml)
def git_pre_install():
"""Perform keystone pre-install setup."""
dirs = [
'/var/lib/keystone',
'/var/lib/keystone/cache',
'/var/log/keystone',
]
logs = [
'/var/log/keystone/keystone.log',
]
adduser('keystone', shell='/bin/bash', system_user=True,
home_dir='/var/lib/keystone')
add_group('keystone', system_group=True)
add_user_to_group('keystone', 'keystone')
for d in dirs:
mkdir(d, owner=KEYSTONE_USER, group=KEYSTONE_USER, perms=0o755,
force=False)
for l in logs:
write_file(l, '', owner=KEYSTONE_USER, group=KEYSTONE_USER,
perms=0o600)
def git_post_install(projects_yaml):
"""Perform keystone post-install setup."""
http_proxy = git_yaml_value(projects_yaml, 'http_proxy')
if http_proxy:
pip_install('mysql-python', proxy=http_proxy,
venv=git_pip_venv_dir(projects_yaml))
else:
pip_install('mysql-python',
venv=git_pip_venv_dir(projects_yaml))
src_etc = os.path.join(git_src_dir(projects_yaml, 'keystone'), 'etc')
configs = {
'src': src_etc,
'dest': '/etc/keystone',
}
if os.path.exists(configs['dest']):
shutil.rmtree(configs['dest'])
shutil.copytree(configs['src'], configs['dest'])
# NOTE(coreycb): Need to find better solution than bin symlinks.
symlinks = [
{'src': os.path.join(git_pip_venv_dir(projects_yaml),
'bin/keystone-manage'),
'link': '/usr/local/bin/keystone-manage'},
]
for s in symlinks:
if os.path.lexists(s['link']):
os.remove(s['link'])
os.symlink(s['src'], s['link'])
render('git/logging.conf', '/etc/keystone/logging.conf', {}, perms=0o644)
bin_dir = os.path.join(git_pip_venv_dir(projects_yaml), 'bin')
# The charm runs the keystone API under apache2 for openstack liberty
# onward. Prior to liberty upstart is used.
if CompareOpenStackReleases(os_release('keystone')) < 'liberty':
keystone_context = {
'service_description': 'Keystone API server',
'service_name': 'Keystone',
'user_name': 'keystone',
'start_dir': '/var/lib/keystone',
'process_name': 'keystone',
'executable_name': os.path.join(bin_dir, 'keystone-all'),
'config_files': ['/etc/keystone/keystone.conf'],
}
keystone_context['log_file'] = '/var/log/keystone/keystone.log'
templates_dir = 'hooks/charmhelpers/contrib/openstack/templates'
templates_dir = os.path.join(charm_dir(), templates_dir)
render('git.upstart', '/etc/init/keystone.conf', keystone_context,
perms=0o644, templates_dir=templates_dir)
# Don't restart if the unit is supposed to be paused.
if not is_unit_paused_set():
service_restart(keystone_service())
def get_optional_interfaces():
"""Return the optional interfaces that should be checked if the relavent
relations have appeared.

View File

@ -1,39 +0,0 @@
[loggers]
keys=root
[formatters]
keys=normal,normal_with_name,debug
[handlers]
keys=production,file,devel
[logger_root]
level=WARNING
handlers=file
[handler_production]
class=handlers.SysLogHandler
level=ERROR
formatter=normal_with_name
args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
[handler_file]
class=FileHandler
level=DEBUG
formatter=normal_with_name
args=('/var/log/keystone/keystone.log', 'a')
[handler_devel]
class=StreamHandler
level=NOTSET
formatter=debug
args=(sys.stdout,)
[formatter_normal]
format=%(asctime)s %(levelname)s %(message)s
[formatter_normal_with_name]
format=(%(name)s): %(asctime)s %(levelname)s %(message)s
[formatter_debug]
format=(%(name)s): %(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s

View File

@ -21,7 +21,6 @@ Basic keystone amulet functional tests.
import amulet
import json
import os
import yaml
from charmhelpers.contrib.openstack.amulet.deployment import (
OpenStackAmuletDeployment
@ -45,13 +44,12 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
DEFAULT_DOMAIN = 'default'
def __init__(self, series=None, openstack=None,
source=None, git=False, stable=False, snap_source=None):
source=None, stable=False, snap_source=None):
"""Deploy the entire test environment."""
super(KeystoneBasicDeployment, self).__init__(series, openstack,
source, stable)
self.keystone_num_units = 3
self.keystone_api_version = 2
self.git = git
self._setup_test_object(snap_source)
self._add_services()
@ -142,33 +140,6 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
'preferred-api-version': self.keystone_api_version,
})
if self.git:
amulet_http_proxy = os.environ.get('AMULET_HTTP_PROXY')
reqs_repo = 'git://github.com/openstack/requirements'
keystone_repo = 'git://github.com/openstack/keystone'
if self._get_openstack_release() == self.trusty_icehouse:
reqs_repo = 'git://github.com/coreycb/requirements'
keystone_repo = 'git://github.com/coreycb/keystone'
branch = 'stable/' + self._get_openstack_release_string()
openstack_origin_git = {
'repositories': [
{'name': 'requirements',
'repository': reqs_repo,
'branch': branch},
{'name': 'keystone',
'repository': keystone_repo,
'branch': branch},
],
'directory': '/mnt/openstack-git',
'http_proxy': amulet_http_proxy,
'https_proxy': amulet_http_proxy,
}
self.keystone_config['openstack-origin-git'] = \
yaml.dump(openstack_origin_git)
pxc_config = {
'dataset-size': '25%',
'max-connections': 1000,

View File

@ -1,23 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2016 Canonical Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Amulet tests on a basic keystone git deployment on trusty-icehouse."""
from basic_deployment import KeystoneBasicDeployment
if __name__ == '__main__':
deployment = KeystoneBasicDeployment(series='trusty', git=True)
deployment.run_tests()

View File

@ -1,26 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2016 Canonical Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Amulet tests on a basic keystone git deployment on trusty-kilo."""
from basic_deployment import KeystoneBasicDeployment
if __name__ == '__main__':
deployment = KeystoneBasicDeployment(series='trusty',
openstack='cloud:trusty-kilo',
source='cloud:trusty-updates/kilo',
git=True)
deployment.run_tests()

View File

@ -1,126 +0,0 @@
# Copyright 2016 Canonical Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from mock import patch, MagicMock
# python-apt is not installed as part of test-requirements but is imported by
# some charmhelpers modules so create a fake import.
mock_apt = MagicMock()
sys.modules['apt'] = mock_apt
mock_apt.apt_pkg = MagicMock()
# NOTE(hopem): we have to mock hooks.charmhelpers (not charmhelpers)
# otherwise the mock is not applied to action.hooks.*
with patch('hooks.charmhelpers.contrib.hardening.harden.harden') as mock_dec, \
patch('hooks.charmhelpers.contrib.openstack.utils.'
'snap_install_requested') as snap_install_requested, \
patch('hooks.keystone_utils.register_configs') as register_configs, \
patch('hooks.keystone_utils.os_release') as os_release:
snap_install_requested.return_value = False
mock_dec.side_effect = (lambda *dargs, **dkwargs: lambda f:
lambda *args, **kwargs: f(*args, **kwargs))
os_release.return_value = 'juno'
import git_reinstall
from test_utils import (
CharmTestCase
)
TO_PATCH = [
'config',
]
openstack_origin_git = \
"""repositories:
- {name: requirements,
repository: 'git://git.openstack.org/openstack/requirements',
branch: stable/juno}
- {name: keystone,
repository: 'git://git.openstack.org/openstack/keystone',
branch: stable/juno}"""
class TestKeystoneActions(CharmTestCase):
def setUp(self):
super(TestKeystoneActions, self).setUp(git_reinstall, TO_PATCH)
self.config.side_effect = self.test_config.get
@patch.object(git_reinstall, 'action_set')
@patch.object(git_reinstall, 'action_fail')
@patch.object(git_reinstall, 'git_install')
@patch.object(git_reinstall, 'config_changed')
@patch('charmhelpers.contrib.openstack.utils.config')
def test_git_reinstall(self, config, config_changed, git_install,
action_fail, action_set):
config.return_value = openstack_origin_git
self.test_config.set('openstack-origin-git', openstack_origin_git)
git_reinstall.git_reinstall()
git_install.assert_called_with(openstack_origin_git)
self.assertTrue(git_install.called)
self.assertTrue(config_changed.called)
self.assertFalse(action_set.called)
self.assertFalse(action_fail.called)
@patch.object(git_reinstall, 'action_set')
@patch.object(git_reinstall, 'action_fail')
@patch.object(git_reinstall, 'git_install')
@patch.object(git_reinstall, 'config_changed')
@patch('charmhelpers.contrib.openstack.utils.config')
def test_git_reinstall_not_configured(self, _config, config_changed,
git_install, action_fail,
action_set):
_config.return_value = None
git_reinstall.git_reinstall()
msg = 'openstack-origin-git is not configured'
action_fail.assert_called_with(msg)
self.assertFalse(git_install.called)
self.assertFalse(action_set.called)
@patch.object(git_reinstall, 'action_set')
@patch.object(git_reinstall, 'action_fail')
@patch.object(git_reinstall, 'git_install')
@patch.object(git_reinstall, 'config_changed')
@patch('traceback.format_exc')
@patch('charmhelpers.contrib.openstack.utils.config')
def test_git_reinstall_exception(self, _config, format_exc,
config_changed, git_install, action_fail,
action_set):
_config.return_value = openstack_origin_git
e = OSError('something bad happened')
git_install.side_effect = e
traceback = (
"Traceback (most recent call last):\n"
" File \"actions/git_reinstall.py\", line 37, in git_reinstall\n"
" git_install(config(\'openstack-origin-git\'))\n"
" File \"/usr/lib/python2.7/dist-packages/mock.py\", line 964, in __call__\n" # noqa
" return _mock_self._mock_call(*args, **kwargs)\n"
" File \"/usr/lib/python2.7/dist-packages/mock.py\", line 1019, in _mock_call\n" # noqa
" raise effect\n"
"OSError: something bad happened\n")
format_exc.return_value = traceback
git_reinstall.git_reinstall()
msg = 'git-reinstall resulted in an unexpected error'
action_fail.assert_called_with(msg)
action_set.assert_called_with({'traceback': traceback})

View File

@ -46,11 +46,9 @@ class TestKeystoneUpgradeActions(CharmTestCase):
@patch.object(openstack_upgrade, 'register_configs')
@patch('charmhelpers.contrib.openstack.utils.config')
@patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.git_install_requested')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
def test_openstack_upgrade_true(self, upgrade_avail, git_requested,
def test_openstack_upgrade_true(self, upgrade_avail,
action_set, config, reg_configs):
git_requested.return_value = False
upgrade_avail.return_value = True
config.return_value = True
@ -63,11 +61,9 @@ class TestKeystoneUpgradeActions(CharmTestCase):
@patch.object(openstack_upgrade, 'register_configs')
@patch('charmhelpers.contrib.openstack.utils.config')
@patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.git_install_requested')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
def test_openstack_upgrade_false(self, upgrade_avail, git_requested,
def test_openstack_upgrade_false(self, upgrade_avail,
action_set, config, reg_configs):
git_requested.return_value = False
upgrade_avail.return_value = True
config.return_value = False

View File

@ -14,7 +14,6 @@
import os
import uuid
import yaml
import sys
from mock import call, patch, MagicMock
@ -71,7 +70,6 @@ TO_PATCH = [
'service_restart',
# charmhelpers.contrib.openstack.utils
'configure_installation_source',
'git_install_requested',
'snap_install_requested',
# charmhelpers.contrib.openstack.ip
'resolve_address',
@ -107,7 +105,6 @@ TO_PATCH = [
# ip
'get_iface_for_address',
'get_netmask_for_address',
'git_install',
'is_service_present',
'delete_service_entry',
'os_release',
@ -128,13 +125,11 @@ class KeystoneRelationTests(CharmTestCase):
self.snap_install_requested.return_value = False
@patch.object(utils, 'os_release')
@patch.object(utils, 'git_install_requested')
@patch.object(unison, 'ensure_user')
@patch.object(hooks, 'service_stop', lambda *args: None)
@patch.object(hooks, 'service_start', lambda *args: None)
def test_install_hook(self, ensure_user, git_requested, os_release):
def test_install_hook(self, ensure_user, os_release):
os_release.return_value = 'havana'
git_requested.return_value = False
self.run_in_apache.return_value = False
repo = 'cloud:precise-grizzly'
self.test_config.set('openstack-origin', repo)
@ -147,18 +142,14 @@ class KeystoneRelationTests(CharmTestCase):
['apache2', 'haproxy', 'keystone', 'openssl', 'pwgen',
'python-keystoneclient', 'python-mysqldb', 'python-psycopg2',
'python-six', 'unison', 'uuid'], fatal=True)
self.git_install.assert_called_with(None)
self.disable_unused_apache_sites.assert_not_called()
@patch.object(utils, 'os_release')
@patch.object(utils, 'git_install_requested')
@patch.object(unison, 'ensure_user')
@patch.object(hooks, 'service_stop', lambda *args: None)
@patch.object(hooks, 'service_start', lambda *args: None)
def test_install_hook_apache2(self, ensure_user,
git_requested, os_release):
def test_install_hook_apache2(self, ensure_user, os_release):
os_release.return_value = 'havana'
git_requested.return_value = False
self.run_in_apache.return_value = True
repo = 'cloud:xenial-newton'
self.test_config.set('openstack-origin', repo)
@ -172,46 +163,8 @@ class KeystoneRelationTests(CharmTestCase):
['apache2', 'haproxy', 'keystone', 'openssl', 'pwgen',
'python-keystoneclient', 'python-mysqldb', 'python-psycopg2',
'python-six', 'unison', 'uuid'], fatal=True)
self.git_install.assert_called_with(None)
self.disable_unused_apache_sites.assert_called_with()
@patch.object(utils, 'os_release')
@patch.object(utils, 'git_install_requested')
@patch.object(unison, 'ensure_user')
@patch.object(hooks, 'service_stop', lambda *args: None)
@patch.object(hooks, 'service_start', lambda *args: None)
def test_install_hook_git(self, ensure_user, git_requested, os_release):
os_release.return_value = 'havana'
git_requested.return_value = True
repo = 'cloud:trusty-juno'
openstack_origin_git = {
'repositories': [
{'name': 'requirements',
'repository': 'git://git.openstack.org/openstack/requirements', # noqa
'branch': 'stable/juno'},
{'name': 'keystone',
'repository': 'git://git.openstack.org/openstack/keystone',
'branch': 'stable/juno'}
],
'directory': '/mnt/openstack-git',
}
projects_yaml = yaml.dump(openstack_origin_git)
self.test_config.set('openstack-origin', repo)
self.test_config.set('openstack-origin-git', projects_yaml)
hooks.install()
self.assertTrue(self.execd_preinstall.called)
self.configure_installation_source.assert_called_with(repo)
ensure_user.assert_called_with(user=self.ssh_user, group='keystone')
self.assertTrue(self.apt_update.called)
self.apt_install.assert_called_with(
['apache2', 'haproxy', 'libffi-dev', 'libmysqlclient-dev',
'libssl-dev', 'libxml2-dev', 'libxslt1-dev', 'libyaml-dev',
'openssl', 'pwgen', 'python-dev', 'python-keystoneclient',
'python-mysqldb', 'python-pip', 'python-psycopg2',
'python-setuptools', 'python-six', 'unison', 'uuid',
'zlib1g-dev'], fatal=True)
self.git_install.assert_called_with(projects_yaml)
mod_ch_openstack_utils = 'charmhelpers.contrib.openstack.utils'
@patch.object(utils, 'os_release')
@ -342,7 +295,6 @@ class KeystoneRelationTests(CharmTestCase):
@patch.object(hooks, 'update_all_identity_relation_units')
@patch.object(hooks, 'run_in_apache')
@patch.object(hooks, 'is_db_initialised')
@patch.object(hooks, 'git_install_requested')
@patch('keystone_utils.log')
@patch('keystone_utils.ensure_ssl_cert_master')
@patch('keystone_utils.ensure_ssl_dirs')
@ -375,7 +327,7 @@ class KeystoneRelationTests(CharmTestCase):
mock_ensure_pki_dir_permissions,
mock_ensure_ssl_dirs,
mock_ensure_ssl_cert_master,
mock_log, git_requested,
mock_log,
mock_is_db_initialised,
mock_run_in_apache,
update,
@ -390,7 +342,6 @@ class KeystoneRelationTests(CharmTestCase):
self.relation_ids.side_effect = fake_relation_ids
mock_run_in_apache.return_value = False
git_requested.return_value = False
mock_is_ssl_cert_master.return_value = True
mock_is_db_initialised.return_value = True
self.is_db_ready.return_value = True
@ -417,7 +368,6 @@ class KeystoneRelationTests(CharmTestCase):
@patch.object(hooks, 'update_all_domain_backends')
@patch.object(hooks, 'update_all_identity_relation_units')
@patch.object(hooks, 'run_in_apache')
@patch.object(hooks, 'git_install_requested')
@patch('keystone_utils.log')
@patch('keystone_utils.ensure_ssl_cert_master')
@patch('keystone_utils.ensure_ssl_dirs')
@ -446,7 +396,7 @@ class KeystoneRelationTests(CharmTestCase):
mock_ensure_pki_permissions,
ensure_ssl_dirs,
mock_ensure_ssl_cert_master,
mock_log, git_requested,
mock_log,
mock_run_in_apache, update,
mock_update_domains):
@ -459,7 +409,6 @@ class KeystoneRelationTests(CharmTestCase):
self.relation_ids.side_effect = fake_relation_ids
mock_run_in_apache.return_value = False
git_requested.return_value = False
mock_is_ssl_cert_master.return_value = True
mock_peer_units.return_value = []
self.openstack_upgrade_available.return_value = False
@ -483,7 +432,6 @@ class KeystoneRelationTests(CharmTestCase):
@patch.object(hooks, 'update_all_identity_relation_units')
@patch.object(hooks, 'run_in_apache')
@patch.object(hooks, 'is_db_initialised')
@patch.object(hooks, 'git_install_requested')
@patch('keystone_utils.log')
@patch('keystone_utils.ensure_ssl_cert_master')
@patch('keystone_utils.ensure_ssl_dirs')
@ -515,7 +463,7 @@ class KeystoneRelationTests(CharmTestCase):
mock_ensure_pki_permissions,
mock_ensure_ssl_dirs,
mock_ensure_ssl_cert_master,
mock_log, git_requested,
mock_log,
mock_is_db_initialised,
mock_run_in_apache,
update,
@ -529,7 +477,6 @@ class KeystoneRelationTests(CharmTestCase):
self.relation_ids.side_effect = fake_relation_ids
mock_run_in_apache.return_value = False
git_requested.return_value = False
mock_is_ssl_cert_master.return_value = True
self.is_db_ready.return_value = True
mock_is_db_initialised.return_value = True
@ -553,79 +500,9 @@ class KeystoneRelationTests(CharmTestCase):
self.assertTrue(update.called)
self.assertTrue(mock_update_domains.called)
@patch.object(hooks, 'update_all_domain_backends')
@patch.object(hooks, 'update_all_identity_relation_units')
@patch.object(hooks, 'run_in_apache')
@patch.object(hooks, 'initialise_pki')
@patch.object(hooks, 'git_install_requested')
@patch.object(hooks, 'config_value_changed')
@patch('keystone_utils.log')
@patch('keystone_utils.ensure_ssl_cert_master')
@patch.object(hooks, 'ensure_ssl_dir')
@patch.object(hooks, 'send_ssl_sync_request')
@patch.object(hooks, 'is_db_initialised')
@patch.object(hooks, 'is_db_ready')
@patch.object(hooks, 'peer_units')
@patch.object(hooks, 'admin_relation_changed')
@patch.object(hooks, 'cluster_joined')
@patch.object(unison, 'ensure_user')
@patch.object(unison, 'get_homedir')
@patch.object(hooks, 'CONFIGS')
@patch.object(hooks, 'identity_changed')
@patch.object(hooks, 'configure_https')
def test_config_changed_git_updated(self, configure_https,
identity_changed,
configs, get_homedir, ensure_user,
cluster_joined, admin_relation_changed,
mock_peer_units,
mock_is_db_ready,
mock_is_db_initialised,
mock_send_ssl_sync_request,
mock_ensure_ssl_dir,
mock_ensure_ssl_cert_master,
mock_log, config_val_changed,
git_requested,
mock_initialise_pki,
mock_run_in_apache,
update,
mock_update_domains):
self.enable_memcache.return_value = False
mock_run_in_apache.return_value = False
git_requested.return_value = True
mock_ensure_ssl_cert_master.return_value = False
self.openstack_upgrade_available.return_value = False
self.is_elected_leader.return_value = True
mock_peer_units.return_value = []
self.relation_ids.return_value = ['identity-service:0']
self.related_units.return_value = ['unit/0']
repo = 'cloud:trusty-juno'
openstack_origin_git = {
'repositories': [
{'name': 'requirements',
'repository': 'git://git.openstack.org/openstack/requirements', # noqa
'branch': 'stable/juno'},
{'name': 'keystone',
'repository': 'git://git.openstack.org/openstack/keystone',
'branch': 'stable/juno'}
],
'directory': '/mnt/openstack-git',
}
projects_yaml = yaml.dump(openstack_origin_git)
self.test_config.set('openstack-origin', repo)
self.test_config.set('openstack-origin-git', projects_yaml)
hooks.config_changed()
self.git_install.assert_called_with(projects_yaml)
self.assertFalse(self.openstack_upgrade_available.called)
self.assertFalse(self.do_openstack_upgrade_reexec.called)
self.assertTrue(update.called)
self.assertTrue(mock_update_domains.called)
@patch.object(hooks, 'run_in_apache')
@patch.object(hooks, 'initialise_pki')
@patch.object(hooks, 'is_db_initialised')
@patch.object(hooks, 'git_install_requested')
@patch.object(hooks, 'config_value_changed')
@patch.object(hooks, 'ensure_ssl_dir')
@patch.object(hooks, 'configure_https')
@patch.object(hooks, 'is_ssl_cert_master')
@ -640,8 +517,6 @@ class KeystoneRelationTests(CharmTestCase):
peer_units, is_ssl,
config_https,
ensure_ssl_dir,
config_value_changed,
git_requested,
mock_db_init,
mock_initialise_pki,
mock_run_in_apache):
@ -650,7 +525,6 @@ class KeystoneRelationTests(CharmTestCase):
ensure_ssl_cert.return_value = False
peer_units.return_value = []
git_requested.return_value = False
self.openstack_upgrade_available.return_value = True
self.test_config.set('action-managed-upgrade', True)
@ -1044,7 +918,6 @@ class KeystoneRelationTests(CharmTestCase):
@patch.object(hooks, 'update_all_identity_relation_units')
@patch.object(utils, 'os_release')
@patch.object(utils, 'git_install_requested')
@patch.object(hooks, 'is_db_ready')
@patch.object(hooks, 'is_db_initialised')
@patch('keystone_utils.log')
@ -1063,7 +936,6 @@ class KeystoneRelationTests(CharmTestCase):
mock_log,
mock_is_db_initialised,
mock_is_db_ready,
git_requested,
os_release,
update):
os_release.return_value = 'havana'
@ -1078,7 +950,6 @@ class KeystoneRelationTests(CharmTestCase):
self.is_elected_leader.return_value = True
self.filter_installed_packages.return_value = []
git_requested.return_value = False
hooks.upgrade_charm()
self.assertTrue(self.apt_install.called)
ssh_authorized_peers.assert_called_with(
@ -1227,7 +1098,6 @@ class KeystoneRelationTests(CharmTestCase):
@patch.object(hooks, 'update_all_identity_relation_units')
@patch.object(utils, 'os_release')
@patch.object(utils, 'git_install_requested')
@patch('keystone_utils.log')
@patch('keystone_utils.relation_ids')
@patch('keystone_utils.ensure_ssl_cert_master')
@ -1237,7 +1107,7 @@ class KeystoneRelationTests(CharmTestCase):
mock_update_hash_from_path,
mock_ensure_ssl_cert_master,
mock_relation_ids,
mock_log, git_requested,
mock_log,
os_release, update):
os_release.return_value = 'havana'
mock_relation_ids.return_value = []
@ -1248,7 +1118,6 @@ class KeystoneRelationTests(CharmTestCase):
self.is_elected_leader.return_value = False
self.filter_installed_packages.return_value = []
git_requested.return_value = False
hooks.upgrade_charm()
self.assertTrue(self.apt_install.called)
ssh_authorized_peers.assert_called_with(

View File

@ -39,9 +39,6 @@ TO_PATCH = [
'get_requested_roles',
'get_service_password',
'get_os_codename_install_source',
'git_clone_and_install',
'git_pip_venv_dir',
'git_src_dir',
'grant_role',
'configure_installation_source',
'is_elected_leader',
@ -57,12 +54,10 @@ TO_PATCH = [
'relation_set',
'relation_ids',
'relation_id',
'render',
'local_unit',
'related_units',
'https',
'peer_store',
'pip_install',
# generic
'apt_update',
'apt_upgrade',
@ -75,15 +70,6 @@ TO_PATCH = [
'reset_os_release',
]
openstack_origin_git = \
"""repositories:
- {name: requirements,
repository: 'git://git.openstack.org/openstack/requirements',
branch: stable/juno}
- {name: keystone,
repository: 'git://git.openstack.org/openstack/keystone',
branch: stable/juno}"""
class TestKeystoneUtils(CharmTestCase):
@ -134,27 +120,21 @@ class TestKeystoneUtils(CharmTestCase):
]
self.assertEqual(fake_renderer.register.call_args_list, ex_reg)
@patch.object(utils, 'git_determine_usr_bin')
@patch.object(utils, 'snap_install_requested')
@patch.object(utils, 'os')
def test_resource_map_enable_memcache_mitaka(self, mock_os,
snap_install_requested,
git_determine_usr_bin):
snap_install_requested):
self.os_release.return_value = 'mitaka'
snap_install_requested.return_value = False
git_determine_usr_bin.return_value = '/usr/bin'
mock_os.path.exists.return_value = True
self.assertTrue('/etc/memcached.conf' in utils.resource_map().keys())
@patch.object(utils, 'git_determine_usr_bin')
@patch.object(utils, 'snap_install_requested')
@patch.object(utils, 'os')
def test_resource_map_enable_memcache_liberty(self, mock_os,
snap_install_requested,
git_determine_usr_bin):
snap_install_requested):
self.os_release.return_value = 'liberty'
snap_install_requested.return_value = False
git_determine_usr_bin.return_value = '/usr/bin'
mock_os.path.exists.return_value = True
self.assertFalse('/etc/memcached.conf' in utils.resource_map().keys())
@ -184,16 +164,6 @@ class TestKeystoneUtils(CharmTestCase):
'memcached']
self.assertEqual(set(ex), set(result))
@patch('charmhelpers.contrib.openstack.utils.config')
def test_determine_packages_git(self, _config):
self.os_release.return_value = 'havana'
_config.return_value = openstack_origin_git
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + utils.BASE_GIT_PACKAGES
for p in utils.GIT_PACKAGE_BLACKLIST:
ex.remove(p)
self.assertEqual(set(ex), set(result))
@patch('charmhelpers.contrib.openstack.utils.config')
def test_determine_packages_snap_install(self, _config):
self.os_release.return_value = 'mitaka'
@ -830,85 +800,6 @@ class TestKeystoneUtils(CharmTestCase):
self.assertFalse(utils.ensure_ssl_cert_master())
self.assertFalse(self.relation_set.called)
@patch.object(utils, 'git_install_requested')
@patch.object(utils, 'git_post_install')
@patch.object(utils, 'git_pre_install')
def test_git_install(self, git_requested, git_pre, git_post):
projects_yaml = openstack_origin_git
git_requested.return_value = True
utils.git_install(projects_yaml)
self.assertTrue(git_pre.called)
self.git_clone_and_install.assert_called_with(openstack_origin_git,
core_project='keystone')
self.assertTrue(git_post.called)
@patch.object(utils, 'mkdir')
@patch.object(utils, 'write_file')
@patch.object(utils, 'add_user_to_group')
@patch.object(utils, 'add_group')
@patch.object(utils, 'adduser')
def test_git_pre_install(self, adduser, add_group, add_user_to_group,
write_file, mkdir):
utils.git_pre_install()
adduser.assert_called_with('keystone', shell='/bin/bash',
system_user=True,
home_dir='/var/lib/keystone')
add_group.assert_called_with('keystone', system_group=True)
add_user_to_group.assert_called_with('keystone', 'keystone')
expected = [
call('/var/lib/keystone', owner='keystone',
group='keystone', perms=0755, force=False),
call('/var/lib/keystone/cache', owner='keystone',
group='keystone', perms=0755, force=False),
call('/var/log/keystone', owner='keystone',
group='keystone', perms=0755, force=False),
]
self.assertEqual(mkdir.call_args_list, expected)
write_file.assert_called_with('/var/log/keystone/keystone.log',
'', owner='keystone', group='keystone',
perms=0600)
@patch('os.path.join')
@patch('os.path.exists')
@patch('os.symlink')
@patch('shutil.copytree')
@patch('shutil.rmtree')
@patch('subprocess.check_call')
def test_git_post_install(self, check_call, rmtree, copytree, symlink,
exists, join):
self.os_release.return_value = 'havana'
projects_yaml = openstack_origin_git
join.return_value = 'joined-string'
self.git_pip_venv_dir.return_value = '/mnt/openstack-git/venv'
self.lsb_release.return_value = {'DISTRIB_RELEASE': '15.04'}
utils.git_post_install(projects_yaml)
expected = [
call('joined-string', '/etc/keystone'),
]
copytree.assert_has_calls(expected)
expected = [
call('joined-string', '/usr/local/bin/keystone-manage'),
]
symlink.assert_has_calls(expected, any_order=True)
keystone_context = {
'service_description': 'Keystone API server',
'service_name': 'Keystone',
'user_name': 'keystone',
'start_dir': '/var/lib/keystone',
'process_name': 'keystone',
'executable_name': 'joined-string',
'config_files': ['/etc/keystone/keystone.conf'],
'log_file': '/var/log/keystone/keystone.log',
}
expected = [
call('git/logging.conf', '/etc/keystone/logging.conf', {},
perms=0o644),
call('git.upstart', '/etc/init/keystone.conf',
keystone_context, perms=0o644, templates_dir='joined-string'),
]
self.assertEqual(self.render.call_args_list, expected)
self.service_restart.assert_called_with('keystone')
@patch.object(utils, 'get_manager')
def test_is_service_present(self, KeystoneManager):
mock_keystone = MagicMock()