Enable nova-placement-api

This change installs the nova-placement-api, runs it under
mod_wsgi with apache2, updates nova.conf accordingly, and
registers its endpoints.

Change-Id: I4af4afa591cf68964e6146ca0ca0c51d1ddb8a64
This commit is contained in:
Corey Bryant 2017-02-08 18:40:04 +00:00
parent ad6fbd48db
commit 2564cf5a5f
8 changed files with 315 additions and 8 deletions

View File

@ -156,6 +156,8 @@ class HAProxyContext(context.HAProxyContext):
singlenode_mode=True)
s3_api = determine_api_port(api_port('nova-objectstore'),
singlenode_mode=True)
placement_api = determine_api_port(api_port('nova-placement-api'),
singlenode_mode=True)
# Apache ports
a_compute_api = determine_apache_port(api_port('nova-api-os-compute'),
singlenode_mode=True)
@ -163,11 +165,14 @@ class HAProxyContext(context.HAProxyContext):
singlenode_mode=True)
a_s3_api = determine_apache_port(api_port('nova-objectstore'),
singlenode_mode=True)
a_placement_api = determine_apache_port(api_port('nova-placement-api'),
singlenode_mode=True)
# to be set in nova.conf accordingly.
listen_ports = {
'osapi_compute_listen_port': compute_api,
'ec2_listen_port': ec2_api,
's3_listen_port': s3_api,
'placement_listen_port': placement_api,
}
port_mapping = {
@ -177,12 +182,15 @@ class HAProxyContext(context.HAProxyContext):
api_port('nova-api-ec2'), a_ec2_api],
'nova-objectstore': [
api_port('nova-objectstore'), a_s3_api],
'nova-placement-api': [
api_port('nova-placement-api'), a_placement_api],
}
# for haproxy.conf
ctxt['service_ports'] = port_mapping
# for nova.conf
ctxt['listen_ports'] = listen_ports
ctxt['port'] = placement_api
return ctxt

View File

@ -87,6 +87,7 @@ from nova_cc_utils import (
determine_endpoints,
determine_packages,
determine_ports,
disable_package_apache_site,
disable_services,
do_openstack_upgrade,
enable_services,
@ -94,6 +95,7 @@ from nova_cc_utils import (
is_api_ready,
keystone_ca_cert_b64,
migrate_nova_database,
placement_api_enabled,
save_script_rc,
services,
ssh_compute_add,
@ -209,6 +211,9 @@ def install():
apt_update()
apt_install(determine_packages(), fatal=True)
if placement_api_enabled():
disable_package_apache_site()
git_install(config('openstack-origin-git'))
_files = os.path.join(charm_dir(), 'files')

View File

@ -130,6 +130,7 @@ REQUIRED_INTERFACES = {
BASE_PACKAGES = [
'apache2',
'haproxy',
'libapache2-mod-wsgi',
'python-keystoneclient',
'python-mysqldb',
'python-psycopg2',
@ -185,6 +186,7 @@ GIT_PACKAGE_BLACKLIST = [
BASE_SERVICES = [
'nova-api-ec2',
'nova-api-os-compute',
'nova-placement-api',
'nova-objectstore',
'nova-cert',
'nova-scheduler',
@ -200,6 +202,7 @@ API_PORTS = {
'nova-api-ec2': 8773,
'nova-api-os-compute': 8774,
'nova-api-os-volume': 8776,
'nova-placement-api': 8778,
'nova-objectstore': 3333,
}
@ -212,6 +215,10 @@ HAPROXY_CONF = '/etc/haproxy/haproxy.cfg'
APACHE_CONF = '/etc/apache2/sites-available/openstack_https_frontend'
APACHE_24_CONF = '/etc/apache2/sites-available/openstack_https_frontend.conf'
MEMCACHED_CONF = '/etc/memcached.conf'
WSGI_NOVA_PLACEMENT_API_CONF = \
'/etc/apache2/sites-enabled/wsgi-openstack-api.conf'
PACKAGE_NOVA_PLACEMENT_API_CONF = \
'/etc/apache2/sites-enabled/nova-placement-api.conf'
def resolve_services():
@ -313,7 +320,7 @@ SERIAL_CONSOLE = {
}
def resource_map():
def resource_map(return_services=True):
'''
Dynamically generate a map of resources that will be managed for a single
hook execution.
@ -358,6 +365,27 @@ def resource_map():
resource_map[MEMCACHED_CONF] = {
'contexts': [context.MemcacheContext()],
'services': ['memcached']}
if return_services and placement_api_enabled():
for cfile in resource_map:
svcs = resource_map[cfile]['services']
if 'nova-placement-api' in svcs:
svcs.remove('nova-placement-api')
if 'apache2' not in svcs:
svcs.append('apache2')
wsgi_script = "/usr/bin/nova-placement-api"
resource_map[WSGI_NOVA_PLACEMENT_API_CONF] = {
'contexts': [context.WSGIWorkerConfigContext(name="nova",
script=wsgi_script),
nova_cc_context.HAProxyContext()],
'services': ['apache2']
}
elif not placement_api_enabled():
for cfile in resource_map:
svcs = resource_map[cfile]['services']
if 'nova-placement-api' in svcs:
svcs.remove('nova-placement-api')
return resource_map
@ -424,7 +452,7 @@ def console_attributes(attr, proto=None):
def determine_packages():
# currently all packages match service names
packages = deepcopy(BASE_PACKAGES)
for v in resource_map().values():
for v in resource_map(return_services=False).values():
packages.extend(v['services'])
if console_attributes('packages'):
packages.extend(console_attributes('packages'))
@ -866,6 +894,14 @@ def determine_endpoints(public_url, internal_url, admin_url):
s3_internal_url = '%s:%s' % (internal_url, api_port('nova-objectstore'))
s3_admin_url = '%s:%s' % (admin_url, api_port('nova-objectstore'))
if os_rel >= 'ocata':
placement_public_url = '%s:%s' % (
public_url, api_port('nova-placement-api'))
placement_internal_url = '%s:%s' % (
internal_url, api_port('nova-placement-api'))
placement_admin_url = '%s:%s' % (
admin_url, api_port('nova-placement-api'))
# the base endpoints
endpoints = {
'nova_service': 'nova',
@ -902,6 +938,15 @@ def determine_endpoints(public_url, internal_url, admin_url):
's3_internal_url': None,
})
if os_rel >= 'ocata':
endpoints.update({
'placement_service': 'placement',
'placement_region': region,
'placement_public_url': placement_public_url,
'placement_admin_url': placement_admin_url,
'placement_internal_url': placement_internal_url,
})
return endpoints
@ -1422,3 +1467,16 @@ def serial_console_settings():
for use in cloud-compute relation
'''
return nova_cc_context.SerialConsoleContext()()
def placement_api_enabled():
"""Return true if nova-placement-api is enabled in this release"""
return os_release('nova-common') >= 'ocata'
def disable_package_apache_site():
"""Ensure that the package-provided apache configuration is disabled to
prevent it from conflicting with the charm-provided version.
"""
if os.path.exists(PACKAGE_NOVA_PLACEMENT_API_CONF):
subprocess.check_call(['a2dissite', 'nova-placement-api'])

167
templates/ocata/nova.conf Normal file
View File

@ -0,0 +1,167 @@
# ocata
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
###############################################################################
[DEFAULT]
verbose={{ verbose }}
debug={{ debug }}
dhcpbridge_flagfile=/etc/nova/nova.conf
dhcpbridge=/usr/bin/nova-dhcpbridge
logdir=/var/log/nova
state_path=/var/lib/nova
force_dhcp_release=True
iscsi_helper=tgtadm
libvirt_use_virtio_for_bridges=True
connection_type=libvirt
root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf
api_paste_config=/etc/nova/api-paste.ini
volumes_path=/var/lib/nova/volumes
enabled_apis=osapi_compute,metadata
auth_strategy=keystone
compute_driver=libvirt.LibvirtDriver
use_ipv6 = {{ use_ipv6 }}
osapi_compute_listen = {{ bind_host }}
metadata_host = {{ bind_host }}
s3_listen = {{ bind_host }}
osapi_compute_workers = {{ workers }}
{% if additional_neutron_filters is defined %}
scheduler_default_filters = {{ scheduler_default_filters }},{{ additional_neutron_filters }}
{% else %}
scheduler_default_filters = {{ scheduler_default_filters }}
{% endif %}
cpu_allocation_ratio = {{ cpu_allocation_ratio }}
ram_allocation_ratio = {{ ram_allocation_ratio }}
use_syslog={{ use_syslog }}
my_ip = {{ host_ip }}
{% if memcached_servers %}
memcached_servers = {{ memcached_servers }}
{% endif %}
{% include "parts/novnc" %}
{% if rbd_pool -%}
rbd_pool = {{ rbd_pool }}
rbd_user = {{ rbd_user }}
rbd_secret_uuid = {{ rbd_secret_uuid }}
{% endif -%}
{% if neutron_plugin and neutron_plugin in ('ovs', 'midonet') -%}
libvirt_vif_driver = nova.virt.libvirt.vif.LibvirtGenericVIFDriver
libvirt_user_virtio_for_bridges = True
{% if neutron_security_groups -%}
security_group_api = {{ network_manager }}
nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver
{% endif -%}
{% if external_network -%}
default_floating_pool = {{ external_network }}
{% endif -%}
{% endif -%}
{% if neutron_plugin and neutron_plugin == 'vsp' -%}
neutron_ovs_bridge = alubr0
{% endif -%}
{% if neutron_plugin and neutron_plugin == 'nvp' -%}
security_group_api = neutron
nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver
{% if external_network -%}
default_floating_pool = {{ external_network }}
{% endif -%}
{% endif -%}
{% if neutron_plugin and neutron_plugin == 'Calico' -%}
security_group_api = neutron
nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver
{% endif -%}
{% if neutron_plugin and neutron_plugin == 'plumgrid' -%}
security_group_api=neutron
firewall_driver = nova.virt.firewall.NoopFirewallDriver
{% endif -%}
{% if network_manager_config -%}
{% for key, value in network_manager_config.iteritems() -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif -%}
{% if network_manager and network_manager == 'neutron' -%}
network_api_class = nova.network.neutronv2.api.API
use_neutron = True
{% else -%}
network_manager = nova.network.manager.FlatDHCPManager
{% endif -%}
{% if default_floating_pool -%}
default_floating_pool = {{ default_floating_pool }}
{% endif -%}
{% if volume_service -%}
volume_api_class=nova.volume.cinder.API
{% endif -%}
{% if user_config_flags -%}
{% for key, value in user_config_flags.iteritems() -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif -%}
{% if listen_ports -%}
{% for key, value in listen_ports.iteritems() -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif -%}
{% if sections and 'DEFAULT' in sections -%}
{% for key, value in sections['DEFAULT'] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif %}
{% include "section-zeromq" %}
{% include "parts/database-v2" %}
{% include "parts/database-api" %}
{% if glance_api_servers -%}
[glance]
api_servers = {{ glance_api_servers }}
{% endif -%}
{% if network_manager and network_manager == 'neutron' -%}
[neutron]
url = {{ neutron_url }}
auth_strategy = keystone
auth_section = keystone_authtoken
auth_plugin = password
{% endif -%}
{% include "section-keystone-authtoken-mitaka" %}
{% include "parts/section-cinder" %}
[osapi_v3]
enabled=True
{% include "parts/cell" %}
[conductor]
workers = {{ workers }}
{% include "section-rabbitmq-oslo" %}
[oslo_concurrency]
lock_path=/var/lock/nova
[spice]
{% include "parts/spice" %}
{% include "parts/section-serial-console" %}
{% include "parts/section-placement" %}

View File

@ -0,0 +1,18 @@
[placement]
{% if auth_host -%}
auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}
auth_type = password
{% if api_version == "3" -%}
project_domain_name = {{ admin_domain_name }}
user_domain_name = {{ admin_domain_name }}
{% else -%}
project_domain_name = default
user_domain_name = default
{% endif -%}
project_name = {{ admin_tenant_name }}
username = {{ admin_user }}
password = {{ admin_password }}
{% endif -%}
{% if region -%}
os_region_name = {{ region }}
{% endif -%}

View File

@ -796,6 +796,10 @@ class NovaCCBasicDeployment(OpenStackAmuletDeployment):
del services['nova-api-ec2']
del services['nova-objectstore']
if self._get_openstack_release() >= self.xenial_ocata:
# nova-placement-api is run under apache2 with mod_wsgi
services['apache2'] = conf_file
# Expected default and alternate values
flags_default = 'quota_cores=20,quota_instances=40,quota_ram=102400'
flags_alt = 'quota_cores=10,quota_instances=20,quota_ram=51200'

View File

@ -68,6 +68,7 @@ TO_PATCH = [
'relation_get',
'relation_set',
'relation_ids',
'placement_api_enabled',
'ssh_compute_add',
'ssh_known_hosts_lines',
'ssh_authorized_keys_lines',

View File

@ -102,8 +102,8 @@ BASE_ENDPOINTS = {
}
# Restart map should be constructed such that API services restart
# before frontends (haproxy/apaceh) to avoid port conflicts.
RESTART_MAP = OrderedDict([
# before frontends (haproxy/apache) to avoid port conflicts.
RESTART_MAP_ICEHOUSE = OrderedDict([
('/etc/nova/nova.conf', [
'nova-api-ec2', 'nova-api-os-compute', 'nova-objectstore',
'nova-cert', 'nova-scheduler', 'nova-conductor'
@ -114,6 +114,18 @@ RESTART_MAP = OrderedDict([
('/etc/haproxy/haproxy.cfg', ['haproxy']),
('/etc/apache2/sites-available/openstack_https_frontend', ['apache2']),
])
RESTART_MAP_OCATA = OrderedDict([
('/etc/nova/nova.conf', [
'nova-api-ec2', 'nova-api-os-compute', 'nova-objectstore',
'nova-cert', 'nova-scheduler', 'nova-conductor', 'apache2'
]),
('/etc/nova/api-paste.ini', [
'nova-api-ec2', 'nova-api-os-compute', 'apache2'
]),
('/etc/haproxy/haproxy.cfg', ['haproxy']),
('/etc/apache2/sites-available/openstack_https_frontend', ['apache2']),
('/etc/apache2/sites-enabled/wsgi-openstack-api.conf', ['apache2']),
])
DPKG_OPTS = [
@ -240,15 +252,30 @@ class NovaCCUtilsTests(CharmTestCase):
@patch('charmhelpers.contrib.openstack.neutron.os_release')
@patch('os.path.exists')
@patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext')
def test_restart_map_api_before_frontends(self, subcontext, _exists,
_os_release):
def test_restart_map_api_before_frontends_icehouse(self, subcontext,
_exists, _os_release):
_os_release.return_value = 'icehouse'
self.os_release.return_value = 'icehouse'
_exists.return_value = False
self.enable_memcache.return_value = False
self._resource_map()
_map = utils.restart_map()
self.assertIsInstance(_map, OrderedDict)
self.assertEquals(_map, RESTART_MAP)
self.assertEquals(_map, RESTART_MAP_ICEHOUSE)
@patch('charmhelpers.contrib.openstack.neutron.os_release')
@patch('os.path.exists')
@patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext')
def test_restart_map_api_before_frontends_ocata(self, subcontext,
_exists, _os_release):
_os_release.return_value = 'ocata'
self.os_release.return_value = 'ocata'
_exists.return_value = False
self.enable_memcache.return_value = False
self._resource_map()
_map = utils.restart_map()
self.assertIsInstance(_map, OrderedDict)
self.assertEquals(_map, RESTART_MAP_OCATA)
@patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext')
@patch('os.path.exists')
@ -317,7 +344,7 @@ class NovaCCUtilsTests(CharmTestCase):
@patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext')
@patch.object(utils, 'git_install_requested')
def test_determine_packages_base(self, git_requested, subcontext):
def test_determine_packages_base_icehouse(self, git_requested, subcontext):
git_requested.return_value = False
self.relation_ids.return_value = []
self.os_release.return_value = 'icehouse'
@ -325,6 +352,20 @@ class NovaCCUtilsTests(CharmTestCase):
self.enable_memcache.return_value = False
pkgs = utils.determine_packages()
ex = list(set(utils.BASE_PACKAGES + utils.BASE_SERVICES))
# nova-placement-api is purposely dropped unless it's ocata
ex.remove('nova-placement-api')
self.assertEquals(ex, pkgs)
@patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext')
@patch.object(utils, 'git_install_requested')
def test_determine_packages_base_ocata(self, git_requested, subcontext):
git_requested.return_value = False
self.relation_ids.return_value = []
self.os_release.return_value = 'ocata'
self.token_cache_pkgs.return_value = []
self.enable_memcache.return_value = False
pkgs = utils.determine_packages()
ex = list(set(utils.BASE_PACKAGES + utils.BASE_SERVICES))
self.assertEquals(ex, pkgs)
@patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext')
@ -715,6 +756,7 @@ class NovaCCUtilsTests(CharmTestCase):
'nova-cert': ['identity-service', 'amqp', 'shared-db'],
'nova-conductor': ['identity-service', 'amqp', 'shared-db'],
'nova-objectstore': ['identity-service', 'amqp', 'shared-db'],
'nova-placement-api': ['identity-service', 'amqp', 'shared-db'],
'nova-scheduler': ['identity-service', 'amqp', 'shared-db']},
utils.guard_map()
)
@ -729,6 +771,7 @@ class NovaCCUtilsTests(CharmTestCase):
'nova-cert': ['identity-service', 'amqp', 'shared-db'],
'nova-conductor': ['identity-service', 'amqp', 'shared-db'],
'nova-objectstore': ['identity-service', 'amqp', 'shared-db'],
'nova-placement-api': ['identity-service', 'amqp', 'shared-db'],
'nova-scheduler': ['identity-service', 'amqp', 'shared-db'], },
utils.guard_map()
)
@ -738,6 +781,7 @@ class NovaCCUtilsTests(CharmTestCase):
{'nova-api-os-compute': ['identity-service', 'amqp', 'shared-db'],
'nova-cert': ['identity-service', 'amqp', 'shared-db'],
'nova-conductor': ['identity-service', 'amqp', 'shared-db'],
'nova-placement-api': ['identity-service', 'amqp', 'shared-db'],
'nova-scheduler': ['identity-service', 'amqp', 'shared-db'], },
utils.guard_map()
)
@ -753,6 +797,8 @@ class NovaCCUtilsTests(CharmTestCase):
'nova-conductor': ['identity-service', 'amqp', 'pgsql-nova-db'],
'nova-objectstore': ['identity-service', 'amqp',
'pgsql-nova-db'],
'nova-placement-api': ['identity-service', 'amqp',
'pgsql-nova-db'],
'nova-scheduler': ['identity-service', 'amqp',
'pgsql-nova-db'], },
utils.guard_map()