Allow Juju AZ context information to be used
The change adds an option to the charm to use JUJU_AVAILABILITY_ZONE environment variable set by Juju for the hook environment based on the underlying provider's availability zone information for a given machine. This information is used to configure default_availability_zone for nova and availability_zone for subordinate networking charms. Change-Id: Idc7112e7fe7b76d15cf9c4896b702b8ffd8c0e8e Closes-Bug: #1796068
This commit is contained in:
parent
e5a8c29f4f
commit
4fb1243100
31
README.md
31
README.md
@ -43,6 +43,37 @@ different cephx keys and user names.
|
||||
See LP Bug [#1671422](https://bugs.launchpad.net/charm-cinder-ceph/+bug/1671422)
|
||||
for more information.
|
||||
|
||||
Availability Zones
|
||||
==================
|
||||
|
||||
There are two options to provide default_availability_zone config
|
||||
for nova nodes:
|
||||
|
||||
- default-availability-zone
|
||||
- customize-failure-domain
|
||||
|
||||
The order of precedence is as follows:
|
||||
|
||||
1. Information from a Juju provider (JUJU_AVAILABILITY_ZONE)
|
||||
if customize-failure-domain is set to True and Juju
|
||||
has set the JUJU_AVAILABILITY_ZONE to a non-empty value;
|
||||
2. The value of default-availability-zone will be used
|
||||
if customize-failure-domain is set to True but no
|
||||
JUJU_AVAILABILITY_ZONE is provided via hook
|
||||
context by the Juju provider;
|
||||
3. Otherwise, the value of default-availability-zone
|
||||
charm option will be used.
|
||||
|
||||
The default_availability_zone in Nova affects scheduling if a
|
||||
given Nova node was not placed into an aggregate with an
|
||||
availability zone present as a property by an operator. Using
|
||||
customize-failure-domain is recommended as it provides AZ-aware
|
||||
scheduling out of the box if an operator specifies an AZ during
|
||||
instance creation.
|
||||
|
||||
These options also affect the AZ propagated down to networking
|
||||
subordinates which is useful for AZ-aware Neutron agent scheduling.
|
||||
|
||||
NFV support
|
||||
===========
|
||||
|
||||
|
15
config.yaml
15
config.yaml
@ -373,11 +373,24 @@ options:
|
||||
.
|
||||
This option determines the availability zone to be used when it is not
|
||||
specified in the VM creation request. If this option is not set, the
|
||||
default availability zone 'nova' is used.
|
||||
default availability zone 'nova' is used. If customize-failure-domain
|
||||
is set to True, it will override this option only if an AZ is set by
|
||||
the Juju provider. If JUJU_AVAILABILITY_ZONE is not set, the value
|
||||
specified by this option will be used regardless of
|
||||
customize-failure-domain's setting.
|
||||
.
|
||||
NOTE: Availability zones must be created manually using the
|
||||
'openstack aggregate create' command.
|
||||
.
|
||||
customize-failure-domain:
|
||||
type: boolean
|
||||
default: False
|
||||
description: |
|
||||
Juju propagates availability zone information to charms from the
|
||||
underlying machine provider such as MAAS and this option allows the
|
||||
charm to use JUJU_AVAILABILITY_ZONE to set default_availability_zone for
|
||||
Nova nodes. This option overrides the default-availability-zone charm
|
||||
config setting only when the Juju provider sets JUJU_AVAILABILITY_ZONE.
|
||||
resume-guests-state-on-host-boot:
|
||||
type: boolean
|
||||
default: False
|
||||
|
@ -51,6 +51,7 @@ from charmhelpers.contrib.network.ip import (
|
||||
get_relation_ip,
|
||||
)
|
||||
|
||||
|
||||
# This is just a label and it must be consistent across
|
||||
# nova-compute nodes to support live migration.
|
||||
CEPH_SECRET_UUID = '514c9fca-8cbe-11e2-9c52-3bc8c7819472'
|
||||
@ -86,6 +87,11 @@ def _network_manager():
|
||||
return manager()
|
||||
|
||||
|
||||
def _get_availability_zone():
|
||||
from nova_compute_utils import get_availability_zone as get_az
|
||||
return get_az()
|
||||
|
||||
|
||||
def _neutron_security_groups():
|
||||
'''
|
||||
Inspects current cloud-compute relation and determine if nova-c-c has
|
||||
@ -722,7 +728,5 @@ class NovaComputeAvailabilityZoneContext(context.OSContextGenerator):
|
||||
|
||||
def __call__(self):
|
||||
ctxt = {}
|
||||
if config('default-availability-zone'):
|
||||
ctxt['default_availability_zone'] = config(
|
||||
'default-availability-zone')
|
||||
ctxt['default_availability_zone'] = _get_availability_zone()
|
||||
return ctxt
|
||||
|
@ -109,6 +109,7 @@ from nova_compute_utils import (
|
||||
configure_local_ephemeral_storage,
|
||||
pause_unit_helper,
|
||||
resume_unit_helper,
|
||||
get_availability_zone,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.network.ip import (
|
||||
@ -464,7 +465,7 @@ def update_nrpe_config():
|
||||
def neutron_plugin_joined(relid=None, remote_restart=False):
|
||||
rel_settings = {
|
||||
'hugepage_number': get_hugepage_number(),
|
||||
'default_availability_zone': config('default-availability-zone')
|
||||
'default_availability_zone': get_availability_zone()
|
||||
}
|
||||
if remote_restart:
|
||||
rel_settings['restart-trigger'] = str(uuid.uuid4())
|
||||
|
@ -907,3 +907,10 @@ def configure_local_ephemeral_storage():
|
||||
# storage is never reconfigured by mistake, losing instance disks
|
||||
db.set('storage-configured', True)
|
||||
db.flush()
|
||||
|
||||
|
||||
def get_availability_zone():
|
||||
use_juju_az = config('customize-failure-domain')
|
||||
juju_az = os.environ.get('JUJU_AVAILABILITY_ZONE')
|
||||
return (juju_az if use_juju_az and juju_az
|
||||
else config('default-availability-zone'))
|
||||
|
@ -563,3 +563,68 @@ class SerialConsoleContextTests(CharmTestCase):
|
||||
'host_uuid': self.host_uuid,
|
||||
'force_raw_images': True,
|
||||
'reserved_host_memory': 512}, libvirt())
|
||||
|
||||
|
||||
class NovaComputeAvailabilityZoneContextTests(CharmTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(NovaComputeAvailabilityZoneContextTests,
|
||||
self).setUp(context, TO_PATCH)
|
||||
self.os_release.return_value = 'kilo'
|
||||
|
||||
@patch('nova_compute_utils.config')
|
||||
@patch('os.environ.get')
|
||||
def test_availability_zone_no_juju_with_env(self, mock_get,
|
||||
mock_config):
|
||||
def environ_get_side_effect(key):
|
||||
return {
|
||||
'JUJU_AVAILABILITY_ZONE': 'az1',
|
||||
}[key]
|
||||
mock_get.side_effect = environ_get_side_effect
|
||||
|
||||
def config_side_effect(key):
|
||||
return {
|
||||
'customize-failure-domain': False,
|
||||
'default-availability-zone': 'nova',
|
||||
}[key]
|
||||
|
||||
mock_config.side_effect = config_side_effect
|
||||
az_context = context.NovaComputeAvailabilityZoneContext()
|
||||
self.assertEqual(
|
||||
{'default_availability_zone': 'nova'}, az_context())
|
||||
|
||||
@patch('nova_compute_utils.config')
|
||||
@patch('os.environ.get')
|
||||
def test_availability_zone_no_juju_no_env(self, mock_get,
|
||||
mock_config):
|
||||
def environ_get_side_effect(key):
|
||||
return {
|
||||
'JUJU_AVAILABILITY_ZONE': '',
|
||||
}[key]
|
||||
mock_get.side_effect = environ_get_side_effect
|
||||
|
||||
def config_side_effect(key):
|
||||
return {
|
||||
'customize-failure-domain': False,
|
||||
'default-availability-zone': 'nova',
|
||||
}[key]
|
||||
|
||||
mock_config.side_effect = config_side_effect
|
||||
az_context = context.NovaComputeAvailabilityZoneContext()
|
||||
|
||||
self.assertEqual(
|
||||
{'default_availability_zone': 'nova'}, az_context())
|
||||
|
||||
@patch('os.environ.get')
|
||||
def test_availability_zone_juju(self, mock_get):
|
||||
def environ_get_side_effect(key):
|
||||
return {
|
||||
'JUJU_AVAILABILITY_ZONE': 'az1',
|
||||
}[key]
|
||||
mock_get.side_effect = environ_get_side_effect
|
||||
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.test_config.set('customize-failure-domain', True)
|
||||
az_context = context.NovaComputeAvailabilityZoneContext()
|
||||
self.assertEqual(
|
||||
{'default_availability_zone': 'az1'}, az_context())
|
||||
|
@ -542,6 +542,29 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||
**expect_rel_settings
|
||||
)
|
||||
|
||||
@patch('os.environ.get')
|
||||
@patch.object(hooks, 'get_hugepage_number')
|
||||
def test_neutron_plugin_joined_relid_juju_az(self,
|
||||
get_hugepage_number,
|
||||
mock_env_get):
|
||||
self.test_config.set('customize-failure-domain', True)
|
||||
|
||||
def environ_get_side_effect(key):
|
||||
return {
|
||||
'JUJU_AVAILABILITY_ZONE': 'az1',
|
||||
}[key]
|
||||
mock_env_get.side_effect = environ_get_side_effect
|
||||
get_hugepage_number.return_value = None
|
||||
hooks.neutron_plugin_joined(relid='relid23')
|
||||
expect_rel_settings = {
|
||||
'hugepage_number': None,
|
||||
'default_availability_zone': 'az1',
|
||||
}
|
||||
self.relation_set.assert_called_with(
|
||||
relation_id='relid23',
|
||||
**expect_rel_settings
|
||||
)
|
||||
|
||||
@patch.object(hooks, 'get_hugepage_number')
|
||||
def test_neutron_plugin_joined_huge(self, get_hugepage_number):
|
||||
get_hugepage_number.return_value = 12
|
||||
|
@ -952,3 +952,55 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
priority=80
|
||||
)
|
||||
self.is_block_device.assert_not_called()
|
||||
|
||||
@patch.object(utils.os.environ, 'get')
|
||||
def test_get_az_customize_with_env(self, os_environ_get_mock):
|
||||
self.test_config.set('customize-failure-domain', True)
|
||||
self.test_config.set('default-availability-zone', 'nova')
|
||||
|
||||
def os_environ_get_side_effect(key):
|
||||
return {
|
||||
'JUJU_AVAILABILITY_ZONE': 'az1',
|
||||
}[key]
|
||||
os_environ_get_mock.side_effect = os_environ_get_side_effect
|
||||
az = utils.get_availability_zone()
|
||||
self.assertEqual('az1', az)
|
||||
|
||||
@patch.object(utils.os.environ, 'get')
|
||||
def test_get_az_customize_without_env(self, os_environ_get_mock):
|
||||
self.test_config.set('customize-failure-domain', True)
|
||||
self.test_config.set('default-availability-zone', 'mynova')
|
||||
|
||||
def os_environ_get_side_effect(key):
|
||||
return {
|
||||
'JUJU_AVAILABILITY_ZONE': '',
|
||||
}[key]
|
||||
os_environ_get_mock.side_effect = os_environ_get_side_effect
|
||||
az = utils.get_availability_zone()
|
||||
self.assertEqual('mynova', az)
|
||||
|
||||
@patch.object(utils.os.environ, 'get')
|
||||
def test_get_az_no_customize_without_env(self, os_environ_get_mock):
|
||||
self.test_config.set('customize-failure-domain', False)
|
||||
self.test_config.set('default-availability-zone', 'nova')
|
||||
|
||||
def os_environ_get_side_effect(key):
|
||||
return {
|
||||
'JUJU_AVAILABILITY_ZONE': '',
|
||||
}[key]
|
||||
os_environ_get_mock.side_effect = os_environ_get_side_effect
|
||||
az = utils.get_availability_zone()
|
||||
self.assertEqual('nova', az)
|
||||
|
||||
@patch.object(utils.os.environ, 'get')
|
||||
def test_get_az_no_customize_with_env(self, os_environ_get_mock):
|
||||
self.test_config.set('customize-failure-domain', False)
|
||||
self.test_config.set('default-availability-zone', 'nova')
|
||||
|
||||
def os_environ_get_side_effect(key):
|
||||
return {
|
||||
'JUJU_AVAILABILITY_ZONE': 'az1',
|
||||
}[key]
|
||||
os_environ_get_mock.side_effect = os_environ_get_side_effect
|
||||
az = utils.get_availability_zone()
|
||||
self.assertEqual('nova', az)
|
||||
|
Loading…
Reference in New Issue
Block a user