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: I44a7a92d5d4ae493bab4d5b81e9757cb12149a66
This commit is contained in:
parent
7b9feea400
commit
c4574ef859
@ -1,5 +1,3 @@
|
||||
git-reinstall:
|
||||
description: Reinstall nova-compute from the openstack-origin-git repositories.
|
||||
openstack-upgrade:
|
||||
description: Perform openstack upgrades. Config option action-managed-upgrade must be set to True.
|
||||
pause:
|
||||
|
@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# 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 nova_compute_utils import (
|
||||
git_install,
|
||||
)
|
||||
|
||||
from nova_compute_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()
|
27
config.yaml
27
config.yaml
@ -38,33 +38,6 @@ options:
|
||||
NOTE: updating this setting to a source that is known to provide
|
||||
a later version of OpenStack will trigger a software upgrade.
|
||||
.
|
||||
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, neutron, and nova
|
||||
repositories, and may also include repositories for other dependencies:
|
||||
repositories:
|
||||
- {name: requirements,
|
||||
repository: 'git://github.com/openstack/requirements',
|
||||
branch: master}
|
||||
- {name: neutron,
|
||||
repository: 'git://github.com/openstack/neutron',
|
||||
branch: master}
|
||||
- {name: nova,
|
||||
repository: 'git://github.com/openstack/nova',
|
||||
branch: master
|
||||
release: master
|
||||
action-managed-upgrade:
|
||||
type: boolean
|
||||
default: False
|
||||
|
@ -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
|
||||
|
||||
|
@ -17,22 +17,22 @@ defaults
|
||||
{%- if haproxy_queue_timeout %}
|
||||
timeout queue {{ haproxy_queue_timeout }}
|
||||
{%- else %}
|
||||
timeout queue 5000
|
||||
timeout queue 9000
|
||||
{%- endif %}
|
||||
{%- if haproxy_connect_timeout %}
|
||||
timeout connect {{ haproxy_connect_timeout }}
|
||||
{%- else %}
|
||||
timeout connect 5000
|
||||
timeout connect 9000
|
||||
{%- endif %}
|
||||
{%- if haproxy_client_timeout %}
|
||||
timeout client {{ haproxy_client_timeout }}
|
||||
{%- else %}
|
||||
timeout client 30000
|
||||
timeout client 90000
|
||||
{%- endif %}
|
||||
{%- if haproxy_server_timeout %}
|
||||
timeout server {{ haproxy_server_timeout }}
|
||||
{%- else %}
|
||||
timeout server 30000
|
||||
timeout server 90000
|
||||
{%- endif %}
|
||||
|
||||
listen stats
|
||||
|
@ -23,7 +23,6 @@ import sys
|
||||
import re
|
||||
import itertools
|
||||
import functools
|
||||
import shutil
|
||||
|
||||
import six
|
||||
import traceback
|
||||
@ -47,7 +46,6 @@ from charmhelpers.core.hookenv import (
|
||||
related_units,
|
||||
relation_ids,
|
||||
relation_set,
|
||||
service_name,
|
||||
status_set,
|
||||
hook_name,
|
||||
application_version_set,
|
||||
@ -68,11 +66,6 @@ from charmhelpers.contrib.network.ip import (
|
||||
port_has_listener,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.python.packages import (
|
||||
pip_create_virtualenv,
|
||||
pip_install,
|
||||
)
|
||||
|
||||
from charmhelpers.core.host import (
|
||||
lsb_release,
|
||||
mounts,
|
||||
@ -84,7 +77,6 @@ from charmhelpers.core.host import (
|
||||
)
|
||||
from charmhelpers.fetch import (
|
||||
apt_cache,
|
||||
install_remote,
|
||||
import_key as fetch_import_key,
|
||||
add_source as fetch_add_source,
|
||||
SourceConfigError,
|
||||
@ -278,27 +270,6 @@ PACKAGE_CODENAMES = {
|
||||
]),
|
||||
}
|
||||
|
||||
GIT_DEFAULT_REPOS = {
|
||||
'requirements': 'git://github.com/openstack/requirements',
|
||||
'cinder': 'git://github.com/openstack/cinder',
|
||||
'glance': 'git://github.com/openstack/glance',
|
||||
'horizon': 'git://github.com/openstack/horizon',
|
||||
'keystone': 'git://github.com/openstack/keystone',
|
||||
'networking-hyperv': 'git://github.com/openstack/networking-hyperv',
|
||||
'neutron': 'git://github.com/openstack/neutron',
|
||||
'neutron-fwaas': 'git://github.com/openstack/neutron-fwaas',
|
||||
'neutron-lbaas': 'git://github.com/openstack/neutron-lbaas',
|
||||
'neutron-vpnaas': 'git://github.com/openstack/neutron-vpnaas',
|
||||
'nova': 'git://github.com/openstack/nova',
|
||||
}
|
||||
|
||||
GIT_DEFAULT_BRANCHES = {
|
||||
'liberty': 'stable/liberty',
|
||||
'mitaka': 'stable/mitaka',
|
||||
'newton': 'stable/newton',
|
||||
'master': 'master',
|
||||
}
|
||||
|
||||
DEFAULT_LOOPBACK_SIZE = '5G'
|
||||
|
||||
|
||||
@ -530,7 +501,6 @@ def os_release(package, base='essex', reset_cache=False):
|
||||
if _os_rel:
|
||||
return _os_rel
|
||||
_os_rel = (
|
||||
git_os_codename_install_source(config('openstack-origin-git')) or
|
||||
get_os_codename_package(package, fatal=False) or
|
||||
get_os_codename_install_source(config('openstack-origin')) or
|
||||
base)
|
||||
@ -771,417 +741,6 @@ def os_requires_version(ostack_release, pkg):
|
||||
return wrap
|
||||
|
||||
|
||||
def git_install_requested():
|
||||
"""
|
||||
Returns true if openstack-origin-git is specified.
|
||||
"""
|
||||
return config('openstack-origin-git') is not None
|
||||
|
||||
|
||||
def git_os_codename_install_source(projects_yaml):
|
||||
"""
|
||||
Returns OpenStack codename of release being installed from source.
|
||||
"""
|
||||
if git_install_requested():
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
|
||||
if projects in GIT_DEFAULT_BRANCHES.keys():
|
||||
if projects == 'master':
|
||||
return 'ocata'
|
||||
return projects
|
||||
|
||||
if 'release' in projects:
|
||||
if projects['release'] == 'master':
|
||||
return 'ocata'
|
||||
return projects['release']
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def git_default_repos(projects_yaml):
|
||||
"""
|
||||
Returns default repos if a default openstack-origin-git value is specified.
|
||||
"""
|
||||
service = service_name()
|
||||
core_project = service
|
||||
|
||||
for default, branch in six.iteritems(GIT_DEFAULT_BRANCHES):
|
||||
if projects_yaml == default:
|
||||
|
||||
# add the requirements repo first
|
||||
repo = {
|
||||
'name': 'requirements',
|
||||
'repository': GIT_DEFAULT_REPOS['requirements'],
|
||||
'branch': branch,
|
||||
}
|
||||
repos = [repo]
|
||||
|
||||
# neutron-* and nova-* charms require some additional repos
|
||||
if service in ['neutron-api', 'neutron-gateway',
|
||||
'neutron-openvswitch']:
|
||||
core_project = 'neutron'
|
||||
if service == 'neutron-api':
|
||||
repo = {
|
||||
'name': 'networking-hyperv',
|
||||
'repository': GIT_DEFAULT_REPOS['networking-hyperv'],
|
||||
'branch': branch,
|
||||
}
|
||||
repos.append(repo)
|
||||
for project in ['neutron-fwaas', 'neutron-lbaas',
|
||||
'neutron-vpnaas', 'nova']:
|
||||
repo = {
|
||||
'name': project,
|
||||
'repository': GIT_DEFAULT_REPOS[project],
|
||||
'branch': branch,
|
||||
}
|
||||
repos.append(repo)
|
||||
|
||||
elif service in ['nova-cloud-controller', 'nova-compute']:
|
||||
core_project = 'nova'
|
||||
repo = {
|
||||
'name': 'neutron',
|
||||
'repository': GIT_DEFAULT_REPOS['neutron'],
|
||||
'branch': branch,
|
||||
}
|
||||
repos.append(repo)
|
||||
elif service == 'openstack-dashboard':
|
||||
core_project = 'horizon'
|
||||
|
||||
# finally add the current service's core project repo
|
||||
repo = {
|
||||
'name': core_project,
|
||||
'repository': GIT_DEFAULT_REPOS[core_project],
|
||||
'branch': branch,
|
||||
}
|
||||
repos.append(repo)
|
||||
|
||||
return yaml.dump(dict(repositories=repos, release=default))
|
||||
|
||||
return projects_yaml
|
||||
|
||||
|
||||
def _git_yaml_load(projects_yaml):
|
||||
"""
|
||||
Load the specified yaml into a dictionary.
|
||||
"""
|
||||
if not projects_yaml:
|
||||
return None
|
||||
|
||||
return yaml.load(projects_yaml)
|
||||
|
||||
|
||||
requirements_dir = None
|
||||
|
||||
|
||||
def git_clone_and_install(projects_yaml, core_project):
|
||||
"""
|
||||
Clone/install all specified OpenStack repositories.
|
||||
|
||||
The expected format of projects_yaml is:
|
||||
|
||||
repositories:
|
||||
- {name: keystone,
|
||||
repository: 'git://git.openstack.org/openstack/keystone.git',
|
||||
branch: 'stable/icehouse'}
|
||||
- {name: requirements,
|
||||
repository: 'git://git.openstack.org/openstack/requirements.git',
|
||||
branch: 'stable/icehouse'}
|
||||
|
||||
directory: /mnt/openstack-git
|
||||
http_proxy: squid-proxy-url
|
||||
https_proxy: squid-proxy-url
|
||||
|
||||
The directory, http_proxy, and https_proxy keys are optional.
|
||||
|
||||
"""
|
||||
global requirements_dir
|
||||
parent_dir = '/mnt/openstack-git'
|
||||
http_proxy = None
|
||||
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
_git_validate_projects_yaml(projects, core_project)
|
||||
|
||||
old_environ = dict(os.environ)
|
||||
|
||||
if 'http_proxy' in projects.keys():
|
||||
http_proxy = projects['http_proxy']
|
||||
os.environ['http_proxy'] = projects['http_proxy']
|
||||
if 'https_proxy' in projects.keys():
|
||||
os.environ['https_proxy'] = projects['https_proxy']
|
||||
|
||||
if 'directory' in projects.keys():
|
||||
parent_dir = projects['directory']
|
||||
|
||||
pip_create_virtualenv(os.path.join(parent_dir, 'venv'))
|
||||
|
||||
# Upgrade setuptools and pip from default virtualenv versions. The default
|
||||
# versions in trusty break master OpenStack branch deployments.
|
||||
for p in ['pip', 'setuptools']:
|
||||
pip_install(p, upgrade=True, proxy=http_proxy,
|
||||
venv=os.path.join(parent_dir, 'venv'))
|
||||
|
||||
constraints = None
|
||||
for p in projects['repositories']:
|
||||
repo = p['repository']
|
||||
branch = p['branch']
|
||||
depth = '1'
|
||||
if 'depth' in p.keys():
|
||||
depth = p['depth']
|
||||
if p['name'] == 'requirements':
|
||||
repo_dir = _git_clone_and_install_single(repo, branch, depth,
|
||||
parent_dir, http_proxy,
|
||||
update_requirements=False)
|
||||
requirements_dir = repo_dir
|
||||
constraints = os.path.join(repo_dir, "upper-constraints.txt")
|
||||
# upper-constraints didn't exist until after icehouse
|
||||
if not os.path.isfile(constraints):
|
||||
constraints = None
|
||||
# use constraints unless project yaml sets use_constraints to false
|
||||
if 'use_constraints' in projects.keys():
|
||||
if not projects['use_constraints']:
|
||||
constraints = None
|
||||
else:
|
||||
repo_dir = _git_clone_and_install_single(repo, branch, depth,
|
||||
parent_dir, http_proxy,
|
||||
update_requirements=True,
|
||||
constraints=constraints)
|
||||
|
||||
os.environ = old_environ
|
||||
|
||||
|
||||
def _git_validate_projects_yaml(projects, core_project):
|
||||
"""
|
||||
Validate the projects yaml.
|
||||
"""
|
||||
_git_ensure_key_exists('repositories', projects)
|
||||
|
||||
for project in projects['repositories']:
|
||||
_git_ensure_key_exists('name', project.keys())
|
||||
_git_ensure_key_exists('repository', project.keys())
|
||||
_git_ensure_key_exists('branch', project.keys())
|
||||
|
||||
if projects['repositories'][0]['name'] != 'requirements':
|
||||
error_out('{} git repo must be specified first'.format('requirements'))
|
||||
|
||||
if projects['repositories'][-1]['name'] != core_project:
|
||||
error_out('{} git repo must be specified last'.format(core_project))
|
||||
|
||||
_git_ensure_key_exists('release', projects)
|
||||
|
||||
|
||||
def _git_ensure_key_exists(key, keys):
|
||||
"""
|
||||
Ensure that key exists in keys.
|
||||
"""
|
||||
if key not in keys:
|
||||
error_out('openstack-origin-git key \'{}\' is missing'.format(key))
|
||||
|
||||
|
||||
def _git_clone_and_install_single(repo, branch, depth, parent_dir, http_proxy,
|
||||
update_requirements, constraints=None):
|
||||
"""
|
||||
Clone and install a single git repository.
|
||||
"""
|
||||
if not os.path.exists(parent_dir):
|
||||
juju_log('Directory already exists at {}. '
|
||||
'No need to create directory.'.format(parent_dir))
|
||||
os.mkdir(parent_dir)
|
||||
|
||||
juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch))
|
||||
repo_dir = install_remote(
|
||||
repo, dest=parent_dir, branch=branch, depth=depth)
|
||||
|
||||
venv = os.path.join(parent_dir, 'venv')
|
||||
|
||||
if update_requirements:
|
||||
if not requirements_dir:
|
||||
error_out('requirements repo must be cloned before '
|
||||
'updating from global requirements.')
|
||||
_git_update_requirements(venv, repo_dir, requirements_dir)
|
||||
|
||||
juju_log('Installing git repo from dir: {}'.format(repo_dir))
|
||||
if http_proxy:
|
||||
pip_install(repo_dir, proxy=http_proxy, venv=venv,
|
||||
constraints=constraints)
|
||||
else:
|
||||
pip_install(repo_dir, venv=venv, constraints=constraints)
|
||||
|
||||
return repo_dir
|
||||
|
||||
|
||||
def _git_update_requirements(venv, package_dir, reqs_dir):
|
||||
"""
|
||||
Update from global requirements.
|
||||
|
||||
Update an OpenStack git directory's requirements.txt and
|
||||
test-requirements.txt from global-requirements.txt.
|
||||
"""
|
||||
orig_dir = os.getcwd()
|
||||
os.chdir(reqs_dir)
|
||||
python = os.path.join(venv, 'bin/python')
|
||||
cmd = [python, 'update.py', package_dir]
|
||||
try:
|
||||
subprocess.check_call(cmd)
|
||||
except subprocess.CalledProcessError:
|
||||
package = os.path.basename(package_dir)
|
||||
error_out("Error updating {} from "
|
||||
"global-requirements.txt".format(package))
|
||||
os.chdir(orig_dir)
|
||||
|
||||
|
||||
def git_pip_venv_dir(projects_yaml):
|
||||
"""
|
||||
Return the pip virtualenv path.
|
||||
"""
|
||||
parent_dir = '/mnt/openstack-git'
|
||||
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
|
||||
if 'directory' in projects.keys():
|
||||
parent_dir = projects['directory']
|
||||
|
||||
return os.path.join(parent_dir, 'venv')
|
||||
|
||||
|
||||
def git_src_dir(projects_yaml, project):
|
||||
"""
|
||||
Return the directory where the specified project's source is located.
|
||||
"""
|
||||
parent_dir = '/mnt/openstack-git'
|
||||
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
|
||||
if 'directory' in projects.keys():
|
||||
parent_dir = projects['directory']
|
||||
|
||||
for p in projects['repositories']:
|
||||
if p['name'] == project:
|
||||
return os.path.join(parent_dir, os.path.basename(p['repository']))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def git_yaml_value(projects_yaml, key):
|
||||
"""
|
||||
Return the value in projects_yaml for the specified key.
|
||||
"""
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
|
||||
if key in projects.keys():
|
||||
return projects[key]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def git_generate_systemd_init_files(templates_dir):
|
||||
"""
|
||||
Generate systemd init files.
|
||||
|
||||
Generates and installs systemd init units and script files based on the
|
||||
*.init.in files contained in the templates_dir directory.
|
||||
|
||||
This code is based on the openstack-pkg-tools package and its init
|
||||
script generation, which is used by the OpenStack packages.
|
||||
"""
|
||||
for f in os.listdir(templates_dir):
|
||||
# Create the init script and systemd unit file from the template
|
||||
if f.endswith(".init.in"):
|
||||
init_in_file = f
|
||||
init_file = f[:-8]
|
||||
service_file = "{}.service".format(init_file)
|
||||
|
||||
init_in_source = os.path.join(templates_dir, init_in_file)
|
||||
init_source = os.path.join(templates_dir, init_file)
|
||||
service_source = os.path.join(templates_dir, service_file)
|
||||
|
||||
init_dest = os.path.join('/etc/init.d', init_file)
|
||||
service_dest = os.path.join('/lib/systemd/system', service_file)
|
||||
|
||||
shutil.copyfile(init_in_source, init_source)
|
||||
with open(init_source, 'a') as outfile:
|
||||
template = ('/usr/share/openstack-pkg-tools/'
|
||||
'init-script-template')
|
||||
with open(template) as infile:
|
||||
outfile.write('\n\n{}'.format(infile.read()))
|
||||
|
||||
cmd = ['pkgos-gen-systemd-unit', init_in_source]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
if os.path.exists(init_dest):
|
||||
os.remove(init_dest)
|
||||
if os.path.exists(service_dest):
|
||||
os.remove(service_dest)
|
||||
shutil.copyfile(init_source, init_dest)
|
||||
shutil.copyfile(service_source, service_dest)
|
||||
os.chmod(init_dest, 0o755)
|
||||
|
||||
for f in os.listdir(templates_dir):
|
||||
# If there's a service.in file, use it instead of the generated one
|
||||
if f.endswith(".service.in"):
|
||||
service_in_file = f
|
||||
service_file = f[:-3]
|
||||
|
||||
service_in_source = os.path.join(templates_dir, service_in_file)
|
||||
service_source = os.path.join(templates_dir, service_file)
|
||||
service_dest = os.path.join('/lib/systemd/system', service_file)
|
||||
|
||||
shutil.copyfile(service_in_source, service_source)
|
||||
|
||||
if os.path.exists(service_dest):
|
||||
os.remove(service_dest)
|
||||
shutil.copyfile(service_source, service_dest)
|
||||
|
||||
for f in os.listdir(templates_dir):
|
||||
# Generate the systemd unit if there's no existing .service.in
|
||||
if f.endswith(".init.in"):
|
||||
init_in_file = f
|
||||
init_file = f[:-8]
|
||||
service_in_file = "{}.service.in".format(init_file)
|
||||
service_file = "{}.service".format(init_file)
|
||||
|
||||
init_in_source = os.path.join(templates_dir, init_in_file)
|
||||
service_in_source = os.path.join(templates_dir, service_in_file)
|
||||
service_source = os.path.join(templates_dir, service_file)
|
||||
service_dest = os.path.join('/lib/systemd/system', service_file)
|
||||
|
||||
if not os.path.exists(service_in_source):
|
||||
cmd = ['pkgos-gen-systemd-unit', init_in_source]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
if os.path.exists(service_dest):
|
||||
os.remove(service_dest)
|
||||
shutil.copyfile(service_source, service_dest)
|
||||
|
||||
|
||||
def git_determine_usr_bin():
|
||||
"""Return the /usr/bin path for Apache2 config.
|
||||
|
||||
The /usr/bin path will be located in the virtualenv if the charm
|
||||
is configured to deploy from source.
|
||||
"""
|
||||
if git_install_requested():
|
||||
projects_yaml = config('openstack-origin-git')
|
||||
projects_yaml = git_default_repos(projects_yaml)
|
||||
return os.path.join(git_pip_venv_dir(projects_yaml), 'bin')
|
||||
else:
|
||||
return '/usr/bin'
|
||||
|
||||
|
||||
def git_determine_python_path():
|
||||
"""Return the python-path for Apache2 config.
|
||||
|
||||
Returns 'None' unless the charm is configured to deploy from source,
|
||||
in which case the path of the virtualenv's site-packages is returned.
|
||||
"""
|
||||
if git_install_requested():
|
||||
projects_yaml = config('openstack-origin-git')
|
||||
projects_yaml = git_default_repos(projects_yaml)
|
||||
return os.path.join(git_pip_venv_dir(projects_yaml),
|
||||
'lib/python2.7/site-packages')
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def os_workload_status(configs, required_interfaces, charm_func=None):
|
||||
"""
|
||||
Decorator to set workload status based on complete contexts
|
||||
@ -1615,27 +1174,24 @@ def do_action_openstack_upgrade(package, upgrade_callback, configs):
|
||||
"""
|
||||
ret = False
|
||||
|
||||
if git_install_requested():
|
||||
action_set({'outcome': 'installed from source, skipped upgrade.'})
|
||||
else:
|
||||
if openstack_upgrade_available(package):
|
||||
if config('action-managed-upgrade'):
|
||||
juju_log('Upgrading OpenStack release')
|
||||
if openstack_upgrade_available(package):
|
||||
if config('action-managed-upgrade'):
|
||||
juju_log('Upgrading OpenStack release')
|
||||
|
||||
try:
|
||||
upgrade_callback(configs=configs)
|
||||
action_set({'outcome': 'success, upgrade completed.'})
|
||||
ret = True
|
||||
except Exception:
|
||||
action_set({'outcome': 'upgrade failed, see traceback.'})
|
||||
action_set({'traceback': traceback.format_exc()})
|
||||
action_fail('do_openstack_upgrade resulted in an '
|
||||
'unexpected error')
|
||||
else:
|
||||
action_set({'outcome': 'action-managed-upgrade config is '
|
||||
'False, skipped upgrade.'})
|
||||
try:
|
||||
upgrade_callback(configs=configs)
|
||||
action_set({'outcome': 'success, upgrade completed.'})
|
||||
ret = True
|
||||
except Exception:
|
||||
action_set({'outcome': 'upgrade failed, see traceback.'})
|
||||
action_set({'traceback': traceback.format_exc()})
|
||||
action_fail('do_openstack_upgrade resulted in an '
|
||||
'unexpected error')
|
||||
else:
|
||||
action_set({'outcome': 'no upgrade available.'})
|
||||
action_set({'outcome': 'action-managed-upgrade config is '
|
||||
'False, skipped upgrade.'})
|
||||
else:
|
||||
action_set({'outcome': 'no upgrade available.'})
|
||||
|
||||
return ret
|
||||
|
||||
@ -2045,14 +1601,25 @@ def token_cache_pkgs(source=None, release=None):
|
||||
|
||||
def update_json_file(filename, items):
|
||||
"""Updates the json `filename` with a given dict.
|
||||
:param filename: json filename (i.e.: /etc/glance/policy.json)
|
||||
:param filename: path to json file (e.g. /etc/glance/policy.json)
|
||||
:param items: dict of items to update
|
||||
"""
|
||||
if not items:
|
||||
return
|
||||
|
||||
with open(filename) as fd:
|
||||
policy = json.load(fd)
|
||||
|
||||
# Compare before and after and if nothing has changed don't write the file
|
||||
# since that could cause unnecessary service restarts.
|
||||
before = json.dumps(policy, indent=4, sort_keys=True)
|
||||
policy.update(items)
|
||||
after = json.dumps(policy, indent=4, sort_keys=True)
|
||||
if before == after:
|
||||
return
|
||||
|
||||
with open(filename, "w") as fd:
|
||||
fd.write(json.dumps(policy, indent=4))
|
||||
fd.write(after)
|
||||
|
||||
|
||||
@cached
|
||||
|
@ -113,7 +113,7 @@ def validator(value, valid_type, valid_range=None):
|
||||
assert isinstance(valid_range, list), \
|
||||
"valid_range must be a list, was given {}".format(valid_range)
|
||||
# If we're dealing with strings
|
||||
if valid_type is six.string_types:
|
||||
if isinstance(value, six.string_types):
|
||||
assert value in valid_range, \
|
||||
"{} is not in the list {}".format(value, valid_range)
|
||||
# Integer, float should have a min and max
|
||||
@ -517,7 +517,8 @@ def pool_set(service, pool_name, key, value):
|
||||
:param value:
|
||||
:return: None. Can raise CalledProcessError
|
||||
"""
|
||||
cmd = ['ceph', '--id', service, 'osd', 'pool', 'set', pool_name, key, value]
|
||||
cmd = ['ceph', '--id', service, 'osd', 'pool', 'set', pool_name, key,
|
||||
str(value).lower()]
|
||||
try:
|
||||
check_call(cmd)
|
||||
except CalledProcessError:
|
||||
@ -621,16 +622,24 @@ def create_erasure_profile(service, profile_name, erasure_plugin_name='jerasure'
|
||||
:param durability_estimator: int
|
||||
:return: None. Can raise CalledProcessError
|
||||
"""
|
||||
version = ceph_version()
|
||||
|
||||
# Ensure this failure_domain is allowed by Ceph
|
||||
validator(failure_domain, six.string_types,
|
||||
['chassis', 'datacenter', 'host', 'osd', 'pdu', 'pod', 'rack', 'region', 'room', 'root', 'row'])
|
||||
|
||||
cmd = ['ceph', '--id', service, 'osd', 'erasure-code-profile', 'set', profile_name,
|
||||
'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks),
|
||||
'ruleset_failure_domain=' + failure_domain]
|
||||
'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks)
|
||||
]
|
||||
if locality is not None and durability_estimator is not None:
|
||||
raise ValueError("create_erasure_profile should be called with k, m and one of l or c but not both.")
|
||||
|
||||
# failure_domain changed in luminous
|
||||
if version and version >= '12.0.0':
|
||||
cmd.append('crush-failure-domain=' + failure_domain)
|
||||
else:
|
||||
cmd.append('ruleset-failure-domain=' + failure_domain)
|
||||
|
||||
# Add plugin specific information
|
||||
if locality is not None:
|
||||
# For local erasure codes
|
||||
@ -1064,14 +1073,24 @@ class CephBrokerRq(object):
|
||||
self.ops = []
|
||||
|
||||
def add_op_request_access_to_group(self, name, namespace=None,
|
||||
permission=None, key_name=None):
|
||||
permission=None, key_name=None,
|
||||
object_prefix_permissions=None):
|
||||
"""
|
||||
Adds the requested permissions to the current service's Ceph key,
|
||||
allowing the key to access only the specified pools
|
||||
allowing the key to access only the specified pools or
|
||||
object prefixes. object_prefix_permissions should be a dictionary
|
||||
keyed on the permission with the corresponding value being a list
|
||||
of prefixes to apply that permission to.
|
||||
{
|
||||
'rwx': ['prefix1', 'prefix2'],
|
||||
'class-read': ['prefix3']}
|
||||
"""
|
||||
self.ops.append({'op': 'add-permissions-to-key', 'group': name,
|
||||
'namespace': namespace, 'name': key_name or service_name(),
|
||||
'group-permission': permission})
|
||||
self.ops.append({
|
||||
'op': 'add-permissions-to-key', 'group': name,
|
||||
'namespace': namespace,
|
||||
'name': key_name or service_name(),
|
||||
'group-permission': permission,
|
||||
'object-prefix-permissions': object_prefix_permissions})
|
||||
|
||||
def add_op_create_pool(self, name, replica_count=3, pg_num=None,
|
||||
weight=None, group=None, namespace=None):
|
||||
@ -1107,7 +1126,10 @@ class CephBrokerRq(object):
|
||||
def _ops_equal(self, other):
|
||||
if len(self.ops) == len(other.ops):
|
||||
for req_no in range(0, len(self.ops)):
|
||||
for key in ['replicas', 'name', 'op', 'pg_num', 'weight']:
|
||||
for key in [
|
||||
'replicas', 'name', 'op', 'pg_num', 'weight',
|
||||
'group', 'group-namespace', 'group-permission',
|
||||
'object-prefix-permissions']:
|
||||
if self.ops[req_no].get(key) != other.ops[req_no].get(key):
|
||||
return False
|
||||
else:
|
||||
|
@ -51,9 +51,7 @@ from charmhelpers.fetch import (
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.openstack.utils import (
|
||||
config_value_changed,
|
||||
configure_installation_source,
|
||||
git_install_requested,
|
||||
openstack_upgrade_available,
|
||||
is_unit_paused_set,
|
||||
pausable_restart_on_change as restart_on_change,
|
||||
@ -72,7 +70,6 @@ from charmhelpers.payload.execd import execd_preinstall
|
||||
from nova_compute_utils import (
|
||||
create_libvirt_secret,
|
||||
determine_packages,
|
||||
git_install,
|
||||
import_authorized_keys,
|
||||
import_keystone_ca_cert,
|
||||
initialize_ssh_keys,
|
||||
@ -135,9 +132,6 @@ def install():
|
||||
apt_update()
|
||||
apt_install(determine_packages(), fatal=True)
|
||||
|
||||
status_set('maintenance', 'Git install')
|
||||
git_install(config('openstack-origin-git'))
|
||||
|
||||
|
||||
@hooks.hook('config-changed')
|
||||
@restart_on_change(restart_map())
|
||||
@ -154,11 +148,7 @@ def config_changed():
|
||||
raise Exception(message)
|
||||
global CONFIGS
|
||||
send_remote_restart = False
|
||||
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('nova-common'):
|
||||
status_set('maintenance', 'Running openstack upgrade')
|
||||
do_openstack_upgrade(CONFIGS)
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import pwd
|
||||
import subprocess
|
||||
import platform
|
||||
@ -36,13 +35,9 @@ from charmhelpers.fetch import (
|
||||
|
||||
from charmhelpers.core.fstab import Fstab
|
||||
from charmhelpers.core.host import (
|
||||
adduser,
|
||||
add_group,
|
||||
add_user_to_group,
|
||||
mkdir,
|
||||
service_restart,
|
||||
lsb_release,
|
||||
write_file,
|
||||
rsync,
|
||||
CompareHostReleases,
|
||||
)
|
||||
@ -60,7 +55,6 @@ from charmhelpers.core.hookenv import (
|
||||
WARNING,
|
||||
)
|
||||
|
||||
from charmhelpers.core.templating import render
|
||||
from charmhelpers.core.decorators import retry_on_exception
|
||||
from charmhelpers.contrib.openstack import templating, context
|
||||
from charmhelpers.contrib.openstack.alternatives import install_alternative
|
||||
@ -68,13 +62,6 @@ from charmhelpers.contrib.openstack.alternatives import install_alternative
|
||||
from charmhelpers.contrib.openstack.utils import (
|
||||
configure_installation_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,
|
||||
reset_os_release,
|
||||
is_unit_paused_set,
|
||||
@ -85,10 +72,6 @@ from charmhelpers.contrib.openstack.utils import (
|
||||
CompareOpenStackReleases,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.python.packages import (
|
||||
pip_install,
|
||||
)
|
||||
|
||||
from charmhelpers.core.hugepage import hugepage_support
|
||||
|
||||
from nova_compute_context import (
|
||||
@ -130,61 +113,6 @@ BASE_PACKAGES = [
|
||||
|
||||
VERSION_PACKAGE = 'nova-common'
|
||||
|
||||
BASE_GIT_PACKAGES = [
|
||||
'libffi-dev',
|
||||
'libssl-dev',
|
||||
'libvirt-bin',
|
||||
'libxml2-dev',
|
||||
'libxslt1-dev',
|
||||
'libvirt-dev',
|
||||
'libyaml-dev',
|
||||
'openstack-pkg-tools',
|
||||
'python-dev',
|
||||
'python-pip',
|
||||
'python-setuptools',
|
||||
'zlib1g-dev',
|
||||
]
|
||||
|
||||
LATE_GIT_PACKAGES = [
|
||||
'bridge-utils',
|
||||
'dnsmasq-base',
|
||||
'dnsmasq-utils',
|
||||
'ebtables',
|
||||
'genisoimage',
|
||||
'iptables',
|
||||
'iputils-arping',
|
||||
'kpartx',
|
||||
'kvm',
|
||||
'netcat',
|
||||
'open-iscsi',
|
||||
'parted',
|
||||
'python-libvirt',
|
||||
'qemu',
|
||||
'qemu-system',
|
||||
'qemu-utils',
|
||||
'vlan',
|
||||
]
|
||||
|
||||
# ubuntu packages that should not be installed when deploying from git
|
||||
GIT_PACKAGE_BLACKLIST = [
|
||||
'neutron-plugin-openvswitch',
|
||||
'neutron-plugin-openvswitch-agent',
|
||||
'neutron-server',
|
||||
'nova-api',
|
||||
'nova-api-metadata',
|
||||
'nova-compute',
|
||||
'nova-compute-kvm',
|
||||
'nova-compute-lxc',
|
||||
'nova-compute-lxd',
|
||||
'nova-compute-qemu',
|
||||
'nova-compute-uml',
|
||||
'nova-network',
|
||||
'python-six',
|
||||
'quantum-plugin-openvswitch',
|
||||
'quantum-plugin-openvswitch-agent',
|
||||
'quantum-server',
|
||||
]
|
||||
|
||||
DEFAULT_INSTANCE_PATH = '/var/lib/nova/instances'
|
||||
NOVA_CONF_DIR = "/etc/nova"
|
||||
QEMU_CONF = '/etc/libvirt/qemu.conf'
|
||||
@ -445,14 +373,6 @@ def determine_packages():
|
||||
|
||||
packages.extend(determine_packages_arch())
|
||||
|
||||
if git_install_requested():
|
||||
packages = list(set(packages))
|
||||
packages.extend(BASE_GIT_PACKAGES)
|
||||
# don't include packages that will be installed from git
|
||||
for p in GIT_PACKAGE_BLACKLIST:
|
||||
if p in packages:
|
||||
packages.remove(p)
|
||||
|
||||
return packages
|
||||
|
||||
|
||||
@ -697,11 +617,10 @@ def destroy_libvirt_network(netname):
|
||||
|
||||
def configure_lxd(user='nova'):
|
||||
''' Configure lxd use for nova user '''
|
||||
if not git_install_requested():
|
||||
_release = lsb_release()['DISTRIB_CODENAME'].lower()
|
||||
if CompareHostReleases(_release) < "vivid":
|
||||
raise Exception("LXD is not supported for Ubuntu "
|
||||
"versions less than 15.04 (vivid)")
|
||||
_release = lsb_release()['DISTRIB_CODENAME'].lower()
|
||||
if CompareHostReleases(_release) < "vivid":
|
||||
raise Exception("LXD is not supported for Ubuntu "
|
||||
"versions less than 15.04 (vivid)")
|
||||
|
||||
configure_subuid(user)
|
||||
lxc_list(user)
|
||||
@ -741,168 +660,6 @@ def assert_charm_supports_ipv6():
|
||||
"versions less than Trusty 14.04")
|
||||
|
||||
|
||||
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='nova')
|
||||
git_post_install(projects_yaml)
|
||||
|
||||
|
||||
def git_pre_install():
|
||||
"""Perform pre-install setup."""
|
||||
dirs = [
|
||||
'/var/lib/nova',
|
||||
'/var/lib/nova/buckets',
|
||||
'/var/lib/nova/CA',
|
||||
'/var/lib/nova/CA/INTER',
|
||||
'/var/lib/nova/CA/newcerts',
|
||||
'/var/lib/nova/CA/private',
|
||||
'/var/lib/nova/CA/reqs',
|
||||
'/var/lib/nova/images',
|
||||
'/var/lib/nova/instances',
|
||||
'/var/lib/nova/keys',
|
||||
'/var/lib/nova/networks',
|
||||
'/var/lib/nova/tmp',
|
||||
'/var/log/nova',
|
||||
]
|
||||
|
||||
logs = [
|
||||
'/var/log/nova/nova-api.log',
|
||||
'/var/log/nova/nova-compute.log',
|
||||
'/var/log/nova/nova-manage.log',
|
||||
'/var/log/nova/nova-network.log',
|
||||
]
|
||||
|
||||
adduser('nova', shell='/bin/bash', system_user=True)
|
||||
check_call(['usermod', '--home', '/var/lib/nova', 'nova'])
|
||||
add_group('nova', system_group=True)
|
||||
add_user_to_group('nova', 'nova')
|
||||
add_user_to_group('nova', 'libvirtd')
|
||||
|
||||
for d in dirs:
|
||||
mkdir(d, owner='nova', group='nova', perms=0o0755, force=False)
|
||||
|
||||
for l in logs:
|
||||
write_file(l, '', owner='nova', group='nova', perms=0o0644)
|
||||
|
||||
|
||||
def git_post_install(projects_yaml):
|
||||
"""Perform post-install setup."""
|
||||
http_proxy = git_yaml_value(projects_yaml, 'http_proxy')
|
||||
if http_proxy:
|
||||
pip_install('libvirt-python', proxy=http_proxy,
|
||||
venv=git_pip_venv_dir(projects_yaml))
|
||||
else:
|
||||
pip_install('libvirt-python',
|
||||
venv=git_pip_venv_dir(projects_yaml))
|
||||
|
||||
src_etc = os.path.join(git_src_dir(projects_yaml, 'nova'), 'etc/nova')
|
||||
configs = [
|
||||
{'src': src_etc,
|
||||
'dest': '/etc/nova'},
|
||||
]
|
||||
|
||||
for c in configs:
|
||||
if os.path.exists(c['dest']):
|
||||
shutil.rmtree(c['dest'])
|
||||
shutil.copytree(c['src'], c['dest'])
|
||||
|
||||
# NOTE(coreycb): Need to find better solution than bin symlinks.
|
||||
symlinks = [
|
||||
{'src': os.path.join(git_pip_venv_dir(projects_yaml),
|
||||
'bin/nova-rootwrap'),
|
||||
'link': '/usr/local/bin/nova-rootwrap'},
|
||||
{'src': os.path.join(git_pip_venv_dir(projects_yaml),
|
||||
'bin/privsep-helper'),
|
||||
'link': '/usr/local/bin/privsep-helper'},
|
||||
]
|
||||
|
||||
for s in symlinks:
|
||||
if os.path.lexists(s['link']):
|
||||
os.remove(s['link'])
|
||||
os.symlink(s['src'], s['link'])
|
||||
|
||||
virt_type = VIRT_TYPES[config('virt-type')][0]
|
||||
nova_compute_conf = 'git/{}.conf'.format(virt_type)
|
||||
render(nova_compute_conf, '/etc/nova/nova-compute.conf', {}, perms=0o644)
|
||||
render('git/nova_sudoers', '/etc/sudoers.d/nova_sudoers', {}, perms=0o440)
|
||||
|
||||
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 = ['nova-api', 'nova-api-metadata', 'nova-compute',
|
||||
'nova-network']
|
||||
for daemon in daemons:
|
||||
nova_compute_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),
|
||||
nova_compute_context, perms=0o644)
|
||||
git_generate_systemd_init_files(templates_dir)
|
||||
else:
|
||||
service_name = 'nova-compute'
|
||||
nova_user = 'nova'
|
||||
start_dir = '/var/lib/nova'
|
||||
nova_conf = '/etc/nova/nova.conf'
|
||||
nova_api_context = {
|
||||
'service_description': 'Nova API server',
|
||||
'service_name': service_name,
|
||||
'user_name': nova_user,
|
||||
'start_dir': start_dir,
|
||||
'process_name': 'nova-api',
|
||||
'executable_name': os.path.join(bin_dir, 'nova-api'),
|
||||
'config_files': [nova_conf],
|
||||
}
|
||||
nova_api_metadata_context = {
|
||||
'service_description': 'Nova Metadata API server',
|
||||
'service_name': service_name,
|
||||
'user_name': nova_user,
|
||||
'start_dir': start_dir,
|
||||
'process_name': 'nova-api-metadata',
|
||||
'executable_name': os.path.join(bin_dir, 'nova-api-metadata'),
|
||||
'config_files': [nova_conf],
|
||||
}
|
||||
nova_compute_context = {
|
||||
'service_description': 'Nova compute worker',
|
||||
'service_name': service_name,
|
||||
'user_name': nova_user,
|
||||
'process_name': 'nova-compute',
|
||||
'executable_name': os.path.join(bin_dir, 'nova-compute'),
|
||||
'config_files': [nova_conf, '/etc/nova/nova-compute.conf'],
|
||||
}
|
||||
nova_network_context = {
|
||||
'service_description': 'Nova network worker',
|
||||
'service_name': service_name,
|
||||
'user_name': nova_user,
|
||||
'start_dir': start_dir,
|
||||
'process_name': 'nova-network',
|
||||
'executable_name': os.path.join(bin_dir, 'nova-network'),
|
||||
'config_files': [nova_conf],
|
||||
}
|
||||
templates_dir = 'hooks/charmhelpers/contrib/openstack/templates'
|
||||
templates_dir = os.path.join(charm_dir(), templates_dir)
|
||||
render('git.upstart', '/etc/init/nova-api-metadata.conf',
|
||||
nova_api_metadata_context, perms=0o644,
|
||||
templates_dir=templates_dir)
|
||||
render('git.upstart', '/etc/init/nova-api.conf',
|
||||
nova_api_context, perms=0o644,
|
||||
templates_dir=templates_dir)
|
||||
render('git/upstart/nova-compute.upstart',
|
||||
'/etc/init/nova-compute.conf',
|
||||
nova_compute_context, perms=0o644)
|
||||
render('git.upstart', '/etc/init/nova-network.conf',
|
||||
nova_network_context, perms=0o644,
|
||||
templates_dir=templates_dir)
|
||||
|
||||
apt_update()
|
||||
apt_install(LATE_GIT_PACKAGES, fatal=True)
|
||||
|
||||
|
||||
def get_hugepage_number():
|
||||
# TODO: defaults to 2M - this should probably be configurable
|
||||
# and support multiple pool sizes - e.g. 2M and 1G.
|
||||
|
@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: nova-api-metadata
|
||||
# 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: Nova API metadata server
|
||||
# Description: Frontend Nova API metadata server
|
||||
### 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 Compute metadata API"
|
||||
PROJECT_NAME=nova
|
||||
NAME=${PROJECT_NAME}-api-metadata
|
||||
DAEMON={{ daemon_path }}
|
@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: nova-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: Nova API server
|
||||
# Description: Frontend Nova API server
|
||||
### 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 Compute API"
|
||||
PROJECT_NAME=nova
|
||||
NAME=${PROJECT_NAME}-api
|
||||
DAEMON={{ daemon_path }}
|
@ -1,4 +0,0 @@
|
||||
[DEFAULT]
|
||||
compute_driver=libvirt.LibvirtDriver
|
||||
[libvirt]
|
||||
virt_type=kvm
|
@ -1,4 +0,0 @@
|
||||
[DEFAULT]
|
||||
compute_driver=libvirt.LibvirtDriver
|
||||
[libvirt]
|
||||
virt_type=lxc
|
@ -1,2 +0,0 @@
|
||||
[DEFAULT]
|
||||
compute_driver=nova_lxd.nova.virt.lxd.LXDDriver
|
@ -1,4 +0,0 @@
|
||||
[DEFAULT]
|
||||
compute_driver=libvirt.LibvirtDriver
|
||||
[libvirt]
|
||||
virt_type=qemu
|
@ -1,2 +0,0 @@
|
||||
[DEFAULT]
|
||||
compute_driver=vmwareapi.VMwareVCDriver
|
@ -1,4 +0,0 @@
|
||||
[DEFAULT]
|
||||
compute_driver=libvirt.LibvirtDriver
|
||||
[libvirt]
|
||||
virt_type=xen
|
@ -1,27 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: nova-compute
|
||||
# Required-Start: $network $local_fs $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs
|
||||
# Should-Start: libvirt-bin postgresql mysql keystone rabbitmq-server ntp neutron-ovs-cleanup
|
||||
# Should-Stop: libvirt-bin postgresql mysql keystone rabbitmq-server ntp
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Nova Compute server
|
||||
# Description: Provides compute server resources for the
|
||||
# OpenStack cloud computing system
|
||||
### 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 Compute"
|
||||
PROJECT_NAME=nova
|
||||
NAME=${PROJECT_NAME}-compute
|
||||
DAEMON={{ daemon_path }}
|
||||
DAEMON_ARGS=""
|
||||
if [ -f '/etc/nova/nova-compute.conf' ] ; then
|
||||
DAEMON_ARGS="--config-file=/etc/nova/nova-compute.conf"
|
||||
fi
|
||||
|
@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: nova-network
|
||||
# Required-Start: $network $local_fs $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs
|
||||
# Should-Start: postgresql mysql keystone
|
||||
# Should-Stop: postgresql mysql keystone
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Nova Network
|
||||
# Description: Provides network resources
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Thomas Goirand <zigo@debian.org>
|
||||
|
||||
DESC="OpenStack Compute Network"
|
||||
PROJECT_NAME=nova
|
||||
NAME=${PROJECT_NAME}-network
|
||||
DAEMON={{ daemon_path }}
|
@ -1,4 +0,0 @@
|
||||
Defaults:nova !requiretty
|
||||
|
||||
nova ALL = (root) NOPASSWD: /usr/local/bin/nova-rootwrap /etc/nova/rootwrap.conf *
|
||||
|
@ -1 +0,0 @@
|
||||
include /var/lib/nova/volumes/*
|
@ -1,27 +0,0 @@
|
||||
description "{{ service_description }}"
|
||||
author "Juju {{ service_name }} Charm <juju@localhost>"
|
||||
|
||||
start on runlevel [2345]
|
||||
stop on runlevel [!2345]
|
||||
|
||||
chdir /var/run
|
||||
|
||||
pre-start script
|
||||
mkdir -p /var/run/nova
|
||||
chown nova:root /var/run/nova/
|
||||
|
||||
mkdir -p /var/lock/nova
|
||||
chown nova:root /var/lock/nova/
|
||||
|
||||
modprobe nbd
|
||||
|
||||
# If libvirt-bin is installed, always wait for it to start first
|
||||
if status libvirt-bin; then
|
||||
start wait-for-state WAIT_FOR=libvirt-bin WAIT_STATE=running WAITER={{ process_name }}
|
||||
fi
|
||||
end script
|
||||
|
||||
exec start-stop-daemon --start --chuid {{ user_name }} --exec {{ executable_name }} -- \
|
||||
{% for config_file in config_files -%}
|
||||
--config-file={{ config_file }} \
|
||||
{% endfor -%}
|
@ -13,8 +13,6 @@
|
||||
# limitations under the License.
|
||||
|
||||
import amulet
|
||||
import os
|
||||
import yaml
|
||||
|
||||
from charmhelpers.contrib.openstack.amulet.deployment import (
|
||||
OpenStackAmuletDeployment
|
||||
@ -52,11 +50,10 @@ class NovaBasicDeployment(OpenStackAmuletDeployment):
|
||||
"""Amulet tests on a basic nova compute deployment."""
|
||||
|
||||
def __init__(self, series=None, openstack=None, source=None,
|
||||
git=False, stable=False):
|
||||
stable=False):
|
||||
"""Deploy the entire test environment."""
|
||||
super(NovaBasicDeployment, self).__init__(series, openstack,
|
||||
source, stable)
|
||||
self.git = git
|
||||
self._add_services()
|
||||
self._add_relations()
|
||||
self._configure_services()
|
||||
@ -137,41 +134,6 @@ class NovaBasicDeployment(OpenStackAmuletDeployment):
|
||||
'enable-live-migration': 'False',
|
||||
'aa-profile-mode': 'enforce'}
|
||||
nova_cc_config = {}
|
||||
if self.git:
|
||||
amulet_http_proxy = os.environ.get('AMULET_HTTP_PROXY')
|
||||
|
||||
reqs_repo = 'git://github.com/openstack/requirements'
|
||||
neutron_repo = 'git://github.com/openstack/neutron'
|
||||
nova_repo = 'git://github.com/openstack/nova'
|
||||
if self._get_openstack_release() == self.trusty_icehouse:
|
||||
reqs_repo = 'git://github.com/coreycb/requirements'
|
||||
neutron_repo = 'git://github.com/coreycb/neutron'
|
||||
nova_repo = 'git://github.com/coreycb/nova'
|
||||
|
||||
branch = 'stable/' + self._get_openstack_release_string()
|
||||
|
||||
openstack_origin_git = {
|
||||
'repositories': [
|
||||
{'name': 'requirements',
|
||||
'repository': reqs_repo,
|
||||
'branch': branch},
|
||||
{'name': 'neutron',
|
||||
'repository': neutron_repo,
|
||||
'branch': branch},
|
||||
{'name': 'nova',
|
||||
'repository': nova_repo,
|
||||
'branch': branch},
|
||||
],
|
||||
'directory': '/mnt/openstack-git',
|
||||
'http_proxy': amulet_http_proxy,
|
||||
'https_proxy': amulet_http_proxy,
|
||||
}
|
||||
nova_config['openstack-origin-git'] = \
|
||||
yaml.dump(openstack_origin_git)
|
||||
|
||||
nova_cc_config['openstack-origin-git'] = \
|
||||
yaml.dump(openstack_origin_git)
|
||||
|
||||
if self._get_openstack_release() >= self.xenial_ocata:
|
||||
nova_cc_config['network-manager'] = 'Neutron'
|
||||
|
||||
|
@ -23,7 +23,6 @@ import sys
|
||||
import re
|
||||
import itertools
|
||||
import functools
|
||||
import shutil
|
||||
|
||||
import six
|
||||
import traceback
|
||||
@ -47,7 +46,6 @@ from charmhelpers.core.hookenv import (
|
||||
related_units,
|
||||
relation_ids,
|
||||
relation_set,
|
||||
service_name,
|
||||
status_set,
|
||||
hook_name,
|
||||
application_version_set,
|
||||
@ -68,11 +66,6 @@ from charmhelpers.contrib.network.ip import (
|
||||
port_has_listener,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.python.packages import (
|
||||
pip_create_virtualenv,
|
||||
pip_install,
|
||||
)
|
||||
|
||||
from charmhelpers.core.host import (
|
||||
lsb_release,
|
||||
mounts,
|
||||
@ -84,7 +77,6 @@ from charmhelpers.core.host import (
|
||||
)
|
||||
from charmhelpers.fetch import (
|
||||
apt_cache,
|
||||
install_remote,
|
||||
import_key as fetch_import_key,
|
||||
add_source as fetch_add_source,
|
||||
SourceConfigError,
|
||||
@ -278,27 +270,6 @@ PACKAGE_CODENAMES = {
|
||||
]),
|
||||
}
|
||||
|
||||
GIT_DEFAULT_REPOS = {
|
||||
'requirements': 'git://github.com/openstack/requirements',
|
||||
'cinder': 'git://github.com/openstack/cinder',
|
||||
'glance': 'git://github.com/openstack/glance',
|
||||
'horizon': 'git://github.com/openstack/horizon',
|
||||
'keystone': 'git://github.com/openstack/keystone',
|
||||
'networking-hyperv': 'git://github.com/openstack/networking-hyperv',
|
||||
'neutron': 'git://github.com/openstack/neutron',
|
||||
'neutron-fwaas': 'git://github.com/openstack/neutron-fwaas',
|
||||
'neutron-lbaas': 'git://github.com/openstack/neutron-lbaas',
|
||||
'neutron-vpnaas': 'git://github.com/openstack/neutron-vpnaas',
|
||||
'nova': 'git://github.com/openstack/nova',
|
||||
}
|
||||
|
||||
GIT_DEFAULT_BRANCHES = {
|
||||
'liberty': 'stable/liberty',
|
||||
'mitaka': 'stable/mitaka',
|
||||
'newton': 'stable/newton',
|
||||
'master': 'master',
|
||||
}
|
||||
|
||||
DEFAULT_LOOPBACK_SIZE = '5G'
|
||||
|
||||
|
||||
@ -530,7 +501,6 @@ def os_release(package, base='essex', reset_cache=False):
|
||||
if _os_rel:
|
||||
return _os_rel
|
||||
_os_rel = (
|
||||
git_os_codename_install_source(config('openstack-origin-git')) or
|
||||
get_os_codename_package(package, fatal=False) or
|
||||
get_os_codename_install_source(config('openstack-origin')) or
|
||||
base)
|
||||
@ -771,417 +741,6 @@ def os_requires_version(ostack_release, pkg):
|
||||
return wrap
|
||||
|
||||
|
||||
def git_install_requested():
|
||||
"""
|
||||
Returns true if openstack-origin-git is specified.
|
||||
"""
|
||||
return config('openstack-origin-git') is not None
|
||||
|
||||
|
||||
def git_os_codename_install_source(projects_yaml):
|
||||
"""
|
||||
Returns OpenStack codename of release being installed from source.
|
||||
"""
|
||||
if git_install_requested():
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
|
||||
if projects in GIT_DEFAULT_BRANCHES.keys():
|
||||
if projects == 'master':
|
||||
return 'ocata'
|
||||
return projects
|
||||
|
||||
if 'release' in projects:
|
||||
if projects['release'] == 'master':
|
||||
return 'ocata'
|
||||
return projects['release']
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def git_default_repos(projects_yaml):
|
||||
"""
|
||||
Returns default repos if a default openstack-origin-git value is specified.
|
||||
"""
|
||||
service = service_name()
|
||||
core_project = service
|
||||
|
||||
for default, branch in six.iteritems(GIT_DEFAULT_BRANCHES):
|
||||
if projects_yaml == default:
|
||||
|
||||
# add the requirements repo first
|
||||
repo = {
|
||||
'name': 'requirements',
|
||||
'repository': GIT_DEFAULT_REPOS['requirements'],
|
||||
'branch': branch,
|
||||
}
|
||||
repos = [repo]
|
||||
|
||||
# neutron-* and nova-* charms require some additional repos
|
||||
if service in ['neutron-api', 'neutron-gateway',
|
||||
'neutron-openvswitch']:
|
||||
core_project = 'neutron'
|
||||
if service == 'neutron-api':
|
||||
repo = {
|
||||
'name': 'networking-hyperv',
|
||||
'repository': GIT_DEFAULT_REPOS['networking-hyperv'],
|
||||
'branch': branch,
|
||||
}
|
||||
repos.append(repo)
|
||||
for project in ['neutron-fwaas', 'neutron-lbaas',
|
||||
'neutron-vpnaas', 'nova']:
|
||||
repo = {
|
||||
'name': project,
|
||||
'repository': GIT_DEFAULT_REPOS[project],
|
||||
'branch': branch,
|
||||
}
|
||||
repos.append(repo)
|
||||
|
||||
elif service in ['nova-cloud-controller', 'nova-compute']:
|
||||
core_project = 'nova'
|
||||
repo = {
|
||||
'name': 'neutron',
|
||||
'repository': GIT_DEFAULT_REPOS['neutron'],
|
||||
'branch': branch,
|
||||
}
|
||||
repos.append(repo)
|
||||
elif service == 'openstack-dashboard':
|
||||
core_project = 'horizon'
|
||||
|
||||
# finally add the current service's core project repo
|
||||
repo = {
|
||||
'name': core_project,
|
||||
'repository': GIT_DEFAULT_REPOS[core_project],
|
||||
'branch': branch,
|
||||
}
|
||||
repos.append(repo)
|
||||
|
||||
return yaml.dump(dict(repositories=repos, release=default))
|
||||
|
||||
return projects_yaml
|
||||
|
||||
|
||||
def _git_yaml_load(projects_yaml):
|
||||
"""
|
||||
Load the specified yaml into a dictionary.
|
||||
"""
|
||||
if not projects_yaml:
|
||||
return None
|
||||
|
||||
return yaml.load(projects_yaml)
|
||||
|
||||
|
||||
requirements_dir = None
|
||||
|
||||
|
||||
def git_clone_and_install(projects_yaml, core_project):
|
||||
"""
|
||||
Clone/install all specified OpenStack repositories.
|
||||
|
||||
The expected format of projects_yaml is:
|
||||
|
||||
repositories:
|
||||
- {name: keystone,
|
||||
repository: 'git://git.openstack.org/openstack/keystone.git',
|
||||
branch: 'stable/icehouse'}
|
||||
- {name: requirements,
|
||||
repository: 'git://git.openstack.org/openstack/requirements.git',
|
||||
branch: 'stable/icehouse'}
|
||||
|
||||
directory: /mnt/openstack-git
|
||||
http_proxy: squid-proxy-url
|
||||
https_proxy: squid-proxy-url
|
||||
|
||||
The directory, http_proxy, and https_proxy keys are optional.
|
||||
|
||||
"""
|
||||
global requirements_dir
|
||||
parent_dir = '/mnt/openstack-git'
|
||||
http_proxy = None
|
||||
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
_git_validate_projects_yaml(projects, core_project)
|
||||
|
||||
old_environ = dict(os.environ)
|
||||
|
||||
if 'http_proxy' in projects.keys():
|
||||
http_proxy = projects['http_proxy']
|
||||
os.environ['http_proxy'] = projects['http_proxy']
|
||||
if 'https_proxy' in projects.keys():
|
||||
os.environ['https_proxy'] = projects['https_proxy']
|
||||
|
||||
if 'directory' in projects.keys():
|
||||
parent_dir = projects['directory']
|
||||
|
||||
pip_create_virtualenv(os.path.join(parent_dir, 'venv'))
|
||||
|
||||
# Upgrade setuptools and pip from default virtualenv versions. The default
|
||||
# versions in trusty break master OpenStack branch deployments.
|
||||
for p in ['pip', 'setuptools']:
|
||||
pip_install(p, upgrade=True, proxy=http_proxy,
|
||||
venv=os.path.join(parent_dir, 'venv'))
|
||||
|
||||
constraints = None
|
||||
for p in projects['repositories']:
|
||||
repo = p['repository']
|
||||
branch = p['branch']
|
||||
depth = '1'
|
||||
if 'depth' in p.keys():
|
||||
depth = p['depth']
|
||||
if p['name'] == 'requirements':
|
||||
repo_dir = _git_clone_and_install_single(repo, branch, depth,
|
||||
parent_dir, http_proxy,
|
||||
update_requirements=False)
|
||||
requirements_dir = repo_dir
|
||||
constraints = os.path.join(repo_dir, "upper-constraints.txt")
|
||||
# upper-constraints didn't exist until after icehouse
|
||||
if not os.path.isfile(constraints):
|
||||
constraints = None
|
||||
# use constraints unless project yaml sets use_constraints to false
|
||||
if 'use_constraints' in projects.keys():
|
||||
if not projects['use_constraints']:
|
||||
constraints = None
|
||||
else:
|
||||
repo_dir = _git_clone_and_install_single(repo, branch, depth,
|
||||
parent_dir, http_proxy,
|
||||
update_requirements=True,
|
||||
constraints=constraints)
|
||||
|
||||
os.environ = old_environ
|
||||
|
||||
|
||||
def _git_validate_projects_yaml(projects, core_project):
|
||||
"""
|
||||
Validate the projects yaml.
|
||||
"""
|
||||
_git_ensure_key_exists('repositories', projects)
|
||||
|
||||
for project in projects['repositories']:
|
||||
_git_ensure_key_exists('name', project.keys())
|
||||
_git_ensure_key_exists('repository', project.keys())
|
||||
_git_ensure_key_exists('branch', project.keys())
|
||||
|
||||
if projects['repositories'][0]['name'] != 'requirements':
|
||||
error_out('{} git repo must be specified first'.format('requirements'))
|
||||
|
||||
if projects['repositories'][-1]['name'] != core_project:
|
||||
error_out('{} git repo must be specified last'.format(core_project))
|
||||
|
||||
_git_ensure_key_exists('release', projects)
|
||||
|
||||
|
||||
def _git_ensure_key_exists(key, keys):
|
||||
"""
|
||||
Ensure that key exists in keys.
|
||||
"""
|
||||
if key not in keys:
|
||||
error_out('openstack-origin-git key \'{}\' is missing'.format(key))
|
||||
|
||||
|
||||
def _git_clone_and_install_single(repo, branch, depth, parent_dir, http_proxy,
|
||||
update_requirements, constraints=None):
|
||||
"""
|
||||
Clone and install a single git repository.
|
||||
"""
|
||||
if not os.path.exists(parent_dir):
|
||||
juju_log('Directory already exists at {}. '
|
||||
'No need to create directory.'.format(parent_dir))
|
||||
os.mkdir(parent_dir)
|
||||
|
||||
juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch))
|
||||
repo_dir = install_remote(
|
||||
repo, dest=parent_dir, branch=branch, depth=depth)
|
||||
|
||||
venv = os.path.join(parent_dir, 'venv')
|
||||
|
||||
if update_requirements:
|
||||
if not requirements_dir:
|
||||
error_out('requirements repo must be cloned before '
|
||||
'updating from global requirements.')
|
||||
_git_update_requirements(venv, repo_dir, requirements_dir)
|
||||
|
||||
juju_log('Installing git repo from dir: {}'.format(repo_dir))
|
||||
if http_proxy:
|
||||
pip_install(repo_dir, proxy=http_proxy, venv=venv,
|
||||
constraints=constraints)
|
||||
else:
|
||||
pip_install(repo_dir, venv=venv, constraints=constraints)
|
||||
|
||||
return repo_dir
|
||||
|
||||
|
||||
def _git_update_requirements(venv, package_dir, reqs_dir):
|
||||
"""
|
||||
Update from global requirements.
|
||||
|
||||
Update an OpenStack git directory's requirements.txt and
|
||||
test-requirements.txt from global-requirements.txt.
|
||||
"""
|
||||
orig_dir = os.getcwd()
|
||||
os.chdir(reqs_dir)
|
||||
python = os.path.join(venv, 'bin/python')
|
||||
cmd = [python, 'update.py', package_dir]
|
||||
try:
|
||||
subprocess.check_call(cmd)
|
||||
except subprocess.CalledProcessError:
|
||||
package = os.path.basename(package_dir)
|
||||
error_out("Error updating {} from "
|
||||
"global-requirements.txt".format(package))
|
||||
os.chdir(orig_dir)
|
||||
|
||||
|
||||
def git_pip_venv_dir(projects_yaml):
|
||||
"""
|
||||
Return the pip virtualenv path.
|
||||
"""
|
||||
parent_dir = '/mnt/openstack-git'
|
||||
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
|
||||
if 'directory' in projects.keys():
|
||||
parent_dir = projects['directory']
|
||||
|
||||
return os.path.join(parent_dir, 'venv')
|
||||
|
||||
|
||||
def git_src_dir(projects_yaml, project):
|
||||
"""
|
||||
Return the directory where the specified project's source is located.
|
||||
"""
|
||||
parent_dir = '/mnt/openstack-git'
|
||||
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
|
||||
if 'directory' in projects.keys():
|
||||
parent_dir = projects['directory']
|
||||
|
||||
for p in projects['repositories']:
|
||||
if p['name'] == project:
|
||||
return os.path.join(parent_dir, os.path.basename(p['repository']))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def git_yaml_value(projects_yaml, key):
|
||||
"""
|
||||
Return the value in projects_yaml for the specified key.
|
||||
"""
|
||||
projects = _git_yaml_load(projects_yaml)
|
||||
|
||||
if key in projects.keys():
|
||||
return projects[key]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def git_generate_systemd_init_files(templates_dir):
|
||||
"""
|
||||
Generate systemd init files.
|
||||
|
||||
Generates and installs systemd init units and script files based on the
|
||||
*.init.in files contained in the templates_dir directory.
|
||||
|
||||
This code is based on the openstack-pkg-tools package and its init
|
||||
script generation, which is used by the OpenStack packages.
|
||||
"""
|
||||
for f in os.listdir(templates_dir):
|
||||
# Create the init script and systemd unit file from the template
|
||||
if f.endswith(".init.in"):
|
||||
init_in_file = f
|
||||
init_file = f[:-8]
|
||||
service_file = "{}.service".format(init_file)
|
||||
|
||||
init_in_source = os.path.join(templates_dir, init_in_file)
|
||||
init_source = os.path.join(templates_dir, init_file)
|
||||
service_source = os.path.join(templates_dir, service_file)
|
||||
|
||||
init_dest = os.path.join('/etc/init.d', init_file)
|
||||
service_dest = os.path.join('/lib/systemd/system', service_file)
|
||||
|
||||
shutil.copyfile(init_in_source, init_source)
|
||||
with open(init_source, 'a') as outfile:
|
||||
template = ('/usr/share/openstack-pkg-tools/'
|
||||
'init-script-template')
|
||||
with open(template) as infile:
|
||||
outfile.write('\n\n{}'.format(infile.read()))
|
||||
|
||||
cmd = ['pkgos-gen-systemd-unit', init_in_source]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
if os.path.exists(init_dest):
|
||||
os.remove(init_dest)
|
||||
if os.path.exists(service_dest):
|
||||
os.remove(service_dest)
|
||||
shutil.copyfile(init_source, init_dest)
|
||||
shutil.copyfile(service_source, service_dest)
|
||||
os.chmod(init_dest, 0o755)
|
||||
|
||||
for f in os.listdir(templates_dir):
|
||||
# If there's a service.in file, use it instead of the generated one
|
||||
if f.endswith(".service.in"):
|
||||
service_in_file = f
|
||||
service_file = f[:-3]
|
||||
|
||||
service_in_source = os.path.join(templates_dir, service_in_file)
|
||||
service_source = os.path.join(templates_dir, service_file)
|
||||
service_dest = os.path.join('/lib/systemd/system', service_file)
|
||||
|
||||
shutil.copyfile(service_in_source, service_source)
|
||||
|
||||
if os.path.exists(service_dest):
|
||||
os.remove(service_dest)
|
||||
shutil.copyfile(service_source, service_dest)
|
||||
|
||||
for f in os.listdir(templates_dir):
|
||||
# Generate the systemd unit if there's no existing .service.in
|
||||
if f.endswith(".init.in"):
|
||||
init_in_file = f
|
||||
init_file = f[:-8]
|
||||
service_in_file = "{}.service.in".format(init_file)
|
||||
service_file = "{}.service".format(init_file)
|
||||
|
||||
init_in_source = os.path.join(templates_dir, init_in_file)
|
||||
service_in_source = os.path.join(templates_dir, service_in_file)
|
||||
service_source = os.path.join(templates_dir, service_file)
|
||||
service_dest = os.path.join('/lib/systemd/system', service_file)
|
||||
|
||||
if not os.path.exists(service_in_source):
|
||||
cmd = ['pkgos-gen-systemd-unit', init_in_source]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
if os.path.exists(service_dest):
|
||||
os.remove(service_dest)
|
||||
shutil.copyfile(service_source, service_dest)
|
||||
|
||||
|
||||
def git_determine_usr_bin():
|
||||
"""Return the /usr/bin path for Apache2 config.
|
||||
|
||||
The /usr/bin path will be located in the virtualenv if the charm
|
||||
is configured to deploy from source.
|
||||
"""
|
||||
if git_install_requested():
|
||||
projects_yaml = config('openstack-origin-git')
|
||||
projects_yaml = git_default_repos(projects_yaml)
|
||||
return os.path.join(git_pip_venv_dir(projects_yaml), 'bin')
|
||||
else:
|
||||
return '/usr/bin'
|
||||
|
||||
|
||||
def git_determine_python_path():
|
||||
"""Return the python-path for Apache2 config.
|
||||
|
||||
Returns 'None' unless the charm is configured to deploy from source,
|
||||
in which case the path of the virtualenv's site-packages is returned.
|
||||
"""
|
||||
if git_install_requested():
|
||||
projects_yaml = config('openstack-origin-git')
|
||||
projects_yaml = git_default_repos(projects_yaml)
|
||||
return os.path.join(git_pip_venv_dir(projects_yaml),
|
||||
'lib/python2.7/site-packages')
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def os_workload_status(configs, required_interfaces, charm_func=None):
|
||||
"""
|
||||
Decorator to set workload status based on complete contexts
|
||||
@ -1615,27 +1174,24 @@ def do_action_openstack_upgrade(package, upgrade_callback, configs):
|
||||
"""
|
||||
ret = False
|
||||
|
||||
if git_install_requested():
|
||||
action_set({'outcome': 'installed from source, skipped upgrade.'})
|
||||
else:
|
||||
if openstack_upgrade_available(package):
|
||||
if config('action-managed-upgrade'):
|
||||
juju_log('Upgrading OpenStack release')
|
||||
if openstack_upgrade_available(package):
|
||||
if config('action-managed-upgrade'):
|
||||
juju_log('Upgrading OpenStack release')
|
||||
|
||||
try:
|
||||
upgrade_callback(configs=configs)
|
||||
action_set({'outcome': 'success, upgrade completed.'})
|
||||
ret = True
|
||||
except Exception:
|
||||
action_set({'outcome': 'upgrade failed, see traceback.'})
|
||||
action_set({'traceback': traceback.format_exc()})
|
||||
action_fail('do_openstack_upgrade resulted in an '
|
||||
'unexpected error')
|
||||
else:
|
||||
action_set({'outcome': 'action-managed-upgrade config is '
|
||||
'False, skipped upgrade.'})
|
||||
try:
|
||||
upgrade_callback(configs=configs)
|
||||
action_set({'outcome': 'success, upgrade completed.'})
|
||||
ret = True
|
||||
except Exception:
|
||||
action_set({'outcome': 'upgrade failed, see traceback.'})
|
||||
action_set({'traceback': traceback.format_exc()})
|
||||
action_fail('do_openstack_upgrade resulted in an '
|
||||
'unexpected error')
|
||||
else:
|
||||
action_set({'outcome': 'no upgrade available.'})
|
||||
action_set({'outcome': 'action-managed-upgrade config is '
|
||||
'False, skipped upgrade.'})
|
||||
else:
|
||||
action_set({'outcome': 'no upgrade available.'})
|
||||
|
||||
return ret
|
||||
|
||||
@ -2045,14 +1601,25 @@ def token_cache_pkgs(source=None, release=None):
|
||||
|
||||
def update_json_file(filename, items):
|
||||
"""Updates the json `filename` with a given dict.
|
||||
:param filename: json filename (i.e.: /etc/glance/policy.json)
|
||||
:param filename: path to json file (e.g. /etc/glance/policy.json)
|
||||
:param items: dict of items to update
|
||||
"""
|
||||
if not items:
|
||||
return
|
||||
|
||||
with open(filename) as fd:
|
||||
policy = json.load(fd)
|
||||
|
||||
# Compare before and after and if nothing has changed don't write the file
|
||||
# since that could cause unnecessary service restarts.
|
||||
before = json.dumps(policy, indent=4, sort_keys=True)
|
||||
policy.update(items)
|
||||
after = json.dumps(policy, indent=4, sort_keys=True)
|
||||
if before == after:
|
||||
return
|
||||
|
||||
with open(filename, "w") as fd:
|
||||
fd.write(json.dumps(policy, indent=4))
|
||||
fd.write(after)
|
||||
|
||||
|
||||
@cached
|
||||
|
@ -113,7 +113,7 @@ def validator(value, valid_type, valid_range=None):
|
||||
assert isinstance(valid_range, list), \
|
||||
"valid_range must be a list, was given {}".format(valid_range)
|
||||
# If we're dealing with strings
|
||||
if valid_type is six.string_types:
|
||||
if isinstance(value, six.string_types):
|
||||
assert value in valid_range, \
|
||||
"{} is not in the list {}".format(value, valid_range)
|
||||
# Integer, float should have a min and max
|
||||
@ -517,7 +517,8 @@ def pool_set(service, pool_name, key, value):
|
||||
:param value:
|
||||
:return: None. Can raise CalledProcessError
|
||||
"""
|
||||
cmd = ['ceph', '--id', service, 'osd', 'pool', 'set', pool_name, key, value]
|
||||
cmd = ['ceph', '--id', service, 'osd', 'pool', 'set', pool_name, key,
|
||||
str(value).lower()]
|
||||
try:
|
||||
check_call(cmd)
|
||||
except CalledProcessError:
|
||||
@ -621,16 +622,24 @@ def create_erasure_profile(service, profile_name, erasure_plugin_name='jerasure'
|
||||
:param durability_estimator: int
|
||||
:return: None. Can raise CalledProcessError
|
||||
"""
|
||||
version = ceph_version()
|
||||
|
||||
# Ensure this failure_domain is allowed by Ceph
|
||||
validator(failure_domain, six.string_types,
|
||||
['chassis', 'datacenter', 'host', 'osd', 'pdu', 'pod', 'rack', 'region', 'room', 'root', 'row'])
|
||||
|
||||
cmd = ['ceph', '--id', service, 'osd', 'erasure-code-profile', 'set', profile_name,
|
||||
'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks),
|
||||
'ruleset_failure_domain=' + failure_domain]
|
||||
'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks)
|
||||
]
|
||||
if locality is not None and durability_estimator is not None:
|
||||
raise ValueError("create_erasure_profile should be called with k, m and one of l or c but not both.")
|
||||
|
||||
# failure_domain changed in luminous
|
||||
if version and version >= '12.0.0':
|
||||
cmd.append('crush-failure-domain=' + failure_domain)
|
||||
else:
|
||||
cmd.append('ruleset-failure-domain=' + failure_domain)
|
||||
|
||||
# Add plugin specific information
|
||||
if locality is not None:
|
||||
# For local erasure codes
|
||||
@ -1064,14 +1073,24 @@ class CephBrokerRq(object):
|
||||
self.ops = []
|
||||
|
||||
def add_op_request_access_to_group(self, name, namespace=None,
|
||||
permission=None, key_name=None):
|
||||
permission=None, key_name=None,
|
||||
object_prefix_permissions=None):
|
||||
"""
|
||||
Adds the requested permissions to the current service's Ceph key,
|
||||
allowing the key to access only the specified pools
|
||||
allowing the key to access only the specified pools or
|
||||
object prefixes. object_prefix_permissions should be a dictionary
|
||||
keyed on the permission with the corresponding value being a list
|
||||
of prefixes to apply that permission to.
|
||||
{
|
||||
'rwx': ['prefix1', 'prefix2'],
|
||||
'class-read': ['prefix3']}
|
||||
"""
|
||||
self.ops.append({'op': 'add-permissions-to-key', 'group': name,
|
||||
'namespace': namespace, 'name': key_name or service_name(),
|
||||
'group-permission': permission})
|
||||
self.ops.append({
|
||||
'op': 'add-permissions-to-key', 'group': name,
|
||||
'namespace': namespace,
|
||||
'name': key_name or service_name(),
|
||||
'group-permission': permission,
|
||||
'object-prefix-permissions': object_prefix_permissions})
|
||||
|
||||
def add_op_create_pool(self, name, replica_count=3, pg_num=None,
|
||||
weight=None, group=None, namespace=None):
|
||||
@ -1107,7 +1126,10 @@ class CephBrokerRq(object):
|
||||
def _ops_equal(self, other):
|
||||
if len(self.ops) == len(other.ops):
|
||||
for req_no in range(0, len(self.ops)):
|
||||
for key in ['replicas', 'name', 'op', 'pg_num', 'weight']:
|
||||
for key in [
|
||||
'replicas', 'name', 'op', 'pg_num', 'weight',
|
||||
'group', 'group-namespace', 'group-permission',
|
||||
'object-prefix-permissions']:
|
||||
if self.ops[req_no].get(key) != other.ops[req_no].get(key):
|
||||
return False
|
||||
else:
|
||||
|
@ -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 nova compute git deployment on trusty-icehouse."""
|
||||
|
||||
from basic_deployment import NovaBasicDeployment
|
||||
|
||||
if __name__ == '__main__':
|
||||
deployment = NovaBasicDeployment(series='trusty', git=True)
|
||||
deployment.run_tests()
|
@ -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 nova-compute git deployment on trusty-kilo."""
|
||||
|
||||
from basic_deployment import NovaBasicDeployment
|
||||
|
||||
if __name__ == '__main__':
|
||||
deployment = NovaBasicDeployment(series='trusty',
|
||||
openstack='cloud:trusty-kilo',
|
||||
source='cloud:trusty-updates/kilo',
|
||||
git=True)
|
||||
deployment.run_tests()
|
@ -13,6 +13,12 @@
|
||||
# limitations under the License.
|
||||
|
||||
import sys
|
||||
from mock import MagicMock
|
||||
|
||||
# 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()
|
||||
|
||||
sys.path.append('actions/')
|
||||
sys.path.append('hooks/')
|
||||
|
@ -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 sys
|
||||
|
||||
from mock import patch, MagicMock
|
||||
|
||||
# python-apt is not installed as part of test-requirements but is imported by
|
||||
# some charmhelpers modules so create a fake import.
|
||||
sys.modules['apt'] = MagicMock()
|
||||
sys.modules['apt_pkg'] = MagicMock()
|
||||
|
||||
with patch('charmhelpers.core.hookenv.config') as config:
|
||||
config.return_value = 'nova'
|
||||
import nova_compute_utils as utils # noqa
|
||||
|
||||
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('nova_compute_utils.restart_map'):
|
||||
with patch('nova_compute_utils.register_configs'):
|
||||
import git_reinstall
|
||||
|
||||
from test_utils import (
|
||||
CharmTestCase
|
||||
)
|
||||
|
||||
TO_PATCH = [
|
||||
'config',
|
||||
]
|
||||
|
||||
|
||||
openstack_origin_git = \
|
||||
"""repositories:
|
||||
- {name: requirements,
|
||||
repository: 'git://git.openstack.org/openstack/requirements',
|
||||
branch: stable/juno}
|
||||
- {name: nova,
|
||||
repository: 'git://git.openstack.org/openstack/nova',
|
||||
branch: stable/juno}"""
|
||||
|
||||
|
||||
class TestnovaAPIActions(CharmTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestnovaAPIActions, 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')
|
||||
def test_git_reinstall(self, config_changed, git_install, action_fail,
|
||||
action_set):
|
||||
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})
|
@ -43,13 +43,11 @@ class TestNovaComputeUpgradeActions(CharmTestCase):
|
||||
|
||||
@patch('charmhelpers.contrib.openstack.utils.config')
|
||||
@patch('charmhelpers.contrib.openstack.utils.action_set')
|
||||
@patch('charmhelpers.contrib.openstack.utils.git_install_requested')
|
||||
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
|
||||
@patch('charmhelpers.contrib.openstack.utils.juju_log')
|
||||
def test_openstack_upgrade_true(self, log, upgrade_avail, git_requested,
|
||||
def test_openstack_upgrade_true(self, log, upgrade_avail,
|
||||
action_set, config):
|
||||
|
||||
git_requested.return_value = False
|
||||
upgrade_avail.return_value = True
|
||||
config.return_value = True
|
||||
|
||||
@ -60,13 +58,11 @@ class TestNovaComputeUpgradeActions(CharmTestCase):
|
||||
|
||||
@patch('charmhelpers.contrib.openstack.utils.config')
|
||||
@patch('charmhelpers.contrib.openstack.utils.action_set')
|
||||
@patch('charmhelpers.contrib.openstack.utils.git_install_requested') # noqa
|
||||
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available') # noqa
|
||||
@patch('charmhelpers.contrib.openstack.utils.juju_log')
|
||||
def test_openstack_upgrade_false(self, log, upgrade_avail, git_requested,
|
||||
def test_openstack_upgrade_false(self, log, upgrade_avail,
|
||||
action_set, config):
|
||||
|
||||
git_requested.return_value = False
|
||||
upgrade_avail.return_value = True
|
||||
config.return_value = False
|
||||
|
||||
|
@ -12,8 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import sys
|
||||
import yaml
|
||||
import importlib
|
||||
|
||||
from mock import (
|
||||
ANY,
|
||||
@ -24,11 +23,6 @@ from mock import (
|
||||
|
||||
from nova_compute_hooks import update_nrpe_config
|
||||
|
||||
# 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()
|
||||
|
||||
from test_utils import CharmTestCase
|
||||
|
||||
with patch('charmhelpers.contrib.hardening.harden.harden') as mock_dec:
|
||||
@ -37,6 +31,7 @@ with patch('charmhelpers.contrib.hardening.harden.harden') as mock_dec:
|
||||
with patch("nova_compute_utils.restart_map"):
|
||||
with patch("nova_compute_utils.register_configs"):
|
||||
import nova_compute_hooks as hooks
|
||||
importlib.reload(hooks)
|
||||
|
||||
|
||||
TO_PATCH = [
|
||||
@ -80,8 +75,6 @@ TO_PATCH = [
|
||||
'disable_shell',
|
||||
'enable_shell',
|
||||
'update_nrpe_config',
|
||||
'git_install',
|
||||
'git_install_requested',
|
||||
'network_manager',
|
||||
'libvirt_daemon',
|
||||
# misc_utils
|
||||
@ -124,36 +117,10 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
self.apt_install.assert_called_with(['foo', 'bar'], fatal=True)
|
||||
self.assertTrue(self.execd_preinstall.called)
|
||||
|
||||
def test_install_hook_git(self):
|
||||
self.git_install_requested.return_value = True
|
||||
self.determine_packages.return_value = ['foo', 'bar']
|
||||
repo = 'cloud:trusty-juno'
|
||||
openstack_origin_git = {
|
||||
'repositories': [
|
||||
{'name': 'requirements',
|
||||
'repository': 'git://git.openstack.org/openstack/requirements', # noqa
|
||||
'branch': 'stable/juno'},
|
||||
{'name': 'nova',
|
||||
'repository': 'git://git.openstack.org/openstack/nova',
|
||||
'branch': 'stable/juno'}
|
||||
],
|
||||
'directory': '/mnt/openstack-git',
|
||||
}
|
||||
projects_yaml = yaml.dump(openstack_origin_git)
|
||||
self.test_config.set('openstack-origin', repo)
|
||||
self.test_config.set('openstack-origin-git', projects_yaml)
|
||||
hooks.install()
|
||||
self.configure_installation_source.assert_called_with(repo)
|
||||
self.assertTrue(self.apt_update.called)
|
||||
self.apt_install.assert_called_with(['foo', 'bar'], fatal=True)
|
||||
self.git_install.assert_called_with(projects_yaml)
|
||||
self.assertTrue(self.execd_preinstall.called)
|
||||
|
||||
@patch.object(hooks, 'ceph_changed')
|
||||
@patch.object(hooks, 'neutron_plugin_joined')
|
||||
def test_config_changed_with_upgrade(self, neutron_plugin_joined,
|
||||
ceph_changed):
|
||||
self.git_install_requested.return_value = False
|
||||
self.openstack_upgrade_available.return_value = True
|
||||
|
||||
def rel_ids(x):
|
||||
@ -167,9 +134,7 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
neutron_plugin_joined.assert_called_with('rid1', remote_restart=True)
|
||||
ceph_changed.assert_called_with(rid='ceph:0', unit='ceph/0')
|
||||
|
||||
@patch.object(hooks, 'git_install_requested')
|
||||
def test_config_changed_with_openstack_upgrade_action(self, git_requested):
|
||||
git_requested.return_value = False
|
||||
def test_config_changed_with_openstack_upgrade_action(self):
|
||||
self.openstack_upgrade_available.return_value = True
|
||||
self.test_config.set('action-managed-upgrade', True)
|
||||
self.migration_enabled.return_value = False
|
||||
@ -181,7 +146,6 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
@patch.object(hooks, 'compute_joined')
|
||||
def test_config_changed_with_migration(self, compute_joined,
|
||||
neutron_plugin_joined):
|
||||
self.git_install_requested.return_value = False
|
||||
self.migration_enabled.return_value = True
|
||||
self.test_config.set('migration-auth-type', 'ssh')
|
||||
self.relation_ids.return_value = [
|
||||
@ -200,7 +164,6 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
@patch.object(hooks, 'compute_joined')
|
||||
def test_config_changed_with_resize(self, compute_joined,
|
||||
neutron_plugin_joined):
|
||||
self.git_install_requested.return_value = False
|
||||
self.test_config.set('enable-resize', True)
|
||||
self.migration_enabled.return_value = False
|
||||
self.relation_ids.return_value = [
|
||||
@ -220,7 +183,6 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
@patch.object(hooks, 'compute_joined')
|
||||
def test_config_changed_without_resize(self, compute_joined,
|
||||
neutron_plugin_joined):
|
||||
self.git_install_requested.return_value = False
|
||||
self.test_config.set('enable-resize', False)
|
||||
self.migration_enabled.return_value = False
|
||||
self.relation_ids.return_value = [
|
||||
@ -237,7 +199,6 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
|
||||
@patch.object(hooks, 'compute_joined')
|
||||
def test_config_changed_no_upgrade_no_migration(self, compute_joined):
|
||||
self.git_install_requested.return_value = False
|
||||
self.openstack_upgrade_available.return_value = False
|
||||
self.migration_enabled.return_value = False
|
||||
hooks.config_changed()
|
||||
@ -246,7 +207,6 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
|
||||
@patch.object(hooks, 'compute_joined')
|
||||
def test_config_changed_with_sysctl(self, compute_joined):
|
||||
self.git_install_requested.return_value = False
|
||||
self.migration_enabled.return_value = False
|
||||
self.test_config.set(
|
||||
'sysctl',
|
||||
@ -258,7 +218,6 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
|
||||
@patch.object(hooks, 'compute_joined')
|
||||
def test_config_changed_with_sysctl_swappy_default(self, compute_joined):
|
||||
self.git_install_requested.return_value = False
|
||||
self.test_config.set(
|
||||
'sysctl',
|
||||
'{ kernel.max_pid : "1337" }')
|
||||
@ -268,33 +227,8 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
"{kernel.max_pid: '1337', vm.swappiness: 1}\n",
|
||||
'/etc/sysctl.d/50-nova-compute.conf')
|
||||
|
||||
@patch.object(hooks, 'config_value_changed')
|
||||
def test_config_changed_git(self, config_val_changed):
|
||||
self.git_install_requested.return_value = True
|
||||
repo = 'cloud:trusty-juno'
|
||||
openstack_origin_git = {
|
||||
'repositories': [
|
||||
{'name': 'requirements',
|
||||
'repository':
|
||||
'git://git.openstack.org/openstack/requirements',
|
||||
'branch': 'stable/juno'},
|
||||
{'name': 'nova',
|
||||
'repository': 'git://git.openstack.org/openstack/nova',
|
||||
'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)
|
||||
self.migration_enabled.return_value = False
|
||||
hooks.config_changed()
|
||||
self.git_install.assert_called_with(projects_yaml)
|
||||
self.assertFalse(self.do_openstack_upgrade.called)
|
||||
|
||||
@patch.object(hooks, 'compute_joined')
|
||||
def test_config_changed_no_nrpe(self, compute_joined):
|
||||
self.git_install_requested.return_value = False
|
||||
self.openstack_upgrade_available.return_value = False
|
||||
self.migration_enabled.return_value = False
|
||||
self.is_relation_made.return_value = False
|
||||
@ -303,7 +237,6 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
|
||||
@patch.object(hooks, 'compute_joined')
|
||||
def test_config_changed_nrpe(self, compute_joined):
|
||||
self.git_install_requested.return_value = False
|
||||
self.openstack_upgrade_available.return_value = False
|
||||
self.migration_enabled.return_value = False
|
||||
self.is_relation_made.return_value = True
|
||||
|
@ -39,19 +39,14 @@ TO_PATCH = [
|
||||
'apt_install',
|
||||
'apt_update',
|
||||
'config',
|
||||
'git_src_dir',
|
||||
'git_pip_venv_dir',
|
||||
'os_release',
|
||||
'log',
|
||||
'pip_install',
|
||||
'related_units',
|
||||
'relation_ids',
|
||||
'relation_get',
|
||||
'render',
|
||||
'service_restart',
|
||||
'mkdir',
|
||||
'install_alternative',
|
||||
'add_user_to_group',
|
||||
'MetadataServiceContext',
|
||||
'lsb_release',
|
||||
'charm_dir',
|
||||
@ -62,15 +57,6 @@ TO_PATCH = [
|
||||
'lsb_release',
|
||||
]
|
||||
|
||||
openstack_origin_git = \
|
||||
"""repositories:
|
||||
- {name: requirements,
|
||||
repository: 'git://git.openstack.org/openstack/requirements',
|
||||
branch: stable/juno}
|
||||
- {name: nova,
|
||||
repository: 'git://git.openstack.org/openstack/nova',
|
||||
branch: stable/juno}"""
|
||||
|
||||
|
||||
class NovaComputeUtilsTests(CharmTestCase):
|
||||
|
||||
@ -82,12 +68,10 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
|
||||
@patch.object(utils, 'nova_metadata_requirement')
|
||||
@patch.object(utils, 'network_manager')
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
@patch('platform.machine')
|
||||
def test_determine_packages_nova_network(self, machine, git_requested,
|
||||
def test_determine_packages_nova_network(self, machine,
|
||||
net_man, en_meta):
|
||||
self.os_release.return_value = 'icehouse'
|
||||
git_requested.return_value = False
|
||||
en_meta.return_value = (False, None)
|
||||
net_man.return_value = 'flatdhcpmanager'
|
||||
machine.return_value = 'x86_64'
|
||||
@ -102,13 +86,10 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
|
||||
@patch.object(utils, 'nova_metadata_requirement')
|
||||
@patch.object(utils, 'network_manager')
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
@patch('platform.machine')
|
||||
def test_determine_packages_nova_network_ocata(self, machine,
|
||||
git_requested,
|
||||
net_man, en_meta):
|
||||
self.os_release.return_value = 'ocata'
|
||||
git_requested.return_value = False
|
||||
en_meta.return_value = (False, None)
|
||||
net_man.return_value = 'flatdhcpmanager'
|
||||
machine.return_value = 'x86_64'
|
||||
@ -122,11 +103,9 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
@patch.object(utils, 'nova_metadata_requirement')
|
||||
@patch.object(utils, 'neutron_plugin')
|
||||
@patch.object(utils, 'network_manager')
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
@patch('platform.machine')
|
||||
def test_determine_packages_neutron(self, machine, git_requested, net_man,
|
||||
def test_determine_packages_neutron(self, machine, net_man,
|
||||
n_plugin, en_meta):
|
||||
git_requested.return_value = False
|
||||
en_meta.return_value = (False, None)
|
||||
net_man.return_value = 'neutron'
|
||||
n_plugin.return_value = 'ovs'
|
||||
@ -139,16 +118,13 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
@patch.object(utils, 'nova_metadata_requirement')
|
||||
@patch.object(utils, 'neutron_plugin')
|
||||
@patch.object(utils, 'network_manager')
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
@patch('platform.machine')
|
||||
def test_determine_packages_neutron_aarch64_xenial(self, machine,
|
||||
git_requested,
|
||||
net_man, n_plugin,
|
||||
en_meta):
|
||||
self.lsb_release.return_value = {
|
||||
'DISTRIB_CODENAME': 'xenial'
|
||||
}
|
||||
git_requested.return_value = False
|
||||
en_meta.return_value = (False, None)
|
||||
net_man.return_value = 'neutron'
|
||||
n_plugin.return_value = 'ovs'
|
||||
@ -161,16 +137,13 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
@patch.object(utils, 'nova_metadata_requirement')
|
||||
@patch.object(utils, 'neutron_plugin')
|
||||
@patch.object(utils, 'network_manager')
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
@patch('platform.machine')
|
||||
def test_determine_packages_neutron_aarch64_trusty(self, machine,
|
||||
git_requested,
|
||||
net_man, n_plugin,
|
||||
en_meta):
|
||||
self.lsb_release.return_value = {
|
||||
'DISTRIB_CODENAME': 'trusty'
|
||||
}
|
||||
git_requested.return_value = False
|
||||
en_meta.return_value = (False, None)
|
||||
net_man.return_value = 'neutron'
|
||||
n_plugin.return_value = 'ovs'
|
||||
@ -183,11 +156,9 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
@patch.object(utils, 'nova_metadata_requirement')
|
||||
@patch.object(utils, 'neutron_plugin')
|
||||
@patch.object(utils, 'network_manager')
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
@patch('platform.machine')
|
||||
def test_determine_packages_neutron_ceph(self, machine, git_requested,
|
||||
def test_determine_packages_neutron_ceph(self, machine,
|
||||
net_man, n_plugin, en_meta):
|
||||
git_requested.return_value = False
|
||||
en_meta.return_value = (False, None)
|
||||
net_man.return_value = 'neutron'
|
||||
n_plugin.return_value = 'ovs'
|
||||
@ -200,10 +171,8 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
@patch.object(utils, 'nova_metadata_requirement')
|
||||
@patch.object(utils, 'neutron_plugin')
|
||||
@patch.object(utils, 'network_manager')
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
def test_determine_packages_metadata(self, git_requested, net_man,
|
||||
def test_determine_packages_metadata(self, net_man,
|
||||
n_plugin, en_meta):
|
||||
git_requested.return_value = False
|
||||
en_meta.return_value = (True, None)
|
||||
net_man.return_value = 'bob'
|
||||
n_plugin.return_value = 'ovs'
|
||||
@ -686,12 +655,9 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
_configure_subuid.assert_called_with('nova')
|
||||
_lxc_list.assert_called_with('nova')
|
||||
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
@patch.object(utils, 'lxc_list')
|
||||
@patch.object(utils, 'configure_subuid')
|
||||
def test_configure_lxd_pre_vivid(self, _configure_subuid, _lxc_list,
|
||||
_git_install):
|
||||
_git_install.return_value = False
|
||||
def test_configure_lxd_pre_vivid(self, _configure_subuid, _lxc_list):
|
||||
self.lsb_release.return_value = {
|
||||
'DISTRIB_CODENAME': 'trusty'
|
||||
}
|
||||
@ -699,200 +665,6 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
utils.configure_lxd('nova')
|
||||
self.assertFalse(_configure_subuid.called)
|
||||
|
||||
@patch.object(utils, 'git_default_repos')
|
||||
@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, git_default_repos):
|
||||
projects_yaml = openstack_origin_git
|
||||
git_default_repos.return_value = projects_yaml
|
||||
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='nova')
|
||||
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')
|
||||
@patch.object(utils, 'check_call')
|
||||
def test_git_pre_install(self, check_call, adduser, add_group,
|
||||
add_user_to_group, write_file, mkdir):
|
||||
utils.git_pre_install()
|
||||
adduser.assert_called_with('nova', shell='/bin/bash',
|
||||
system_user=True)
|
||||
check_call.assert_called_with(['usermod', '--home', '/var/lib/nova',
|
||||
'nova'])
|
||||
add_group.assert_called_with('nova', system_group=True)
|
||||
expected = [
|
||||
call('nova', 'nova'),
|
||||
call('nova', 'libvirtd'),
|
||||
]
|
||||
self.assertEqual(add_user_to_group.call_args_list, expected)
|
||||
expected = [
|
||||
call('/var/lib/nova', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/buckets', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/CA', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/CA/INTER', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/CA/newcerts', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/CA/private', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/CA/reqs', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/images', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/instances', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/keys', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/networks', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/lib/nova/tmp', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
call('/var/log/nova', owner='nova',
|
||||
group='nova', perms=0o0755, force=False),
|
||||
]
|
||||
self.assertEqual(mkdir.call_args_list, expected)
|
||||
expected = [
|
||||
call('/var/log/nova/nova-api.log', '', owner='nova',
|
||||
group='nova', perms=0o0644),
|
||||
call('/var/log/nova/nova-compute.log', '', owner='nova',
|
||||
group='nova', perms=0o0644),
|
||||
call('/var/log/nova/nova-manage.log', '', owner='nova',
|
||||
group='nova', perms=0o0644),
|
||||
call('/var/log/nova/nova-network.log', '', owner='nova',
|
||||
group='nova', perms=0o0644),
|
||||
]
|
||||
self.assertEqual(write_file.call_args_list, expected)
|
||||
|
||||
@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_upstart(self, check_call, rmtree, copytree,
|
||||
symlink, exists, join):
|
||||
projects_yaml = openstack_origin_git
|
||||
join.return_value = 'joined-string'
|
||||
self.lsb_release.return_value = {'DISTRIB_RELEASE': '15.04'}
|
||||
self.git_pip_venv_dir.return_value = '/mnt/openstack-git/venv'
|
||||
utils.git_post_install(projects_yaml)
|
||||
expected = [
|
||||
call('joined-string', '/etc/nova'),
|
||||
]
|
||||
copytree.assert_has_calls(expected)
|
||||
expected = [
|
||||
call('joined-string', '/usr/local/bin/nova-rootwrap'),
|
||||
]
|
||||
symlink.assert_has_calls(expected, any_order=True)
|
||||
|
||||
service_name = 'nova-compute'
|
||||
nova_user = 'nova'
|
||||
start_dir = '/var/lib/nova'
|
||||
nova_conf = '/etc/nova/nova.conf'
|
||||
nova_api_metadata_context = {
|
||||
'service_description': 'Nova Metadata API server',
|
||||
'service_name': service_name,
|
||||
'user_name': nova_user,
|
||||
'start_dir': start_dir,
|
||||
'process_name': 'nova-api-metadata',
|
||||
'executable_name': 'joined-string',
|
||||
'config_files': [nova_conf],
|
||||
}
|
||||
nova_api_context = {
|
||||
'service_description': 'Nova API server',
|
||||
'service_name': service_name,
|
||||
'user_name': nova_user,
|
||||
'start_dir': start_dir,
|
||||
'process_name': 'nova-api',
|
||||
'executable_name': 'joined-string',
|
||||
'config_files': [nova_conf],
|
||||
}
|
||||
nova_compute_context = {
|
||||
'service_description': 'Nova compute worker',
|
||||
'service_name': service_name,
|
||||
'user_name': nova_user,
|
||||
'process_name': 'nova-compute',
|
||||
'executable_name': 'joined-string',
|
||||
'config_files': [nova_conf, '/etc/nova/nova-compute.conf'],
|
||||
}
|
||||
nova_network_context = {
|
||||
'service_description': 'Nova network worker',
|
||||
'service_name': service_name,
|
||||
'user_name': nova_user,
|
||||
'start_dir': start_dir,
|
||||
'process_name': 'nova-network',
|
||||
'executable_name': 'joined-string',
|
||||
'config_files': [nova_conf],
|
||||
}
|
||||
expected = [
|
||||
call('git/nova-compute-kvm.conf', '/etc/nova/nova-compute.conf',
|
||||
{}, perms=0o644),
|
||||
call('git/nova_sudoers', '/etc/sudoers.d/nova_sudoers',
|
||||
{}, perms=0o440),
|
||||
call('git.upstart', '/etc/init/nova-api-metadata.conf',
|
||||
nova_api_metadata_context, perms=0o644,
|
||||
templates_dir='joined-string'),
|
||||
call('git.upstart', '/etc/init/nova-api.conf',
|
||||
nova_api_context, perms=0o644,
|
||||
templates_dir='joined-string'),
|
||||
call('git/upstart/nova-compute.upstart',
|
||||
'/etc/init/nova-compute.conf',
|
||||
nova_compute_context, perms=420),
|
||||
call('git.upstart', '/etc/init/nova-network.conf',
|
||||
nova_network_context, perms=0o644,
|
||||
templates_dir='joined-string'),
|
||||
]
|
||||
self.assertEqual(self.render.call_args_list, expected)
|
||||
self.assertTrue(self.apt_update.called)
|
||||
self.apt_install.assert_called_with(
|
||||
['bridge-utils', 'dnsmasq-base',
|
||||
'dnsmasq-utils', 'ebtables', 'genisoimage', 'iptables',
|
||||
'iputils-arping', 'kpartx', 'kvm', 'netcat', 'open-iscsi',
|
||||
'parted', 'python-libvirt', 'qemu', 'qemu-system',
|
||||
'qemu-utils', 'vlan'], fatal=True)
|
||||
|
||||
@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):
|
||||
projects_yaml = openstack_origin_git
|
||||
join.return_value = 'joined-string'
|
||||
self.lsb_release.return_value = {'DISTRIB_RELEASE': '15.10'}
|
||||
self.git_pip_venv_dir.return_value = '/mnt/openstack-git/venv'
|
||||
utils.git_post_install(projects_yaml)
|
||||
expected = [
|
||||
call('git/nova-compute-kvm.conf', '/etc/nova/nova-compute.conf',
|
||||
{}, perms=420),
|
||||
call('git/nova_sudoers', '/etc/sudoers.d/nova_sudoers',
|
||||
{}, perms=288),
|
||||
call('git/nova-api.init.in.template', 'joined-string',
|
||||
{'daemon_path': 'joined-string'}, perms=420),
|
||||
call('git/nova-api-metadata.init.in.template', 'joined-string',
|
||||
{'daemon_path': 'joined-string'}, perms=420),
|
||||
call('git/nova-compute.init.in.template', 'joined-string',
|
||||
{'daemon_path': 'joined-string'}, perms=420),
|
||||
call('git/nova-network.init.in.template', 'joined-string',
|
||||
{'daemon_path': 'joined-string'}, perms=420),
|
||||
]
|
||||
self.assertEqual(self.render.call_args_list, expected)
|
||||
|
||||
@patch('psutil.virtual_memory')
|
||||
@patch('subprocess.check_call')
|
||||
@patch('subprocess.call')
|
||||
|
Loading…
Reference in New Issue
Block a user