Merge "Remove deploy from source support"

This commit is contained in:
Zuul 2018-01-12 14:50:18 +00:00 committed by Gerrit Code Review
commit f202d93c5b
19 changed files with 110 additions and 1258 deletions

View File

@ -1,5 +1,3 @@
git-reinstall:
description: Reinstall glance from the openstack-origin-git repositories.
openstack-upgrade:
description: Perform openstack upgrades. Config option action-managed-upgrade must be set to True.
pause:

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.glance_utils import (
git_install,
)
from hooks.glance_relations 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

@ -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

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

View File

@ -31,30 +31,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 glance repositories,
and may also include repositories for other dependencies:
repositories:
- {name: requirements,
repository: 'git://github.com/openstack/requirements',
branch: master}
- {name: glance,
repository: 'git://github.com/openstack/glance',
branch: master}
release: master
action-managed-upgrade:
type: boolean
default: False

View File

@ -23,7 +23,6 @@ from subprocess import (
from glance_utils import (
do_openstack_upgrade,
git_install,
migrate_database,
register_configs,
restart_map,
@ -80,9 +79,7 @@ from charmhelpers.contrib.openstack.ha.utils import (
update_dns_ha_resource_params,
)
from charmhelpers.contrib.openstack.utils import (
config_value_changed,
configure_installation_source,
git_install_requested,
lsb_release,
openstack_upgrade_available,
os_release,
@ -137,9 +134,6 @@ def install_hook():
apt_update(fatal=True)
apt_install(determine_packages(), fatal=True)
status_set('maintenance', 'Git install')
git_install(config('openstack-origin-git'))
for service in SERVICES:
service_stop(service)
@ -348,11 +342,7 @@ def config_changed():
sync_db_with_multi_ipv6_addresses(config('database'),
config('database-user'))
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('glance-common'):
status_set('maintenance', 'Upgrading OpenStack release')
do_openstack_upgrade(CONFIGS)

View File

@ -16,7 +16,6 @@
import json
import os
import shutil
import subprocess
from itertools import chain
@ -30,12 +29,7 @@ from charmhelpers.fetch import (
apt_install,
add_source)
from charmhelpers.contrib.python.packages import (
pip_install,
)
from charmhelpers.core.hookenv import (
charm_dir,
config,
log,
INFO,
@ -45,17 +39,12 @@ from charmhelpers.core.hookenv import (
from charmhelpers.core.host import (
adduser,
add_group,
add_user_to_group,
CompareHostReleases,
lsb_release,
mkdir,
pwgen,
service_stop,
service_start,
service_restart,
write_file,
)
from charmhelpers.contrib.openstack import (
@ -75,13 +64,6 @@ from charmhelpers.contrib.openstack.utils import (
incomplete_relation_data,
is_unit_paused_set,
get_os_codename_install_source,
git_clone_and_install,
git_default_repos,
git_generate_systemd_init_files,
git_install_requested,
git_pip_venv_dir,
git_src_dir,
git_yaml_value,
make_assess_status_func,
os_application_version_set,
os_release,
@ -92,8 +74,6 @@ from charmhelpers.contrib.openstack.utils import (
update_json_file,
)
from charmhelpers.core.templating import render
from charmhelpers.core.decorators import (
retry_on_exception,
)
@ -109,33 +89,11 @@ PACKAGES = [
VERSION_PACKAGE = 'glance-common'
BASE_GIT_PACKAGES = [
'libffi-dev',
'libmysqlclient-dev',
'libxml2-dev',
'libxslt1-dev',
'libssl-dev',
'libyaml-dev',
'openstack-pkg-tools',
'python-dev',
'python-pip',
'python-setuptools',
'zlib1g-dev',
]
SERVICES = [
"glance-api",
"glance-registry",
]
# ubuntu packages that should not be installed when deploying from git
GIT_PACKAGE_BLACKLIST = [
'glance',
'python-swiftclient',
'python-keystone',
]
CHARM = "glance"
GLANCE_CONF_DIR = "/etc/glance"
@ -274,11 +232,6 @@ def register_configs():
def determine_packages():
packages = set(PACKAGES)
if git_install_requested():
packages |= set(BASE_GIT_PACKAGES)
packages -= set(GIT_PACKAGE_BLACKLIST)
packages |= set(token_cache_pkgs(source=config('openstack-origin')))
return sorted(packages)
@ -373,128 +326,6 @@ def setup_ipv6():
apt_install('haproxy/trusty-backports', fatal=True)
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='glance')
git_post_install(projects_yaml)
def git_pre_install():
"""Perform glance pre-install setup."""
dirs = [
'/var/lib/glance',
'/var/lib/glance/images',
'/var/lib/glance/image-cache',
'/var/lib/glance/image-cache/incomplete',
'/var/lib/glance/image-cache/invalid',
'/var/lib/glance/image-cache/queue',
'/var/log/glance',
]
logs = [
'/var/log/glance/glance-api.log',
'/var/log/glance/glance-registry.log',
]
adduser('glance', shell='/bin/bash', system_user=True)
add_group('glance', system_group=True)
add_user_to_group('glance', 'glance')
for d in dirs:
mkdir(d, owner='glance', group='glance', perms=0755, force=False)
for l in logs:
write_file(l, '', owner='glance', group='glance', perms=0600)
def git_post_install(projects_yaml):
"""Perform glance post-install setup."""
http_proxy = git_yaml_value(projects_yaml, 'http_proxy')
if http_proxy:
for pkg in ['mysql-python', 'python-cephlibs']:
pip_install(pkg, proxy=http_proxy,
venv=git_pip_venv_dir(projects_yaml))
else:
for pkg in ['mysql-python', 'python-cephlibs']:
pip_install(pkg, venv=git_pip_venv_dir(projects_yaml))
src_etc = os.path.join(git_src_dir(projects_yaml, 'glance'), 'etc')
configs = {
'src': src_etc,
'dest': GLANCE_CONF_DIR,
}
if os.path.exists(configs['dest']):
shutil.rmtree(configs['dest'])
shutil.copytree(configs['src'], configs['dest'])
symlinks = [
# NOTE(coreycb): Need to find better solution than bin symlinks.
{'src': os.path.join(git_pip_venv_dir(projects_yaml),
'bin/glance-manage'),
'link': '/usr/local/bin/glance-manage'},
]
for s in symlinks:
if os.path.lexists(s['link']):
os.remove(s['link'])
os.symlink(s['src'], s['link'])
bin_dir = os.path.join(git_pip_venv_dir(projects_yaml), 'bin')
# Use systemd init units/scripts from ubuntu wily onward
if lsb_release()['DISTRIB_RELEASE'] >= '15.10':
templates_dir = os.path.join(charm_dir(), TEMPLATES, 'git')
daemons = ['glance-api', 'glance-glare', 'glance-registry']
for daemon in daemons:
glance_context = {
'daemon_path': os.path.join(bin_dir, daemon),
}
template_file = 'git/{}.init.in.template'.format(daemon)
init_in_file = '{}.init.in'.format(daemon)
render(template_file, os.path.join(templates_dir, init_in_file),
glance_context, perms=0o644)
git_generate_systemd_init_files(templates_dir)
else:
glance_api_context = {
'service_description': 'Glance API server',
'service_name': 'Glance',
'user_name': 'glance',
'start_dir': '/var/lib/glance',
'process_name': 'glance-api',
'executable_name': os.path.join(bin_dir, 'glance-api'),
'config_files': [GLANCE_API_CONF],
'log_file': '/var/log/glance/api.log',
}
glance_registry_context = {
'service_description': 'Glance registry server',
'service_name': 'Glance',
'user_name': 'glance',
'start_dir': '/var/lib/glance',
'process_name': 'glance-registry',
'executable_name': os.path.join(bin_dir, 'glance-registry'),
'config_files': [GLANCE_REGISTRY_CONF],
'log_file': '/var/log/glance/registry.log',
}
templates_dir = 'hooks/charmhelpers/contrib/openstack/templates'
templates_dir = os.path.join(charm_dir(), templates_dir)
render('git.upstart', '/etc/init/glance-api.conf',
glance_api_context, perms=0o644,
templates_dir=templates_dir)
render('git.upstart', '/etc/init/glance-registry.conf',
glance_registry_context, perms=0o644,
templates_dir=templates_dir)
# Don't restart services if the unit is supposed to be paused.
if not is_unit_paused_set():
service_restart('glance-api')
service_restart('glance-registry')
def get_optional_interfaces():
"""Return the optional interfaces that should be checked if the relavent
relations have appeared.

View File

@ -1,21 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: glance-api
# Required-Start: $network $local_fs $remote_fs $syslog
# Required-Stop: $remote_fs
# Should-Start: postgresql mysql keystone ntp rabbitmq-server
# Should-Stop: postgresql mysql keystone ntp rabbitmq-server
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Glance API server
# Description: Frontend Glance API server
### END INIT INFO
# Author: Julien Danjou <acid@debian.org>
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="OpenStack Image Service API"
PROJECT_NAME=glance
NAME=${PROJECT_NAME}-api
CONFIG_FILE=/etc/${PROJECT_NAME}/${NAME}.conf
DAEMON={{ daemon_path }}

View File

@ -1,21 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: glance-glare
# Required-Start: $network $local_fs $remote_fs $syslog
# Required-Stop: $remote_fs
# Should-Start: postgresql mysql keystone ntp rabbitmq-server
# Should-Stop: postgresql mysql keystone ntp rabbitmq-server
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Glance Artifact Repository API
# Description: Frontend Glance Artifact Repository API
### END INIT INFO
# Author: Corey Bryant <corey.bryant@canonical.com>
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="OpenStack Glance Artifact Repository API"
PROJECT_NAME=glance
NAME=${PROJECT_NAME}-glare
CONFIG_FILE=/etc/${PROJECT_NAME}/${NAME}.conf
DAEMON={{ daemon_path }}

View File

@ -1,21 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: glance-registry
# Required-Start: $network $local_fs $remote_fs $syslog
# Required-Stop: $remote_fs
# Should-Start: postgresql mysql keystone ntp rabbitmq-server
# Should-Stop: postgresql mysql keystone ntp rabbitmq-server
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Glance registry server
# Description: Frontend Glance registry server
### END INIT INFO
# Author: Julien Danjou <acid@debian.org>
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="OpenStack Image Service Registry"
PROJECT_NAME=glance
NAME=${PROJECT_NAME}-registry
CONFIG_FILE=/etc/${PROJECT_NAME}/${NAME}.conf
DAEMON={{ daemon_path }}

View File

@ -19,9 +19,7 @@ Basic glance amulet functional tests.
"""
import amulet
import os
import time
import yaml
from charmhelpers.contrib.openstack.amulet.deployment import (
OpenStackAmuletDeployment
@ -44,12 +42,11 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
SERVICES = ('apache2', 'haproxy', 'glance-api', 'glance-registry')
def __init__(self, series=None, openstack=None, source=None, git=False,
def __init__(self, series=None, openstack=None, source=None,
stable=False):
"""Deploy the entire test environment."""
super(GlanceBasicDeployment, self).__init__(series, openstack,
source, stable)
self.git = git
self._add_services()
self._add_relations()
self._configure_services()
@ -94,33 +91,6 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
def _configure_services(self):
"""Configure all of the services."""
glance_config = {}
if self.git:
amulet_http_proxy = os.environ.get('AMULET_HTTP_PROXY')
reqs_repo = 'git://github.com/openstack/requirements'
glance_repo = 'git://github.com/openstack/glance'
if self._get_openstack_release() == self.trusty_icehouse:
reqs_repo = 'git://github.com/coreycb/requirements'
glance_repo = 'git://github.com/coreycb/glance'
branch = 'stable/' + self._get_openstack_release_string()
openstack_origin_git = {
'repositories': [
{'name': 'requirements',
'repository': reqs_repo,
'branch': branch},
{'name': 'glance',
'repository': glance_repo,
'branch': branch},
],
'directory': '/mnt/openstack-git',
'http_proxy': amulet_http_proxy,
'https_proxy': amulet_http_proxy,
}
glance_config['openstack-origin-git'] = \
yaml.dump(openstack_origin_git)
keystone_config = {
'admin-password': 'openstack',
'admin-token': 'ubuntutesting',

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 Glance git deployment on trusty-icehouse."""
from basic_deployment import GlanceBasicDeployment
if __name__ == '__main__':
deployment = GlanceBasicDeployment(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 Glance git deployment on trusty-kilo."""
from basic_deployment import GlanceBasicDeployment
if __name__ == '__main__':
deployment = GlanceBasicDeployment(series='trusty',
openstack='cloud:trusty-kilo',
source='cloud:trusty-updates/kilo',
git=True)
deployment.run_tests()

View File

@ -1,118 +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 os
import sys
from mock import patch, MagicMock
from test_utils import CharmTestCase
# python-apt is not installed as part of test-requirements but is imported by
# some charmhelpers modules so create a fake import.
sys.modules['apt'] = MagicMock()
sys.modules['apt_pkg'] = MagicMock()
os.environ['JUJU_UNIT_NAME'] = 'glance'
with patch('actions.hooks.charmhelpers.contrib.hardening.harden.harden') as \
mock_dec:
mock_dec.side_effect = (lambda *dargs, **dkwargs: lambda f:
lambda *args, **kwargs: f(*args, **kwargs))
with patch('actions.hooks.charmhelpers.core.hookenv.config') as config:
with patch('actions.hooks.glance_utils.register_configs'):
with patch('actions.hooks.glance_utils.restart_map'):
from actions import git_reinstall
TO_PATCH = [
'config',
'git_install_requested',
]
openstack_origin_git = \
"""repositories:
- {name: requirements,
repository: 'git://git.openstack.org/openstack/requirements',
branch: stable/juno}
- {name: glance,
repository: 'git://git.openstack.org/openstack/glance',
branch: stable/juno}"""
class TestGlanceActions(CharmTestCase):
def setUp(self):
super(TestGlanceActions, self).setUp(git_reinstall, TO_PATCH)
self.config.side_effect = self.test_config.get
self.git_install_requested.return_value = True
@patch.object(git_reinstall, 'action_set')
@patch.object(git_reinstall, 'action_fail')
@patch.object(git_reinstall, 'git_install')
@patch.object(git_reinstall, 'config_changed')
def test_git_reinstall(self, 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')
def test_git_reinstall_not_configured(self, config_changed, git_install,
action_fail, action_set):
config.return_value = None
self.git_install_requested.return_value = False
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')
def test_git_reinstall_exception(self, 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

@ -27,6 +27,7 @@ mock_apt.apt_pkg = MagicMock()
with patch('actions.hooks.glance_utils.register_configs'):
with patch('hooks.glance_utils.register_configs'):
with patch('actions.hooks.glance_utils.restart_map'):
from actions import openstack_upgrade
from test_utils import CharmTestCase
@ -45,14 +46,12 @@ class TestGlanceUpgradeActions(CharmTestCase):
@patch('actions.charmhelpers.contrib.openstack.utils.config')
@patch('actions.charmhelpers.contrib.openstack.utils.action_set')
@patch('actions.charmhelpers.contrib.openstack.utils.git_install_requested') # noqa
@patch('actions.charmhelpers.contrib.openstack.utils.openstack_upgrade_available') # noqa
@patch('actions.charmhelpers.contrib.openstack.utils.juju_log')
@patch('subprocess.check_output')
def test_openstack_upgrade_true(self, _check_output, log, upgrade_avail,
git_requested, action_set, config):
action_set, config):
_check_output.return_value = 'null'
git_requested.return_value = False
upgrade_avail.return_value = True
config.return_value = True
@ -63,14 +62,12 @@ class TestGlanceUpgradeActions(CharmTestCase):
@patch('actions.charmhelpers.contrib.openstack.utils.config')
@patch('actions.charmhelpers.contrib.openstack.utils.action_set')
@patch('actions.charmhelpers.contrib.openstack.utils.git_install_requested') # noqa
@patch('actions.charmhelpers.contrib.openstack.utils.openstack_upgrade_available') # noqa
@patch('actions.charmhelpers.contrib.openstack.utils.juju_log')
@patch('subprocess.check_output')
def test_openstack_upgrade_false(self, _check_output, log, upgrade_avail,
git_requested, action_set, config):
action_set, config):
_check_output.return_value = 'null'
git_requested.return_value = False
upgrade_avail.return_value = True
config.return_value = False

View File

@ -14,7 +14,6 @@
import os
import sys
import yaml
from mock import call, patch, MagicMock
from test_utils import CharmTestCase
@ -83,7 +82,6 @@ TO_PATCH = [
'migrate_database',
'ensure_ceph_keyring',
'ceph_config_file',
'git_install',
'update_nrpe_config',
'reinstall_paste_ini',
# other
@ -109,10 +107,8 @@ class GlanceRelationTests(CharmTestCase):
@patch.object(utils, 'config')
@patch.object(utils, 'token_cache_pkgs')
@patch.object(utils, 'git_install_requested')
def test_install_hook(self, git_requested, token_cache_pkgs, util_config):
def test_install_hook(self, token_cache_pkgs, util_config):
token_cache_pkgs.return_value = ['memcached']
git_requested.return_value = False
repo = 'cloud:precise-grizzly'
self.test_config.set('openstack-origin', repo)
self.service_stop.return_value = True
@ -124,15 +120,12 @@ class GlanceRelationTests(CharmTestCase):
'python-mysqldb', 'python-psycopg2', 'python-six',
'python-swiftclient', 'uuid'], fatal=True)
self.assertTrue(self.execd_preinstall.called)
self.git_install.assert_called_with(None)
@patch.object(utils, 'config')
@patch.object(utils, 'token_cache_pkgs')
@patch.object(utils, 'git_install_requested')
def test_install_hook_precise_distro(self, git_requested, token_cache_pkgs,
def test_install_hook_precise_distro(self, token_cache_pkgs,
util_config):
token_cache_pkgs.return_value = []
git_requested.return_value = False
self.test_config.set('openstack-origin', 'distro')
self.lsb_release.return_value = {'DISTRIB_RELEASE': 12.04,
'DISTRIB_CODENAME': 'precise'}
@ -142,39 +135,6 @@ class GlanceRelationTests(CharmTestCase):
"cloud:precise-folsom"
)
@patch.object(utils, 'config')
@patch.object(utils, 'token_cache_pkgs')
@patch.object(utils, 'git_install_requested')
def test_install_hook_git(self, git_requested, token_cache_pkgs,
util_config):
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': 'glance',
'repository': 'git://git.openstack.org/openstack/glance',
'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)
relations.install_hook()
self.assertTrue(self.execd_preinstall.called)
self.configure_installation_source.assert_called_with(repo)
self.apt_update.assert_called_with(fatal=True)
self.apt_install.assert_called_with(
['apache2', 'haproxy', 'libffi-dev', 'libmysqlclient-dev',
'libssl-dev', 'libxml2-dev', 'libxslt1-dev', 'libyaml-dev',
'openstack-pkg-tools', 'python-dev', 'python-mysqldb',
'python-pip', 'python-psycopg2', 'python-setuptools',
'python-six', 'uuid', 'zlib1g-dev'], fatal=True)
self.git_install.assert_called_with(projects_yaml)
def test_db_joined(self):
self.get_relation_ip.return_value = '10.0.0.1'
relations.db_joined()
@ -508,13 +468,11 @@ class GlanceRelationTests(CharmTestCase):
@patch.object(relations, 'configure_https')
@patch.object(relations, 'object_store_joined')
@patch.object(relations, 'CONFIGS')
@patch.object(utils, 'git_install_requested')
def test_keystone_changed_with_object_store_relation(self, git_requested,
def test_keystone_changed_with_object_store_relation(self,
configs,
object_store_joined,
configure_https,
image_service_joined):
git_requested.return_value = False
configs.complete_contexts = MagicMock()
configs.complete_contexts.return_value = ['identity-service']
configs.write = MagicMock()
@ -546,11 +504,9 @@ class GlanceRelationTests(CharmTestCase):
@patch.object(relations, 'update_image_location_policy')
@patch.object(relations, 'configure_https')
@patch.object(relations, 'git_install_requested')
def test_config_changed_no_openstack_upgrade(self, git_requested,
def test_config_changed_no_openstack_upgrade(self,
configure_https,
mock_update_policy):
git_requested.return_value = False
self.openstack_upgrade_available.return_value = False
relations.config_changed()
self.open_port.assert_called_with(9292)
@ -560,12 +516,10 @@ class GlanceRelationTests(CharmTestCase):
@patch.object(relations, 'update_image_location_policy')
@patch.object(relations, 'status_set')
@patch.object(relations, 'configure_https')
@patch.object(relations, 'git_install_requested')
def test_config_changed_with_openstack_upgrade(self, git_requested,
def test_config_changed_with_openstack_upgrade(self,
configure_https,
status,
mock_update_policy):
git_requested.return_value = False
self.openstack_upgrade_available.return_value = True
relations.config_changed()
status.assert_called_with(
@ -577,10 +531,8 @@ class GlanceRelationTests(CharmTestCase):
self.assertTrue(mock_update_policy.called)
@patch.object(relations, 'update_image_location_policy')
@patch.object(relations, 'git_install_requested')
def test_config_changed_with_openstack_upgrade_action(self, git_requested,
def test_config_changed_with_openstack_upgrade_action(self,
mock_update_policy):
git_requested.return_value = False
self.openstack_upgrade_available.return_value = True
self.test_config.set('action-managed-upgrade', True)
@ -588,35 +540,6 @@ class GlanceRelationTests(CharmTestCase):
self.assertFalse(self.do_openstack_upgrade.called)
self.assertTrue(mock_update_policy.called)
@patch.object(relations, 'update_image_location_policy')
@patch.object(relations, 'configure_https')
@patch.object(relations, 'git_install_requested')
@patch.object(relations, 'config_value_changed')
def test_config_changed_git_updated(self, config_val_changed,
git_requested, configure_https,
mock_update_image_location_policy):
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': 'glance',
'repository': 'git://git.openstack.org/openstack/glance',
'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)
relations.config_changed()
self.git_install.assert_called_with(projects_yaml)
self.assertFalse(self.do_openstack_upgrade.called)
self.assertTrue(configure_https.called)
self.assertTrue(mock_update_image_location_policy.called)
@patch.object(relations, 'CONFIGS')
def test_cluster_changed(self, configs):
self.test_config.set('prefer-ipv6', False)
@ -648,10 +571,8 @@ class GlanceRelationTests(CharmTestCase):
@patch.object(utils, 'config')
@patch.object(utils, 'token_cache_pkgs')
@patch.object(relations, 'CONFIGS')
@patch.object(utils, 'git_install_requested')
def test_upgrade_charm(self, git_requested, configs, token_cache_pkgs,
def test_upgrade_charm(self, configs, token_cache_pkgs,
util_config, mock_update_image_location_policy):
git_requested.return_value = False
self.filter_installed_packages.return_value = ['test']
relations.upgrade_charm()
self.apt_install.assert_called_with(['test'], fatal=True)

View File

@ -36,13 +36,8 @@ TO_PATCH = [
'apt_update',
'apt_upgrade',
'apt_install',
'git_pip_venv_dir',
'git_src_dir',
'mkdir',
'os_release',
'pip_install',
'render',
'service_restart',
'service_start',
'service_stop',
'service_name',
@ -58,15 +53,6 @@ DPKG_OPTS = [
'--option', 'Dpkg::Options::=--force-confdef',
]
openstack_origin_git = \
"""repositories:
- {name: requirements,
repository: 'git://git.openstack.org/openstack/requirements',
branch: stable/juno}
- {name: glance,
repository: 'git://git.openstack.org/openstack/glance',
branch: stable/juno}"""
class TestGlanceUtils(CharmTestCase):
@ -154,33 +140,17 @@ class TestGlanceUtils(CharmTestCase):
self.assertEqual(ex_map, utils.restart_map())
@patch.object(utils, 'token_cache_pkgs')
@patch.object(utils, 'git_install_requested')
def test_determine_packages(self, git_install_requested, token_cache_pkgs):
def test_determine_packages(self, token_cache_pkgs):
self.config.side_effect = None
token_cache_pkgs.return_value = []
git_install_requested.return_value = False
ex = utils.PACKAGES
self.assertEqual(set(ex), set(utils.determine_packages()))
token_cache_pkgs.return_value = ['memcached']
ex.append('memcached')
self.assertEqual(set(ex), set(utils.determine_packages()))
@patch.object(utils, 'token_cache_pkgs')
@patch.object(utils, 'git_install_requested')
def test_determine_packages_git(self, git_install_requested,
token_cache_pkgs):
self.config.side_effect = None
git_install_requested.return_value = True
result = utils.determine_packages()
ex = utils.PACKAGES + utils.BASE_GIT_PACKAGES
for p in utils.GIT_PACKAGE_BLACKLIST:
ex.remove(p)
self.assertEqual(set(ex), set(result))
@patch.object(utils, 'migrate_database')
@patch.object(utils, 'git_install_requested')
def test_openstack_upgrade_leader(self, git_requested, migrate):
git_requested.return_value = True
def test_openstack_upgrade_leader(self, migrate):
self.config.side_effect = None
self.config.return_value = 'cloud:precise-havana'
self.is_elected_leader.return_value = True
@ -196,9 +166,7 @@ class TestGlanceUtils(CharmTestCase):
self.assertTrue(migrate.called)
@patch.object(utils, 'migrate_database')
@patch.object(utils, 'git_install_requested')
def test_openstack_upgrade_not_leader(self, git_requested, migrate):
git_requested.return_value = True
def test_openstack_upgrade_not_leader(self, migrate):
self.config.side_effect = None
self.config.return_value = 'cloud:precise-havana'
self.is_elected_leader.return_value = False
@ -213,140 +181,6 @@ class TestGlanceUtils(CharmTestCase):
configs.set_release.assert_called_with(openstack_release='havana')
self.assertFalse(migrate.called)
@patch.object(utils, 'git_install_requested')
@patch.object(utils, 'git_clone_and_install')
@patch.object(utils, 'git_post_install')
@patch.object(utils, 'git_pre_install')
def test_git_install(self, git_pre, git_post, git_clone_and_install,
git_requested):
projects_yaml = openstack_origin_git
git_requested.return_value = True
utils.git_install(projects_yaml)
self.assertTrue(git_pre.called)
git_clone_and_install.assert_called_with(openstack_origin_git,
core_project='glance')
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('glance', shell='/bin/bash',
system_user=True)
add_group.assert_called_with('glance', system_group=True)
add_user_to_group.assert_called_with('glance', 'glance')
expected = [
call('/var/lib/glance', owner='glance',
group='glance', perms=0755, force=False),
call('/var/lib/glance/images', owner='glance',
group='glance', perms=0755, force=False),
call('/var/lib/glance/image-cache', owner='glance',
group='glance', perms=0755, force=False),
call('/var/lib/glance/image-cache/incomplete', owner='glance',
group='glance', perms=0755, force=False),
call('/var/lib/glance/image-cache/invalid', owner='glance',
group='glance', perms=0755, force=False),
call('/var/lib/glance/image-cache/queue', owner='glance',
group='glance', perms=0755, force=False),
call('/var/log/glance', owner='glance',
group='glance', perms=0755, force=False),
]
self.assertEqual(mkdir.call_args_list, expected)
expected = [
call('/var/log/glance/glance-api.log', '', owner='glance',
group='glance', perms=0600),
call('/var/log/glance/glance-registry.log', '', owner='glance',
group='glance', perms=0600),
]
self.assertEqual(write_file.call_args_list, expected)
@patch('os.path.join')
@patch('os.path.exists')
@patch('os.remove')
@patch('os.symlink')
@patch('shutil.copytree')
@patch('shutil.rmtree')
@patch('subprocess.check_call')
def test_git_post_install_upstart(self, check_call, rmtree, copytree,
symlink, remove, exists, join):
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/glance'),
]
copytree.assert_has_calls(expected)
expected = [
call('joined-string', '/usr/local/bin/glance-manage'),
]
symlink.assert_has_calls(expected, any_order=True)
glance_api_context = {
'service_description': 'Glance API server',
'service_name': 'Glance',
'user_name': 'glance',
'start_dir': '/var/lib/glance',
'process_name': 'glance-api',
'executable_name': 'joined-string',
'config_files': ['/etc/glance/glance-api.conf'],
'log_file': '/var/log/glance/api.log',
}
glance_registry_context = {
'service_description': 'Glance registry server',
'service_name': 'Glance',
'user_name': 'glance',
'start_dir': '/var/lib/glance',
'process_name': 'glance-registry',
'executable_name': 'joined-string',
'config_files': ['/etc/glance/glance-registry.conf'],
'log_file': '/var/log/glance/registry.log',
}
expected = [
call('git.upstart', '/etc/init/glance-api.conf',
glance_api_context, perms=0o644,
templates_dir='joined-string'),
call('git.upstart', '/etc/init/glance-registry.conf',
glance_registry_context, perms=0o644,
templates_dir='joined-string'),
]
self.assertEqual(self.render.call_args_list, expected)
expected = [
call('glance-api'),
call('glance-registry'),
]
self.assertEqual(self.service_restart.call_args_list, expected)
@patch.object(utils, 'services')
@patch('os.listdir')
@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_systemd(self, check_call, rmtree, copytree,
symlink, exists, join, listdir,
services):
projects_yaml = openstack_origin_git
join.return_value = 'joined-string'
self.lsb_release.return_value = {'DISTRIB_RELEASE': '15.10'}
utils.git_post_install(projects_yaml)
expected = [
call('git/glance-api.init.in.template', 'joined-string',
{'daemon_path': 'joined-string'}, perms=420),
call('git/glance-glare.init.in.template', 'joined-string',
{'daemon_path': 'joined-string'}, perms=420),
call('git/glance-registry.init.in.template', 'joined-string',
{'daemon_path': 'joined-string'}, perms=420),
]
self.assertEqual(self.render.call_args_list, expected)
def test_assess_status(self):
with patch.object(utils, 'assess_status_func') as asf:
callee = MagicMock()