[freyes,r=hopem]
Install python-memcache, configure nova.conf adding the key memcached_servers when a relationship with memcached service is established. If multiple units of memcached are available, all of them are used i.e. memcached_servers = host1:port1,host2:port,host3:port3 To secure memcached access this relies in the memcached charm ability to use iptables rules to only allow access to related machines. Closes-Bug: 1386271
This commit is contained in:
commit
c42017fe2c
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -6,6 +6,7 @@ from charmhelpers.core.hookenv import (
|
|||
ERROR,
|
||||
unit_get,
|
||||
related_units,
|
||||
relations_for_id,
|
||||
relation_get,
|
||||
)
|
||||
from charmhelpers.fetch import (
|
||||
|
@ -299,3 +300,24 @@ class NovaIPv6Context(context.BindHostContext):
|
|||
ctxt = super(NovaIPv6Context, self).__call__()
|
||||
ctxt['use_ipv6'] = config('prefer-ipv6')
|
||||
return ctxt
|
||||
|
||||
|
||||
class InstanceConsoleContext(context.OSContextGenerator):
|
||||
interfaces = []
|
||||
|
||||
def __call__(self):
|
||||
ctxt = {}
|
||||
servers = []
|
||||
try:
|
||||
for rid in relation_ids('memcache'):
|
||||
for rel in relations_for_id(rid):
|
||||
priv_addr = rel['private-address']
|
||||
# Format it as IPv6 address if needed
|
||||
priv_addr = format_ipv6_addr(priv_addr) or priv_addr
|
||||
servers.append("%s:%s" % (priv_addr, rel['port']))
|
||||
except Exception as ex:
|
||||
log("Could not get memcache servers: %s" % (ex), level='WARNING')
|
||||
servers = []
|
||||
|
||||
ctxt['memcached_servers'] = ','.join(servers)
|
||||
return ctxt
|
||||
|
|
|
@ -849,6 +849,15 @@ def neutron_api_relation_broken():
|
|||
quantum_joined(rid=rid)
|
||||
|
||||
|
||||
@hooks.hook('memcache-relation-joined',
|
||||
'memcache-relation-departed',
|
||||
'memcache-relation-changed',
|
||||
'memcache-relation-broken')
|
||||
@restart_on_change(restart_map())
|
||||
def memcached_joined():
|
||||
CONFIGS.write(NOVA_CONF)
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
hooks.execute(sys.argv)
|
||||
|
|
|
@ -69,6 +69,7 @@ BASE_PACKAGES = [
|
|||
'python-psutil',
|
||||
'python-six',
|
||||
'uuid',
|
||||
'python-memcache',
|
||||
]
|
||||
|
||||
BASE_SERVICES = [
|
||||
|
@ -124,7 +125,8 @@ BASE_RESOURCE_MAP = OrderedDict([
|
|||
nova_cc_context.VolumeServiceContext(),
|
||||
nova_cc_context.NovaIPv6Context(),
|
||||
nova_cc_context.NeutronCCContext(),
|
||||
nova_cc_context.NovaConfigContext()],
|
||||
nova_cc_context.NovaConfigContext(),
|
||||
nova_cc_context.InstanceConsoleContext()],
|
||||
}),
|
||||
(NOVA_API_PASTE, {
|
||||
'services': [s for s in BASE_SERVICES if 'api' in s],
|
||||
|
|
|
@ -40,6 +40,8 @@ requires:
|
|||
nova-vmware:
|
||||
interface: nova-vmware
|
||||
scope: container
|
||||
memcache:
|
||||
interface: memcache
|
||||
peers:
|
||||
cluster:
|
||||
interface: nova-ha
|
||||
|
|
|
@ -21,6 +21,11 @@ volumes_path=/var/lib/nova/volumes
|
|||
enabled_apis=ec2,osapi_compute,metadata
|
||||
auth_strategy=keystone
|
||||
compute_driver=libvirt.LibvirtDriver
|
||||
|
||||
{% if memcached_servers %}
|
||||
memcached_servers = {{ memcached_servers }}
|
||||
{% endif %}
|
||||
|
||||
{% if keystone_ec2_url -%}
|
||||
keystone_ec2_url = {{ keystone_ec2_url }}
|
||||
{% endif -%}
|
||||
|
|
|
@ -20,6 +20,11 @@ volumes_path=/var/lib/nova/volumes
|
|||
enabled_apis=ec2,osapi_compute,metadata
|
||||
auth_strategy=keystone
|
||||
compute_driver=libvirt.LibvirtDriver
|
||||
|
||||
{% if memcached_servers %}
|
||||
memcached_servers = {{ memcached_servers }}
|
||||
{% endif %}
|
||||
|
||||
{% if keystone_ec2_url -%}
|
||||
keystone_ec2_url = {{ keystone_ec2_url }}
|
||||
{% endif -%}
|
||||
|
|
|
@ -27,6 +27,10 @@ cpu_allocation_ratio = {{ cpu_allocation_ratio }}
|
|||
use_syslog={{ use_syslog }}
|
||||
my_ip = {{ host_ip }}
|
||||
|
||||
{% if memcached_servers %}
|
||||
memcached_servers = {{ memcached_servers }}
|
||||
{% endif %}
|
||||
|
||||
{% if keystone_ec2_url -%}
|
||||
keystone_ec2_url = {{ keystone_ec2_url }}
|
||||
{% endif -%}
|
||||
|
|
|
@ -38,6 +38,10 @@ ram_allocation_ratio = {{ ram_allocation_ratio }}
|
|||
use_syslog={{ use_syslog }}
|
||||
my_ip = {{ host_ip }}
|
||||
|
||||
{% if memcached_servers %}
|
||||
memcached_servers = {{ memcached_servers }}
|
||||
{% endif %}
|
||||
|
||||
{% if keystone_ec2_url -%}
|
||||
keystone_ec2_url = {{ keystone_ec2_url }}
|
||||
{% endif -%}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import mock
|
||||
|
||||
#####
|
||||
# NOTE(freyes): this is a workaround to patch config() function imported by
|
||||
# nova_cc_utils before it gets a reference to the actual config() provided by
|
||||
# hookenv module.
|
||||
from charmhelpers.core import hookenv
|
||||
_conf = hookenv.config
|
||||
hookenv.config = mock.MagicMock()
|
||||
import nova_cc_utils as _utils
|
||||
# this assert is a double check + to avoid pep8 warning
|
||||
assert _utils.config == hookenv.config
|
||||
hookenv.config = _conf
|
||||
#####
|
||||
|
||||
import nova_cc_context as context
|
||||
|
||||
from charmhelpers.contrib.openstack import utils
|
||||
|
||||
from test_utils import CharmTestCase
|
||||
|
||||
|
||||
TO_PATCH = [
|
||||
'apt_install',
|
||||
'filter_installed_packages',
|
||||
'relation_ids',
|
||||
'relation_get',
|
||||
'related_units',
|
||||
'config',
|
||||
'log',
|
||||
'unit_get',
|
||||
'relations_for_id',
|
||||
]
|
||||
|
||||
|
||||
def fake_log(msg, level=None):
|
||||
level = level or 'INFO'
|
||||
print('[juju test log (%s)] %s' % (level, msg))
|
||||
|
||||
|
||||
class NovaComputeContextTests(CharmTestCase):
|
||||
def setUp(self):
|
||||
super(NovaComputeContextTests, self).setUp(context, TO_PATCH)
|
||||
self.relation_get.side_effect = self.test_relation.get
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.log.side_effect = fake_log
|
||||
|
||||
@mock.patch.object(utils, 'os_release')
|
||||
@mock.patch('charmhelpers.contrib.network.ip.log')
|
||||
def test_instance_console_context_without_memcache(self, os_release, log_):
|
||||
self.unit_get.return_value = '127.0.0.1'
|
||||
self.relation_ids.return_value = 'cache:0'
|
||||
self.related_units.return_value = 'memcached/0'
|
||||
instance_console = context.InstanceConsoleContext()
|
||||
os_release.return_value = 'icehouse'
|
||||
self.assertEqual({'memcached_servers': ''},
|
||||
instance_console())
|
||||
|
||||
@mock.patch.object(utils, 'os_release')
|
||||
@mock.patch('charmhelpers.contrib.network.ip.log')
|
||||
def test_instance_console_context_with_memcache(self, os_release, log_):
|
||||
self.check_instance_console_context_with_memcache(os_release,
|
||||
'127.0.1.1',
|
||||
'127.0.1.1')
|
||||
|
||||
@mock.patch.object(utils, 'os_release')
|
||||
@mock.patch('charmhelpers.contrib.network.ip.log')
|
||||
def test_instance_console_context_with_memcache_ipv6(self, os_release,
|
||||
log_):
|
||||
self.check_instance_console_context_with_memcache(os_release, '::1',
|
||||
'[::1]')
|
||||
|
||||
def check_instance_console_context_with_memcache(self, os_release, ip,
|
||||
formated_ip):
|
||||
memcached_servers = [{'private-address': formated_ip,
|
||||
'port': '11211'}]
|
||||
self.unit_get.return_value = ip
|
||||
self.relation_ids.return_value = ['cache:0']
|
||||
self.relations_for_id.return_value = memcached_servers
|
||||
self.related_units.return_value = 'memcached/0'
|
||||
instance_console = context.InstanceConsoleContext()
|
||||
os_release.return_value = 'icehouse'
|
||||
self.maxDiff = None
|
||||
self.assertEqual({'memcached_servers': "%s:11211" % (formated_ip, )},
|
||||
instance_console())
|
|
@ -1,6 +1,7 @@
|
|||
from mock import MagicMock, patch, call
|
||||
from test_utils import CharmTestCase, patch_open
|
||||
import os
|
||||
|
||||
with patch('charmhelpers.core.hookenv.config') as config:
|
||||
config.return_value = 'neutron'
|
||||
import nova_cc_utils as utils
|
||||
|
|
Loading…
Reference in New Issue