Add systemd init support for deploy from source

systemd is used instead of upstart by default since Ubuntu 15.10
(Wily).  This adds systemd init file support for nova services
that are deployed from source.

Change-Id: I776c2e2af095cdff41e8aaffa3b0da6d1226fe0a
This commit is contained in:
Corey Bryant 2016-06-23 20:41:01 +00:00 committed by James Page
parent 47ffb50ff1
commit 5e122bff12
7 changed files with 192 additions and 91 deletions

View File

@ -40,7 +40,6 @@ from charmhelpers.core.host import (
service_restart,
lsb_release,
write_file,
init_is_systemd,
)
from charmhelpers.core.hookenv import (
@ -62,11 +61,12 @@ from charmhelpers.contrib.openstack.alternatives import install_alternative
from charmhelpers.contrib.openstack.utils import (
configure_installation_source,
get_os_codename_install_source,
git_install_requested,
git_clone_and_install,
git_default_repos,
git_src_dir,
git_generate_systemd_init_files,
git_install_requested,
git_pip_venv_dir,
git_src_dir,
git_yaml_value,
os_release,
is_unit_paused_set,
@ -118,6 +118,7 @@ BASE_GIT_PACKAGES = [
'libxslt1-dev',
'libvirt-dev',
'libyaml-dev',
'openstack-pkg-tools',
'python-dev',
'python-pip',
'python-setuptools',
@ -705,42 +706,44 @@ def git_post_install(projects_yaml):
render(nova_compute_conf, '/etc/nova/nova-compute.conf', {}, perms=0o644)
render('git/nova_sudoers', '/etc/sudoers.d/nova_sudoers', {}, perms=0o440)
service_name = 'nova-compute'
nova_user = 'nova'
start_dir = '/var/lib/nova'
bin_dir = os.path.join(git_pip_venv_dir(projects_yaml), 'bin')
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': os.path.join(bin_dir, 'nova-api-metadata'),
'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': os.path.join(bin_dir, 'nova-api'),
'config_files': [nova_conf],
}
# Use systemd init units/scripts from ubuntu wily onwar
if init_is_systemd():
activate_path = os.path.join(git_pip_venv_dir(projects_yaml), 'bin',
'activate')
nova_compute_context = {
'daemon_path': os.path.join(bin_dir, 'nova-compute'),
'activate_path': activate_path,
}
# 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')
render('git/nova-compute.system.in.template',
'/lib/systemd/system/nova-compute.service',
nova_compute_context, perms=0o644)
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,
@ -749,29 +752,29 @@ def git_post_install(projects_yaml):
'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)
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],
}
# NOTE(coreycb): Needs systemd support
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', '/etc/init/nova-network.conf',
nova_network_context, perms=0o644, templates_dir=templates_dir)
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)

View File

@ -0,0 +1,21 @@
#!/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 }}

View File

@ -0,0 +1,21 @@
#!/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 }}

View File

@ -0,0 +1,27 @@
#!/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

View File

@ -1,17 +0,0 @@
[Unit]
Description=OpenStack Compute
After=libvirtd.service postgresql.service mysql.service keystone.service rabbitmq-server.service ntp.service neutron-ovs-cleanup.service
[Service]
User=nova
Group=nova
WorkingDirectory=/var/lib/nova
PermissionsStartOnly=true
ExecStartPre=/bin/mkdir -p /var/lock/nova /var/log/nova /var/lib/nova
ExecStartPre=/bin/chown nova:nova /var/lock/nova /var/log/nova /var/lib/nova
ExecStart=/bin/bash -c "source {{activate_path}} ;{{ daemon_path }} --config-file=/etc/nova/nova.conf --config-file=/etc/nova/nova-compute.conf"
Restart=on-failure
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,19 @@
#!/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 }}

View File

@ -29,13 +29,18 @@ from test_utils import (
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',
@ -507,26 +512,18 @@ class NovaComputeUtilsTests(CharmTestCase):
]
self.assertEquals(write_file.call_args_list, expected)
@patch.object(utils, 'init_is_systemd')
@patch.object(utils, 'git_src_dir')
@patch.object(utils, 'service_restart')
@patch.object(utils, 'render')
@patch.object(utils, 'git_pip_venv_dir')
@patch('os.path.join')
@patch('os.path.exists')
@patch('os.symlink')
@patch('shutil.copytree')
@patch('shutil.rmtree')
@patch('subprocess.check_call')
@patch.object(utils, 'apt_install')
@patch.object(utils, 'apt_update')
def test_git_post_install(self, apt_update, apt_install, check_call,
rmtree, copytree, symlink, exists, join, venv,
render, service_restart, git_src_dir, systemd):
systemd.return_value = False
def test_git_post_install_upstart(self, check_call, rmtree, copytree,
symlink, exists, join):
projects_yaml = openstack_origin_git
join.return_value = 'joined-string'
venv.return_value = '/mnt/openstack-git/venv'
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'),
@ -581,28 +578,58 @@ class NovaComputeUtilsTests(CharmTestCase):
{}, perms=0o644),
call('git/nova_sudoers', '/etc/sudoers.d/nova_sudoers',
{}, perms=0o440),
call('git/upstart/nova-compute.upstart',
'/etc/init/nova-compute.conf',
nova_compute_context, perms=420),
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.assertEquals(render.call_args_list, expected)
self.assertTrue(apt_update.called)
apt_install.assert_called_with(
self.assertEquals(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', 'xen-system-amd64'], 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.assertEquals(self.render.call_args_list, expected)
@patch('psutil.virtual_memory')
@patch('subprocess.check_call')
@patch('subprocess.call')