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: Icd464e950c6f53470311e3c110b530a69bff6e2f
This commit is contained in:
James Page 2018-01-08 12:37:06 +00:00
parent 46f0b43dd3
commit 4ea9d6a427
25 changed files with 122 additions and 1481 deletions

View File

@ -107,9 +107,6 @@ Users should be aware of three options, in particular:
openstack-origin: Allows Cinder to be installed from a specific apt repository. openstack-origin: Allows Cinder to be installed from a specific apt repository.
See config.yaml for a list of supported sources. See config.yaml for a list of supported sources.
openstack-origin-git: Allows Cinder to be installed from source.
See config.yaml for a list of supported sources.
block-device: When using local storage, a block device should be specified to block-device: When using local storage, a block device should be specified to
back a LVM volume group. It's important this device exists on back a LVM volume group. It's important this device exists on
all nodes that the service may be deployed to. all nodes that the service may be deployed to.

View File

@ -2,8 +2,6 @@ pause:
description: Pause the cinder unit. This action will stop cinder services. description: Pause the cinder unit. This action will stop cinder services.
resume: resume:
descrpition: Resume the cinder unit. This action will start cinder services. descrpition: Resume the cinder unit. This action will start cinder services.
git-reinstall:
description: Reinstall cinder from the openstack-origin-git repositories.
openstack-upgrade: openstack-upgrade:
description: Perform openstack upgrades. Config option action-managed-upgrade must be set to True. description: Perform openstack upgrades. Config option action-managed-upgrade must be set to True.
remove-services: remove-services:

View File

@ -1,60 +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 sys
import traceback
sys.path.append('hooks/')
from charmhelpers.contrib.openstack.utils import (
git_install_requested,
)
from charmhelpers.core.hookenv import (
action_set,
action_fail,
config,
)
from cinder_utils import (
git_install,
)
from cinder_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

@ -31,30 +31,6 @@ options:
NOTE: updating this setting to a source that is known to provide NOTE: updating this setting to a source that is known to provide
a later version of OpenStack will trigger a software upgrade unless a later version of OpenStack will trigger a software upgrade unless
action-managed-upgrade is set to True. 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 cinder repositories,
and may also include repositories for other dependencies:
repositories:
- {name: requirements,
repository: 'git://github.com/openstack/requirements',
branch: master}
- {name: cinder,
repository: 'git://github.com/openstack/cinder',
branch: master}
release: master
action-managed-upgrade: action-managed-upgrade:
type: boolean type: boolean
default: False default: False

View File

@ -97,8 +97,6 @@ from charmhelpers.contrib.network.ip import (
from charmhelpers.contrib.openstack.utils import ( from charmhelpers.contrib.openstack.utils import (
config_flags_parser, config_flags_parser,
get_host_ip, get_host_ip,
git_determine_usr_bin,
git_determine_python_path,
enable_memcache, enable_memcache,
snap_install_requested, snap_install_requested,
CompareOpenStackReleases, CompareOpenStackReleases,
@ -334,10 +332,7 @@ class IdentityServiceContext(OSContextGenerator):
self.rel_name = rel_name self.rel_name = rel_name
self.interfaces = [self.rel_name] self.interfaces = [self.rel_name]
def __call__(self): def _setup_pki_cache(self):
log('Generating template context for ' + self.rel_name, level=DEBUG)
ctxt = {}
if self.service and self.service_user: if self.service and self.service_user:
# This is required for pki token signing if we don't want /tmp to # This is required for pki token signing if we don't want /tmp to
# be used. # be used.
@ -347,6 +342,15 @@ class IdentityServiceContext(OSContextGenerator):
mkdir(path=cachedir, owner=self.service_user, mkdir(path=cachedir, owner=self.service_user,
group=self.service_user, perms=0o700) 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 ctxt['signing_dir'] = cachedir
for rid in relation_ids(self.rel_name): for rid in relation_ids(self.rel_name):
@ -385,6 +389,62 @@ class IdentityServiceContext(OSContextGenerator):
return {} 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): class AMQPContext(OSContextGenerator):
def __init__(self, ssl_dir=None, rel_name='amqp', relation_prefix=None): 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 * "public_processes": int(math.ceil(self.public_process_weight *
total_processes)), total_processes)),
"threads": 1, "threads": 1,
"usr_bin": git_determine_usr_bin(),
"python_path": git_determine_python_path(),
} }
return ctxt return ctxt

View File

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

View File

@ -23,7 +23,6 @@ import sys
import re import re
import itertools import itertools
import functools import functools
import shutil
import six import six
import traceback import traceback
@ -47,7 +46,6 @@ from charmhelpers.core.hookenv import (
related_units, related_units,
relation_ids, relation_ids,
relation_set, relation_set,
service_name,
status_set, status_set,
hook_name, hook_name,
application_version_set, application_version_set,
@ -68,11 +66,6 @@ from charmhelpers.contrib.network.ip import (
port_has_listener, port_has_listener,
) )
from charmhelpers.contrib.python.packages import (
pip_create_virtualenv,
pip_install,
)
from charmhelpers.core.host import ( from charmhelpers.core.host import (
lsb_release, lsb_release,
mounts, mounts,
@ -84,7 +77,6 @@ from charmhelpers.core.host import (
) )
from charmhelpers.fetch import ( from charmhelpers.fetch import (
apt_cache, apt_cache,
install_remote,
import_key as fetch_import_key, import_key as fetch_import_key,
add_source as fetch_add_source, add_source as fetch_add_source,
SourceConfigError, 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' DEFAULT_LOOPBACK_SIZE = '5G'
@ -530,7 +501,6 @@ def os_release(package, base='essex', reset_cache=False):
if _os_rel: if _os_rel:
return _os_rel return _os_rel
_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_package(package, fatal=False) or
get_os_codename_install_source(config('openstack-origin')) or get_os_codename_install_source(config('openstack-origin')) or
base) base)
@ -771,417 +741,6 @@ def os_requires_version(ostack_release, pkg):
return wrap 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): def os_workload_status(configs, required_interfaces, charm_func=None):
""" """
Decorator to set workload status based on complete contexts Decorator to set workload status based on complete contexts
@ -1615,27 +1174,24 @@ def do_action_openstack_upgrade(package, upgrade_callback, configs):
""" """
ret = False ret = False
if git_install_requested(): if openstack_upgrade_available(package):
action_set({'outcome': 'installed from source, skipped upgrade.'}) if config('action-managed-upgrade'):
else: juju_log('Upgrading OpenStack release')
if openstack_upgrade_available(package):
if config('action-managed-upgrade'):
juju_log('Upgrading OpenStack release')
try: try:
upgrade_callback(configs=configs) upgrade_callback(configs=configs)
action_set({'outcome': 'success, upgrade completed.'}) action_set({'outcome': 'success, upgrade completed.'})
ret = True ret = True
except Exception: except Exception:
action_set({'outcome': 'upgrade failed, see traceback.'}) action_set({'outcome': 'upgrade failed, see traceback.'})
action_set({'traceback': traceback.format_exc()}) action_set({'traceback': traceback.format_exc()})
action_fail('do_openstack_upgrade resulted in an ' action_fail('do_openstack_upgrade resulted in an '
'unexpected error') 'unexpected error')
else:
action_set({'outcome': 'action-managed-upgrade config is '
'False, skipped upgrade.'})
else: 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 return ret

View File

@ -113,7 +113,7 @@ def validator(value, valid_type, valid_range=None):
assert isinstance(valid_range, list), \ assert isinstance(valid_range, list), \
"valid_range must be a list, was given {}".format(valid_range) "valid_range must be a list, was given {}".format(valid_range)
# If we're dealing with strings # If we're dealing with strings
if valid_type is six.string_types: if isinstance(value, six.string_types):
assert value in valid_range, \ assert value in valid_range, \
"{} is not in the list {}".format(value, valid_range) "{} is not in the list {}".format(value, valid_range)
# Integer, float should have a min and max # Integer, float should have a min and max
@ -517,7 +517,8 @@ def pool_set(service, pool_name, key, value):
:param value: :param value:
:return: None. Can raise CalledProcessError :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: try:
check_call(cmd) check_call(cmd)
except CalledProcessError: except CalledProcessError:
@ -621,16 +622,24 @@ def create_erasure_profile(service, profile_name, erasure_plugin_name='jerasure'
:param durability_estimator: int :param durability_estimator: int
:return: None. Can raise CalledProcessError :return: None. Can raise CalledProcessError
""" """
version = ceph_version()
# Ensure this failure_domain is allowed by Ceph # Ensure this failure_domain is allowed by Ceph
validator(failure_domain, six.string_types, validator(failure_domain, six.string_types,
['chassis', 'datacenter', 'host', 'osd', 'pdu', 'pod', 'rack', 'region', 'room', 'root', 'row']) ['chassis', 'datacenter', 'host', 'osd', 'pdu', 'pod', 'rack', 'region', 'room', 'root', 'row'])
cmd = ['ceph', '--id', service, 'osd', 'erasure-code-profile', 'set', profile_name, cmd = ['ceph', '--id', service, 'osd', 'erasure-code-profile', 'set', profile_name,
'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks), 'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks)
'ruleset_failure_domain=' + failure_domain] ]
if locality is not None and durability_estimator is not None: 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.") 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 # Add plugin specific information
if locality is not None: if locality is not None:
# For local erasure codes # For local erasure codes

View File

@ -26,7 +26,6 @@ from cinder_utils import (
determine_packages, determine_packages,
disable_package_apache_site, disable_package_apache_site,
do_openstack_upgrade, do_openstack_upgrade,
git_install,
juju_log, juju_log,
migrate_database, migrate_database,
configure_lvm_storage, configure_lvm_storage,
@ -78,7 +77,6 @@ from charmhelpers.core.host import (
from charmhelpers.contrib.openstack.utils import ( from charmhelpers.contrib.openstack.utils import (
config_value_changed, config_value_changed,
configure_installation_source, configure_installation_source,
git_install_requested,
openstack_upgrade_available, openstack_upgrade_available,
sync_db_with_multi_ipv6_addresses, sync_db_with_multi_ipv6_addresses,
os_release, os_release,
@ -145,9 +143,6 @@ def install():
if run_in_apache(): if run_in_apache():
disable_package_apache_site() disable_package_apache_site()
status_set('maintenance', 'Git install')
git_install(config('openstack-origin-git'))
@hooks.hook('config-changed') @hooks.hook('config-changed')
@restart_on_change(restart_map(), stopstart=True) @restart_on_change(restart_map(), stopstart=True)
@ -175,11 +170,7 @@ def config_changed():
conf['remove-missing'], conf['remove-missing'],
conf['remove-missing-force']) conf['remove-missing-force'])
if git_install_requested(): if not config('action-managed-upgrade'):
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 openstack_upgrade_available('cinder-common'): if openstack_upgrade_available('cinder-common'):
status_set('maintenance', 'Running openstack upgrade') status_set('maintenance', 'Running openstack upgrade')
do_openstack_upgrade(configs=CONFIGS) do_openstack_upgrade(configs=CONFIGS)

View File

@ -13,7 +13,6 @@
# limitations under the License. # limitations under the License.
import os import os
import shutil
import subprocess import subprocess
import uuid import uuid
@ -21,16 +20,11 @@ from copy import deepcopy
from collections import OrderedDict from collections import OrderedDict
from copy import copy from copy import copy
from charmhelpers.contrib.python.packages import (
pip_install,
)
from charmhelpers.core.strutils import ( from charmhelpers.core.strutils import (
bytes_from_string bytes_from_string
) )
from charmhelpers.core.hookenv import ( from charmhelpers.core.hookenv import (
charm_dir,
config, config,
local_unit, local_unit,
relation_get, relation_get,
@ -50,9 +44,6 @@ from charmhelpers.fetch import (
) )
from charmhelpers.core.host import ( from charmhelpers.core.host import (
adduser,
add_group,
add_user_to_group,
CompareHostReleases, CompareHostReleases,
lsb_release, lsb_release,
mkdir, mkdir,
@ -61,7 +52,6 @@ from charmhelpers.core.host import (
service_restart, service_restart,
service_stop, service_stop,
service_start, service_start,
write_file,
) )
from charmhelpers.contrib.openstack.alternatives import install_alternative from charmhelpers.contrib.openstack.alternatives import install_alternative
@ -99,13 +89,6 @@ from charmhelpers.contrib.openstack import (
from charmhelpers.contrib.openstack.utils import ( from charmhelpers.contrib.openstack.utils import (
configure_installation_source, configure_installation_source,
get_os_codename_install_source, 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,
os_release, os_release,
reset_os_release, reset_os_release,
make_assess_status_func, make_assess_status_func,
@ -121,7 +104,6 @@ from charmhelpers.contrib.openstack.utils import (
from charmhelpers.core.decorators import ( from charmhelpers.core.decorators import (
retry_on_exception, retry_on_exception,
) )
from charmhelpers.core.templating import render
import cinder_contexts import cinder_contexts
@ -143,30 +125,6 @@ API_PACKAGES = ['cinder-api']
VOLUME_PACKAGES = ['cinder-volume'] VOLUME_PACKAGES = ['cinder-volume']
SCHEDULER_PACKAGES = ['cinder-scheduler'] SCHEDULER_PACKAGES = ['cinder-scheduler']
BASE_GIT_PACKAGES = [
'libffi-dev',
'libmysqlclient-dev',
'libssl-dev',
'libxml2-dev',
'libxslt1-dev',
'libyaml-dev',
'lvm2',
'openstack-pkg-tools',
'python-dev',
'python-pip',
'python-setuptools',
'zlib1g-dev',
]
# ubuntu packages that should not be installed when deploying from source
GIT_PACKAGE_BLACKLIST = [
'cinder-api',
'cinder-common',
'cinder-scheduler',
'cinder-volume',
'python-keystoneclient',
]
DEFAULT_LOOPBACK_SIZE = '5G' DEFAULT_LOOPBACK_SIZE = '5G'
# Cluster resource used to determine leadership when hacluster'd # Cluster resource used to determine leadership when hacluster'd
@ -381,12 +339,6 @@ def determine_packages():
if service_enabled(s): if service_enabled(s):
pkgs += p pkgs += p
if git_install_requested():
pkgs.extend(BASE_GIT_PACKAGES)
# don't include packages that will be installed from git
for p in GIT_PACKAGE_BLACKLIST:
pkgs.remove(p)
pkgs.extend(token_cache_pkgs(source=config()['openstack-origin'])) pkgs.extend(token_cache_pkgs(source=config()['openstack-origin']))
return pkgs return pkgs
@ -810,189 +762,6 @@ def setup_ipv6():
apt_install('haproxy/trusty-backports', fatal=True) 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='cinder')
git_post_install(projects_yaml)
def git_pre_install():
"""Perform cinder pre-install setup."""
dirs = [{'path': '/etc/tgt',
'owner': 'cinder',
'group': 'cinder',
'perms': 0750,
},
{'path': '/var/lib/cinder',
'owner': 'cinder',
'group': 'cinder',
'perms': 0755,
},
{'path': '/var/lib/cinder/volumes',
'owner': 'cinder',
'group': 'cinder',
'perms': 0750,
},
{'path': '/var/lock/cinder',
'owner': 'cinder',
'group': 'root',
'perms': 0750,
},
{'path': '/var/log/cinder',
'owner': 'cinder',
'group': 'cinder',
'perms': 0750,
}]
logs = [
'/var/log/cinder/cinder-api.log',
'/var/log/cinder/cinder-backup.log',
'/var/log/cinder/cinder-scheduler.log',
'/var/log/cinder/cinder-volume.log',
]
adduser('cinder', shell='/bin/bash', system_user=True)
add_group('cinder', system_group=True)
add_user_to_group('cinder', 'cinder')
for d in dirs:
mkdir(d['path'], owner=d['owner'], group=d['group'], perms=d['perms'],
force=False)
for l in logs:
write_file(l, '', owner='cinder', group='cinder', perms=0600)
def git_post_install(projects_yaml):
"""Perform cinder post-install setup."""
http_proxy = git_yaml_value(projects_yaml, 'http_proxy')
base_packages = ['mysql-python', 'python-cephlibs']
for pkg in base_packages:
if http_proxy:
pip_install(pkg, proxy=http_proxy,
venv=git_pip_venv_dir(projects_yaml))
else:
pip_install(pkg,
venv=git_pip_venv_dir(projects_yaml))
src_etc = os.path.join(git_src_dir(projects_yaml, 'cinder'), 'etc/cinder')
configs = {
'src': src_etc,
'dest': '/etc/cinder',
}
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/cinder-manage'),
'link': '/usr/local/bin/cinder-manage'},
{'src': os.path.join(git_pip_venv_dir(projects_yaml),
'bin/cinder-rootwrap'),
'link': '/usr/local/bin/cinder-rootwrap'},
]
for s in symlinks:
if os.path.lexists(s['link']):
os.remove(s['link'])
os.symlink(s['src'], s['link'])
render('git/cinder_tgt.conf', '/etc/tgt/conf.d', {}, owner='cinder',
group='cinder', perms=0o644)
render('git/logging.conf', '/etc/cinder/logging.conf', {}, owner='cinder',
group='cinder', perms=0o644)
render('git/cinder_sudoers', '/etc/sudoers.d/cinder_sudoers', {},
owner='root', group='root', perms=0o440)
os.chmod('/etc/sudoers.d', 0o750)
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 = ['cinder-api', 'cinder-backup', 'cinder-scheduler',
'cinder-volume']
for daemon in daemons:
cinder_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),
cinder_context, perms=0o644)
git_generate_systemd_init_files(templates_dir)
else:
cinder_api_context = {
'service_description': 'Cinder API server',
'service_name': 'Cinder',
'user_name': 'cinder',
'start_dir': '/var/lib/cinder',
'process_name': 'cinder-api',
'executable_name': os.path.join(bin_dir, 'cinder-api'),
'config_files': ['/etc/cinder/cinder.conf'],
'log_file': '/var/log/cinder/cinder-api.log',
}
cinder_backup_context = {
'service_description': 'Cinder backup server',
'service_name': 'Cinder',
'user_name': 'cinder',
'start_dir': '/var/lib/cinder',
'process_name': 'cinder-backup',
'executable_name': os.path.join(bin_dir, 'cinder-backup'),
'config_files': ['/etc/cinder/cinder.conf'],
'log_file': '/var/log/cinder/cinder-backup.log',
}
cinder_scheduler_context = {
'service_description': 'Cinder scheduler server',
'service_name': 'Cinder',
'user_name': 'cinder',
'start_dir': '/var/lib/cinder',
'process_name': 'cinder-scheduler',
'executable_name': os.path.join(bin_dir, 'cinder-scheduler'),
'config_files': ['/etc/cinder/cinder.conf'],
'log_file': '/var/log/cinder/cinder-scheduler.log',
}
cinder_volume_context = {
'service_description': 'Cinder volume server',
'service_name': 'Cinder',
'user_name': 'cinder',
'start_dir': '/var/lib/cinder',
'process_name': 'cinder-volume',
'executable_name': os.path.join(bin_dir, 'cinder-volume'),
'config_files': ['/etc/cinder/cinder.conf'],
'log_file': '/var/log/cinder/cinder-volume.log',
}
templates_dir = 'hooks/charmhelpers/contrib/openstack/templates'
templates_dir = os.path.join(charm_dir(), templates_dir)
render('git.upstart', '/etc/init/cinder-api.conf',
cinder_api_context, perms=0o644,
templates_dir=templates_dir)
render('git.upstart', '/etc/init/cinder-backup.conf',
cinder_backup_context, perms=0o644,
templates_dir=templates_dir)
render('git.upstart', '/etc/init/cinder-scheduler.conf',
cinder_scheduler_context, perms=0o644,
templates_dir=templates_dir)
render('git.upstart', '/etc/init/cinder-volume.conf',
cinder_volume_context, perms=0o644,
templates_dir=templates_dir)
if not is_unit_paused_set():
service_restart('tgtd')
[service_restart(s) for s in services()]
def filesystem_mounted(fs): def filesystem_mounted(fs):
return subprocess.call(['grep', '-wqs', fs, '/proc/mounts']) == 0 return subprocess.call(['grep', '-wqs', fs, '/proc/mounts']) == 0

View File

@ -1,22 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: cinder-api
# Required-Start: $network $local_fs $remote_fs $syslog
# Required-Stop: $remote_fs
# Should-Start: postgresql mysql keystone rabbitmq-server ntp
# Should-Stop: postgresql mysql keystone rabbitmq-server ntp
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Cinder Api
# Description: Provides EBS like storage for your
# virtual machine instances
### END INIT INFO
# Author: Julien Danjou <acid@debian.org>, Thomas Goirand <zigo@debian.org>
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="OpenStack Cinder Api"
PROJECT_NAME=cinder
NAME=${PROJECT_NAME}-api
DAEMON={{ daemon_path }}

View File

@ -1,21 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: cinder-backup
# Required-Start: $network $local_fs $remote_fs $syslog
# Required-Stop: $remote_fs
# Should-Start: postgresql mysql keystone rabbitmq-server ntp
# Should-Stop: postgresql mysql keystone rabbitmq-server ntp
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Cinder Backup
# Description: Provides Cinder Backup
### END INIT INFO
# Author: Thomas Goirand <zigo@debian.org>
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="OpenStack Cinder Backup"
PROJECT_NAME=cinder
NAME=${PROJECT_NAME}-backup
DAEMON={{ daemon_path }}

View File

@ -1,22 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: cinder-scheduler
# Required-Start: $network $local_fs $remote_fs $syslog
# Required-Stop: $remote_fs
# Should-Start: postgresql mysql keystone rabbitmq-server ntp
# Should-Stop: postgresql mysql keystone rabbitmq-server ntp
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Cinder Scheduler
# Description: Provides EBS like storage for your
# virtual machine instances
### END INIT INFO
# Author: Julien Danjou <acid@debian.org>, Thomas Goirand <zigo@debian.org>
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="OpenStack Cinder Scheduler"
PROJECT_NAME=cinder
NAME=${PROJECT_NAME}-scheduler
DAEMON={{ daemon_path }}

View File

@ -1,22 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: cinder-volume
# Required-Start: $network $local_fs $remote_fs $syslog
# Required-Stop: $remote_fs
# Should-Start: postgresql mysql keystone rabbitmq-server ntp
# Should-Stop: postgresql mysql keystone rabbitmq-server ntp
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Cinder Volume
# Description: Provides EBS like storage for your
# virtual machine instances
### END INIT INFO
# Author: Julien Danjou <acid@debian.org>
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="OpenStack Cinder Volume"
PROJECT_NAME=cinder
NAME=${PROJECT_NAME}-volume
DAEMON={{ daemon_path }}

View File

@ -1,4 +0,0 @@
Defaults:cinder !requiretty
cinder ALL = (root) NOPASSWD: /usr/local/bin/cinder-rootwrap /etc/cinder/rootwrap.conf *

View File

@ -1 +0,0 @@
include /var/lib/cinder/volumes/*

View File

@ -1,76 +0,0 @@
[loggers]
keys = root, cinder
[handlers]
keys = stderr, stdout, watchedfile, syslog, null
[formatters]
keys = legacycinder, default
[logger_root]
level = WARNING
handlers = null
[logger_cinder]
level = INFO
handlers = stderr
qualname = cinder
[logger_amqplib]
level = WARNING
handlers = stderr
qualname = amqplib
[logger_sqlalchemy]
level = WARNING
handlers = stderr
qualname = sqlalchemy
# "level = INFO" logs SQL queries.
# "level = DEBUG" logs SQL queries and results.
# "level = WARNING" logs neither. (Recommended for production systems.)
[logger_boto]
level = WARNING
handlers = stderr
qualname = boto
[logger_suds]
level = INFO
handlers = stderr
qualname = suds
[logger_eventletwsgi]
level = WARNING
handlers = stderr
qualname = eventlet.wsgi.server
[handler_stderr]
class = StreamHandler
args = (sys.stderr,)
formatter = legacycinder
[handler_stdout]
class = StreamHandler
args = (sys.stdout,)
formatter = legacycinder
[handler_watchedfile]
class = handlers.WatchedFileHandler
args = ('cinder.log',)
formatter = legacycinder
[handler_syslog]
class = handlers.SysLogHandler
args = ('/dev/log', handlers.SysLogHandler.LOG_USER)
formatter = legacycinder
[handler_null]
class = cinder.log.NullHandler
formatter = default
args = ()
[formatter_legacycinder]
class = cinder.log.LegacyCinderFormatter
[formatter_default]
format = %(message)s

View File

@ -15,8 +15,6 @@
# limitations under the License. # limitations under the License.
import amulet import amulet
import os
import yaml
from charmhelpers.contrib.openstack.amulet.deployment import ( from charmhelpers.contrib.openstack.amulet.deployment import (
OpenStackAmuletDeployment OpenStackAmuletDeployment
@ -38,12 +36,11 @@ class CinderBasicDeployment(OpenStackAmuletDeployment):
Create, clone, delete volumes. Create volume from glance image. Create, clone, delete volumes. Create volume from glance image.
Create volume snapshot. Create volume from snapshot.""" Create volume snapshot. Create volume from snapshot."""
def __init__(self, series=None, openstack=None, source=None, git=False, def __init__(self, series=None, openstack=None, source=None,
stable=False): stable=False):
"""Deploy the entire test environment.""" """Deploy the entire test environment."""
super(CinderBasicDeployment, self).__init__(series, openstack, source, super(CinderBasicDeployment, self).__init__(series, openstack, source,
stable) stable)
self.git = git
self._add_services() self._add_services()
self._add_relations() self._add_relations()
self._configure_services() self._configure_services()
@ -119,35 +116,6 @@ class CinderBasicDeployment(OpenStackAmuletDeployment):
'glance-api-version': '2', 'glance-api-version': '2',
'overwrite': 'true', 'overwrite': 'true',
'ephemeral-unmount': '/mnt'} 'ephemeral-unmount': '/mnt'}
if self.git:
amulet_http_proxy = os.environ.get('AMULET_HTTP_PROXY')
reqs_repo = 'git://github.com/openstack/requirements'
cinder_repo = 'git://github.com/openstack/cinder'
if self._get_openstack_release() == self.trusty_icehouse:
reqs_repo = 'git://github.com/coreycb/requirements'
cinder_repo = 'git://github.com/coreycb/cinder'
branch = 'stable/' + self._get_openstack_release_string()
openstack_origin_git = {
'repositories': [
{'name': 'requirements',
'repository': reqs_repo,
'branch': branch},
{'name': 'cinder',
'repository': cinder_repo,
'branch': branch},
],
# Most tests use /mnt/openstack-git but cinder's using /dev/vdb
# to store block devices so leave /mnt alone.
'directory': '/tmp/openstack-git',
'http_proxy': amulet_http_proxy,
'https_proxy': amulet_http_proxy,
}
cinder_config['openstack-origin-git'] = \
yaml.dump(openstack_origin_git)
keystone_config = { keystone_config = {
'admin-password': 'openstack', 'admin-password': 'openstack',
'admin-token': 'ubuntutesting' 'admin-token': 'ubuntutesting'
@ -365,7 +333,7 @@ class CinderBasicDeployment(OpenStackAmuletDeployment):
}] }]
else: else:
expected = [{ expected = [{
'name': 'cinderv3_cinderv2', 'name': 'cinderv2_cinderv3',
'enabled': True, 'enabled': True,
'tenantId': u.not_null, 'tenantId': u.not_null,
'id': u.not_null, 'id': u.not_null,
@ -515,7 +483,7 @@ class CinderBasicDeployment(OpenStackAmuletDeployment):
expected['service_username'] = 'cinder_cinderv2' expected['service_username'] = 'cinder_cinderv2'
else: else:
# Pike and later # Pike and later
expected['service_username'] = 'cinderv3_cinderv2' expected['service_username'] = 'cinderv2_cinderv3'
ret = u.validate_relation_data(unit, relation, expected) ret = u.validate_relation_data(unit, relation, expected)
if ret: if ret:

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

View File

@ -25,3 +25,9 @@ sys.modules['cinder.context'] = cinder.context
sys.modules['cinder.db'] = cinder.db sys.modules['cinder.db'] = cinder.db
sys.modules['cinder.db.sqlalchemy'] = cinder.db.sqlalchemy sys.modules['cinder.db.sqlalchemy'] = cinder.db.sqlalchemy
sys.modules['cinder.db.sqlalchemy.api'] = cinder.db.sqlalchemy.api sys.modules['cinder.db.sqlalchemy.api'] = cinder.db.sqlalchemy.api
# python-apt is not installed as part of test-requirements but is imported by
# some charmhelpers modules so create a fake import.
mock_apt = mock.MagicMock()
sys.modules['apt'] = mock_apt
mock_apt.apt_pkg = mock.MagicMock()

View File

@ -1,120 +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
os.environ['JUJU_UNIT_NAME'] = 'cinder'
# 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()
from test_utils import RESTART_MAP, CharmTestCase
with patch('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('cinder_utils.register_configs') as register_configs:
with patch('cinder_utils.restart_map') as restart_map:
restart_map.return_value = RESTART_MAP
import git_reinstall
TO_PATCH = [
'config',
]
openstack_origin_git = \
"""repositories:
- {name: requirements,
repository: 'git://git.openstack.org/openstack/requirements',
branch: stable/juno}
- {name: cinder,
repository: 'git://git.openstack.org/openstack/cinder',
branch: stable/juno}"""
class TestCinderActions(CharmTestCase):
def setUp(self):
super(TestCinderActions, 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

@ -45,13 +45,11 @@ class TestCinderUpgradeActions(CharmTestCase):
@patch('charmhelpers.contrib.openstack.utils.juju_log') @patch('charmhelpers.contrib.openstack.utils.juju_log')
@patch('charmhelpers.contrib.openstack.utils.config') @patch('charmhelpers.contrib.openstack.utils.config')
@patch('charmhelpers.contrib.openstack.utils.action_set') @patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.git_install_requested')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available') @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, log, action_set, config, log,
mock_cinder_hooks): mock_cinder_hooks):
mock_cinder_hooks.config_changed = MagicMock() mock_cinder_hooks.config_changed = MagicMock()
git_requested.return_value = False
upgrade_avail.return_value = True upgrade_avail.return_value = True
config.return_value = True config.return_value = True
self.relation_ids.return_value = ['relid1'] self.relation_ids.return_value = ['relid1']
@ -69,13 +67,11 @@ class TestCinderUpgradeActions(CharmTestCase):
@patch('charmhelpers.contrib.openstack.utils.juju_log') @patch('charmhelpers.contrib.openstack.utils.juju_log')
@patch('charmhelpers.contrib.openstack.utils.config') @patch('charmhelpers.contrib.openstack.utils.config')
@patch('charmhelpers.contrib.openstack.utils.action_set') @patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.git_install_requested')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available') @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, log, action_set, config, log,
mock_cinder_hooks): mock_cinder_hooks):
mock_cinder_hooks.config_changed = MagicMock() mock_cinder_hooks.config_changed = MagicMock()
git_requested.return_value = False
upgrade_avail.return_value = True upgrade_avail.return_value = True
config.return_value = False config.return_value = False

View File

@ -13,11 +13,8 @@
# limitations under the License. # limitations under the License.
import json import json
import sys
import yaml
from mock import ( from mock import (
MagicMock,
patch, patch,
call call
) )
@ -27,13 +24,6 @@ from test_utils import (
RESTART_MAP, RESTART_MAP,
) )
# 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()
with patch('charmhelpers.contrib.hardening.harden.harden') as mock_dec: with patch('charmhelpers.contrib.hardening.harden.harden') as mock_dec:
mock_dec.side_effect = (lambda *dargs, **dkwargs: lambda f: mock_dec.side_effect = (lambda *dargs, **dkwargs: lambda f:
lambda *args, **kwargs: f(*args, **kwargs)) lambda *args, **kwargs: f(*args, **kwargs))
@ -41,6 +31,7 @@ with patch('charmhelpers.contrib.hardening.harden.harden') as mock_dec:
with patch('cinder_utils.restart_map') as restart_map: with patch('cinder_utils.restart_map') as restart_map:
restart_map.return_value = RESTART_MAP restart_map.return_value = RESTART_MAP
import cinder_hooks as hooks import cinder_hooks as hooks
reload(hooks)
hooks.hooks._config_save = False hooks.hooks._config_save = False
import cinder_utils as utils import cinder_utils as utils
@ -54,7 +45,6 @@ TO_PATCH = [
'determine_packages', 'determine_packages',
'do_openstack_upgrade', 'do_openstack_upgrade',
'ensure_ceph_keyring', 'ensure_ceph_keyring',
'git_install',
'is_clustered', 'is_clustered',
'juju_log', 'juju_log',
'log', 'log',
@ -105,45 +95,15 @@ class TestInstallHook(CharmTestCase):
super(TestInstallHook, self).setUp(hooks, TO_PATCH) super(TestInstallHook, self).setUp(hooks, TO_PATCH)
self.config.side_effect = self.test_config.get self.config.side_effect = self.test_config.get
@patch.object(utils, 'git_install_requested') def test_install_precise_distro(self):
def test_install_precise_distro(self, git_requested):
'It redirects to cloud archive if setup to install precise+distro' 'It redirects to cloud archive if setup to install precise+distro'
git_requested.return_value = False
self.lsb_release.return_value = {'DISTRIB_CODENAME': 'precise'} self.lsb_release.return_value = {'DISTRIB_CODENAME': 'precise'}
hooks.hooks.execute(['hooks/install.real']) hooks.hooks.execute(['hooks/install.real'])
ca = 'cloud:precise-folsom' ca = 'cloud:precise-folsom'
self.configure_installation_source.assert_called_with(ca) self.configure_installation_source.assert_called_with(ca)
@patch.object(utils, 'git_install_requested') def test_correct_install_packages(self):
def test_install_git(self, git_requested):
git_requested.return_value = True
self.determine_packages.return_value = ['foo', 'bar', 'baz']
repo = 'cloud:trusty-juno'
openstack_origin_git = {
'repositories': [
{'name': 'requirements',
'repository': 'git://git.openstack.org/openstack/requirements', # noqa
'branch': 'stable/juno'},
{'name': 'cinder',
'repository': 'git://git.openstack.org/openstack/cinder',
'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.hooks.execute(['hooks/install.real'])
self.assertTrue(self.execd_preinstall.called)
self.configure_installation_source.assert_called_with(repo)
self.apt_update.assert_called_with()
self.apt_install.assert_called_with(['foo', 'bar', 'baz'], fatal=True)
self.git_install.assert_called_with(projects_yaml)
@patch.object(utils, 'git_install_requested')
def test_correct_install_packages(self, git_requested):
'It installs the correct packages based on what is determined' 'It installs the correct packages based on what is determined'
git_requested.return_value = False
self.determine_packages.return_value = ['foo', 'bar', 'baz'] self.determine_packages.return_value = ['foo', 'bar', 'baz']
hooks.hooks.execute(['hooks/install.real']) hooks.hooks.execute(['hooks/install.real'])
self.apt_install.assert_called_with(['foo', 'bar', 'baz'], fatal=True) self.apt_install.assert_called_with(['foo', 'bar', 'baz'], fatal=True)
@ -168,12 +128,10 @@ class TestChangedHooks(CharmTestCase):
_joined.assert_called_with(relation_id='amqp:1') _joined.assert_called_with(relation_id='amqp:1')
@patch.object(hooks, 'configure_https') @patch.object(hooks, 'configure_https')
@patch.object(hooks, 'git_install_requested')
@patch.object(hooks, 'config_value_changed') @patch.object(hooks, 'config_value_changed')
def test_config_changed(self, config_val_changed, def test_config_changed(self, config_val_changed,
git_requested, conf_https): conf_https):
'It writes out all config' 'It writes out all config'
git_requested.return_value = False
self.openstack_upgrade_available.return_value = False self.openstack_upgrade_available.return_value = False
hooks.hooks.execute(['hooks/config-changed']) hooks.hooks.execute(['hooks/config-changed'])
self.assertTrue(self.CONFIGS.write_all.called) self.assertTrue(self.CONFIGS.write_all.called)
@ -184,12 +142,10 @@ class TestChangedHooks(CharmTestCase):
self.open_port.assert_called_with(8776) self.open_port.assert_called_with(8776)
@patch.object(hooks, 'configure_https') @patch.object(hooks, 'configure_https')
@patch.object(hooks, 'git_install_requested')
@patch.object(hooks, 'config_value_changed') @patch.object(hooks, 'config_value_changed')
def test_config_changed_block_devices(self, config_val_changed, def test_config_changed_block_devices(self, config_val_changed,
git_requested, conf_https): conf_https):
'It writes out all config' 'It writes out all config'
git_requested.return_value = False
self.openstack_upgrade_available.return_value = False self.openstack_upgrade_available.return_value = False
self.test_config.set('block-device', 'sdb /dev/sdc sde') self.test_config.set('block-device', 'sdb /dev/sdc sde')
self.test_config.set('volume-group', 'cinder-new') self.test_config.set('volume-group', 'cinder-new')
@ -204,14 +160,11 @@ class TestChangedHooks(CharmTestCase):
True, True, False) True, True, False)
@patch.object(hooks, 'configure_https') @patch.object(hooks, 'configure_https')
@patch.object(hooks, 'git_install_requested')
@patch.object(hooks, 'config_value_changed') @patch.object(hooks, 'config_value_changed')
def test_config_changed_uses_remove_missing_force(self, def test_config_changed_uses_remove_missing_force(self,
config_val_changed, config_val_changed,
git_requested,
conf_https): conf_https):
'It uses the remove-missing-force config option' 'It uses the remove-missing-force config option'
git_requested.return_value = False
self.openstack_upgrade_available.return_value = False self.openstack_upgrade_available.return_value = False
self.test_config.set('block-device', 'sdb') self.test_config.set('block-device', 'sdb')
self.test_config.set('remove-missing-force', True) self.test_config.set('remove-missing-force', True)
@ -222,51 +175,21 @@ class TestChangedHooks(CharmTestCase):
False, False, True) False, False, True)
@patch.object(hooks, 'configure_https') @patch.object(hooks, 'configure_https')
@patch.object(hooks, 'git_install_requested')
@patch.object(hooks, 'config_value_changed') @patch.object(hooks, 'config_value_changed')
def test_config_changed_upgrade_available(self, config_val_changed, def test_config_changed_upgrade_available(self, config_val_changed,
git_requested, conf_https): conf_https):
'It writes out all config with an available OS upgrade' 'It writes out all config with an available OS upgrade'
git_requested.return_value = False
self.openstack_upgrade_available.return_value = True self.openstack_upgrade_available.return_value = True
hooks.hooks.execute(['hooks/config-changed']) hooks.hooks.execute(['hooks/config-changed'])
self.do_openstack_upgrade.assert_called_with(configs=self.CONFIGS) self.do_openstack_upgrade.assert_called_with(configs=self.CONFIGS)
@patch.object(hooks, 'configure_https')
@patch.object(hooks, 'git_install_requested')
@patch.object(hooks, 'config_value_changed')
def test_config_changed_git_updated(self, config_val_changed,
git_requested, conf_https):
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': 'cinder',
'repository': 'git://git.openstack.org/openstack/',
'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.hooks.execute(['hooks/config-changed'])
self.git_install.assert_called_with(projects_yaml)
self.assertFalse(self.do_openstack_upgrade.called)
self.assertTrue(conf_https.called)
@patch('charmhelpers.core.host.service') @patch('charmhelpers.core.host.service')
@patch.object(hooks, 'configure_https') @patch.object(hooks, 'configure_https')
@patch.object(hooks, 'git_install_requested')
@patch.object(hooks, 'config_value_changed') @patch.object(hooks, 'config_value_changed')
def test_config_changed_overwrite_changed(self, config_val_changed, def test_config_changed_overwrite_changed(self, config_val_changed,
git_requested, conf_https, conf_https,
_services): _services):
'It uses the overwrite config option' 'It uses the overwrite config option'
git_requested.return_value = False
self.openstack_upgrade_available.return_value = False self.openstack_upgrade_available.return_value = False
config_val_changed.return_value = True config_val_changed.return_value = True
hooks.hooks.execute(['hooks/config-changed']) hooks.hooks.execute(['hooks/config-changed'])
@ -277,12 +200,10 @@ class TestChangedHooks(CharmTestCase):
False, False, False) False, False, False)
self.service_restart.assert_called_with('cinder-volume') self.service_restart.assert_called_with('cinder-volume')
@patch.object(hooks, 'git_install_requested')
@patch.object(hooks, 'config_value_changed') @patch.object(hooks, 'config_value_changed')
def test_config_changed_with_openstack_upgrade_action(self, def test_config_changed_with_openstack_upgrade_action(
config_value_changed, self,
git_requested): config_value_changed):
git_requested.return_value = False
self.openstack_upgrade_available.return_value = True self.openstack_upgrade_available.return_value = True
self.test_config.set('action-managed-upgrade', True) self.test_config.set('action-managed-upgrade', True)

View File

@ -37,13 +37,6 @@ TO_PATCH = [
'umount', 'umount',
'mkdir', 'mkdir',
'service_restart', 'service_restart',
# helpers.core.templating
'render',
# helpers.contrib.openstack.utils
'git_generate_systemd_init_files',
'git_src_dir',
# helpers.contrib.python.packages
'pip_install',
# ceph utils # ceph utils
# storage_utils # storage_utils
'create_lvm_physical_volume', 'create_lvm_physical_volume',
@ -98,15 +91,6 @@ FDISKDISPLAY = """
""" """
openstack_origin_git = \
"""repositories:
- {name: requirements,
repository: 'git://git.openstack.org/openstack/requirements',
branch: stable/juno}
- {name: cinder,
repository: 'git://git.openstack.org/openstack/cinder',
branch: stable/juno}"""
class TestCinderUtils(CharmTestCase): class TestCinderUtils(CharmTestCase):
@ -140,10 +124,8 @@ class TestCinderUtils(CharmTestCase):
self.assertFalse(cinder_utils.service_enabled('volume')) self.assertFalse(cinder_utils.service_enabled('volume'))
@patch('cinder_utils.service_enabled') @patch('cinder_utils.service_enabled')
@patch('cinder_utils.git_install_requested') def test_determine_packages_all(self, service_enabled):
def test_determine_packages_all(self, git_requested, service_enabled):
'It determines all packages required when all services enabled' 'It determines all packages required when all services enabled'
git_requested.return_value = False
service_enabled.return_value = True service_enabled.return_value = True
pkgs = cinder_utils.determine_packages() pkgs = cinder_utils.determine_packages()
self.assertEqual(sorted(pkgs), self.assertEqual(sorted(pkgs),
@ -153,10 +135,8 @@ class TestCinderUtils(CharmTestCase):
cinder_utils.SCHEDULER_PACKAGES)) cinder_utils.SCHEDULER_PACKAGES))
@patch('cinder_utils.service_enabled') @patch('cinder_utils.service_enabled')
@patch('cinder_utils.git_install_requested') def test_determine_packages_subset(self, service_enabled):
def test_determine_packages_subset(self, git_requested, service_enabled):
'It determines packages required for a subset of enabled services' 'It determines packages required for a subset of enabled services'
git_requested.return_value = False
service_enabled.side_effect = self.svc_enabled service_enabled.side_effect = self.svc_enabled
self.test_config.set('openstack-origin', 'cloud:xenial-newton') self.test_config.set('openstack-origin', 'cloud:xenial-newton')
self.token_cache_pkgs.return_value = ['memcached'] self.token_cache_pkgs.return_value = ['memcached']
@ -790,184 +770,6 @@ class TestCinderUtils(CharmTestCase):
configs.set_release.assert_called_with(openstack_release='havana') configs.set_release.assert_called_with(openstack_release='havana')
self.assertFalse(migrate.called) self.assertFalse(migrate.called)
@patch.object(cinder_utils, 'git_install_requested')
@patch.object(cinder_utils, 'git_clone_and_install')
@patch.object(cinder_utils, 'git_post_install')
@patch.object(cinder_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
cinder_utils.git_install(projects_yaml)
self.assertTrue(git_pre.called)
git_clone_and_install.assert_called_with(openstack_origin_git,
core_project='cinder')
self.assertTrue(git_post.called)
@patch.object(cinder_utils, 'mkdir')
@patch.object(cinder_utils, 'write_file')
@patch.object(cinder_utils, 'add_user_to_group')
@patch.object(cinder_utils, 'add_group')
@patch.object(cinder_utils, 'adduser')
def test_git_pre_install(self, adduser, add_group, add_user_to_group,
write_file, mkdir):
cinder_utils.git_pre_install()
adduser.assert_called_with('cinder', shell='/bin/bash',
system_user=True)
add_group.assert_called_with('cinder', system_group=True)
add_user_to_group.assert_called_with('cinder', 'cinder')
expected = [
call('/etc/tgt', owner='cinder', perms=488, force=False,
group='cinder'),
call('/var/lib/cinder', owner='cinder', perms=493, force=False,
group='cinder'),
call('/var/lib/cinder/volumes', owner='cinder', perms=488,
force=False, group='cinder'),
call('/var/lock/cinder', owner='cinder', perms=488, force=False,
group='root'),
call('/var/log/cinder', owner='cinder', perms=488, force=False,
group='cinder'),
]
self.assertEqual(mkdir.call_args_list, expected)
expected = [
call('/var/log/cinder/cinder-api.log', '', perms=0600,
owner='cinder', group='cinder'),
call('/var/log/cinder/cinder-backup.log', '', perms=0600,
owner='cinder', group='cinder'),
call('/var/log/cinder/cinder-scheduler.log', '', perms=0600,
owner='cinder', group='cinder'),
call('/var/log/cinder/cinder-volume.log', '', perms=0600,
owner='cinder', group='cinder'),
]
self.assertEqual(write_file.call_args_list, expected)
@patch.object(cinder_utils, 'services')
@patch('os.path.join')
@patch('os.path.exists')
@patch('shutil.copytree')
@patch('shutil.rmtree')
@patch('os.chown')
@patch('os.chmod')
@patch('os.symlink')
def test_git_post_install_upstart(self, symlink, chmod, chown, rmtree,
copytree, exists, join, services):
services.return_value = ['svc1']
projects_yaml = openstack_origin_git
join.return_value = 'joined-string'
self.lsb_release.return_value = {'DISTRIB_RELEASE': '15.04'}
cinder_utils.git_post_install(projects_yaml)
self.pip_install('mysql-python', venv='joined-string')
expected = [
call('joined-string', '/etc/cinder'),
]
copytree.assert_has_calls(expected)
expected = [
call('joined-string', '/usr/local/bin/cinder-manage'),
]
symlink.assert_has_calls(expected, any_order=True)
cinder_api_context = {
'service_description': 'Cinder API server',
'service_name': 'Cinder',
'user_name': 'cinder',
'start_dir': '/var/lib/cinder',
'process_name': 'cinder-api',
'executable_name': 'joined-string',
'config_files': ['/etc/cinder/cinder.conf'],
'log_file': '/var/log/cinder/cinder-api.log',
}
cinder_backup_context = {
'service_description': 'Cinder backup server',
'service_name': 'Cinder',
'user_name': 'cinder',
'start_dir': '/var/lib/cinder',
'process_name': 'cinder-backup',
'executable_name': 'joined-string',
'config_files': ['/etc/cinder/cinder.conf'],
'log_file': '/var/log/cinder/cinder-backup.log',
}
cinder_scheduler_context = {
'service_description': 'Cinder scheduler server',
'service_name': 'Cinder',
'user_name': 'cinder',
'start_dir': '/var/lib/cinder',
'process_name': 'cinder-scheduler',
'executable_name': 'joined-string',
'config_files': ['/etc/cinder/cinder.conf'],
'log_file': '/var/log/cinder/cinder-scheduler.log',
}
cinder_volume_context = {
'service_description': 'Cinder volume server',
'service_name': 'Cinder',
'user_name': 'cinder',
'start_dir': '/var/lib/cinder',
'process_name': 'cinder-volume',
'executable_name': 'joined-string',
'config_files': ['/etc/cinder/cinder.conf'],
'log_file': '/var/log/cinder/cinder-volume.log',
}
expected = [
call('git/cinder_tgt.conf', '/etc/tgt/conf.d', {}, owner='cinder',
group='cinder', perms=0o644),
call('git/logging.conf', '/etc/cinder/logging.conf', {},
owner='cinder', group='cinder', perms=0o644),
call('git/cinder_sudoers', '/etc/sudoers.d/cinder_sudoers', {},
owner='root', group='root', perms=0o440),
call('git.upstart', '/etc/init/cinder-api.conf',
cinder_api_context, perms=0o644,
templates_dir='joined-string'),
call('git.upstart', '/etc/init/cinder-backup.conf',
cinder_backup_context, perms=0o644,
templates_dir='joined-string'),
call('git.upstart', '/etc/init/cinder-scheduler.conf',
cinder_scheduler_context, perms=0o644,
templates_dir='joined-string'),
call('git.upstart', '/etc/init/cinder-volume.conf',
cinder_volume_context, perms=0o644,
templates_dir='joined-string'),
]
self.assertEqual(self.render.call_args_list, expected)
expected = [call('tgtd'), call('svc1')]
self.assertEqual(self.service_restart.call_args_list, expected)
@patch.object(cinder_utils, 'services')
@patch('os.path.join')
@patch('shutil.copytree')
@patch('shutil.rmtree')
@patch('pwd.getpwnam')
@patch('grp.getgrnam')
@patch('os.chown')
@patch('os.chmod')
@patch('os.symlink')
def test_git_post_install_systemd(self, symlink, chmod, chown, grp, pwd,
rmtree, copytree, join, services):
projects_yaml = openstack_origin_git
join.return_value = 'joined-string'
self.lsb_release.return_value = {'DISTRIB_RELEASE': '15.10'}
cinder_utils.git_post_install(projects_yaml)
expected = [
call('git/cinder_tgt.conf', '/etc/tgt/conf.d', {},
group='cinder', owner='cinder', perms=420),
call('git/logging.conf', '/etc/cinder/logging.conf', {},
group='cinder', owner='cinder', perms=420),
call('git/cinder_sudoers', '/etc/sudoers.d/cinder_sudoers', {},
group='root', owner='root', perms=288),
call('git/cinder-api.init.in.template', 'joined-string',
{'daemon_path': 'joined-string'}, perms=420),
call('git/cinder-backup.init.in.template', 'joined-string',
{'daemon_path': 'joined-string'}, perms=420),
call('git/cinder-scheduler.init.in.template', 'joined-string',
{'daemon_path': 'joined-string'}, perms=420),
call('git/cinder-volume.init.in.template', 'joined-string',
{'daemon_path': 'joined-string'}, perms=420),
]
self.assertEqual(self.render.call_args_list, expected)
@patch.object(cinder_utils, 'local_unit', lambda *args: 'unit/0') @patch.object(cinder_utils, 'local_unit', lambda *args: 'unit/0')
def test_check_local_db_actions_complete_by_self(self): def test_check_local_db_actions_complete_by_self(self):
self.relation_get.return_value = {} self.relation_get.return_value = {}