NSXv: New way to configure availability zones

Configure availability zones in nsx.ini using a dynamic sections.
The previous way of con figuring all in 1 line still works.

Example:
[nsxv]
availability_zones = zone1, zone2

[az:zone1]
resource_pool_id = resgroup-28
datastore_id = datastore-21
edge_ha = True
ha_datastore_id = datastore-22

[az:zone2]
...

Change-Id: I344d2fc1de246fdaf272a6917638716c956e1e23
This commit is contained in:
Adit Sarfaty 2017-01-27 21:08:28 +02:00
parent 3756e8bd6f
commit dd1923005c
5 changed files with 192 additions and 18 deletions

View File

@ -451,9 +451,8 @@ nsxv_opts = [
cfg.ListOpt('availability_zones',
default=[],
help=_('Optional parameter defining the availability zones '
'for deploying NSX Edges with the format: <zone name>:'
'<resource pool id]:<datastore id>:<edge_ha True/False>'
'<(optional)HA datastore id>.')),
'names for deploying NSX Edges. The configuration of '
'each zone will be under a group names [az:<name>]')),
cfg.StrOpt('datastore_id',
deprecated_group="vcns",
help=_('Optional parameter identifying the ID of datastore to '
@ -650,6 +649,22 @@ nsxv_opts = [
"be associated with all router interfaces.")),
]
# define the configuration of each availability zone.
# the list of expected zones in under nsxv group: availability_zones
nsxv_az_opts = [
cfg.StrOpt('resource_pool_id',
help=_('Identifying the ID of resource to deploy NSX Edges')),
cfg.StrOpt('datastore_id',
help=_('Identifying the ID of datastore to deploy NSX Edges')),
cfg.BoolOpt('edge_ha',
default=False,
help=_("(Optional) Enable HA for NSX Edges.")),
cfg.StrOpt('ha_datastore_id',
help=_('Optional parameter identifying the ID of datastore to '
'deploy NSX Edges in addition to data_store_id in case'
'edge_ha is True')),
]
# Register the configuration options
cfg.CONF.register_opts(connection_opts)
cfg.CONF.register_opts(cluster_opts)
@ -659,11 +674,43 @@ cfg.CONF.register_opts(nsxv_opts, group="nsxv")
cfg.CONF.register_opts(base_opts, group="NSX")
cfg.CONF.register_opts(sync_opts, group="NSX_SYNC")
# registser l3_ha config opts. This is due to commit
# register l3_ha config opts. This is due to commit
# a7c633dc8e8a67e65e558ecbdf9ea8efc5468251
cfg.CONF.register_opts(l3_hamode_db.L3_HA_OPTS)
# register a group for each nsxv availability zones
def register_nsxv_azs(conf, availability_zones):
# first verify that the availability zones are in the format of a
# list of names. The old format was a list of values for each az,
# separated with ':'
if not availability_zones or len(availability_zones[0].split(':')) > 1:
return
for az in availability_zones:
az_group = 'az:%s' % az
conf.register_group(cfg.OptGroup(
name=az_group,
title="Configuration for availability zone %s" % az))
conf.register_opts(nsxv_az_opts, group=az_group)
register_nsxv_azs(cfg.CONF, cfg.CONF.nsxv.availability_zones)
def get_nsxv_az_opts(az):
az_info = dict()
group = 'az:%s' % az
if group not in cfg.CONF:
raise nsx_exc.NsxInvalidConfiguration(
opt_name=group,
opt_value='None',
reason=(_("Configuration group \'%s\' must be defined") % group))
for opt in nsxv_az_opts:
az_info[opt.name] = cfg.CONF[group][opt.name]
return az_info
def validate_nsxv_config_options():
if (cfg.CONF.nsxv.manager_uri is None or
cfg.CONF.nsxv.user is None or

View File

@ -16,6 +16,7 @@
from oslo_config import cfg
from vmware_nsx._i18n import _
from vmware_nsx.common import config
from vmware_nsx.common import exceptions as nsx_exc
DEFAULT_NAME = 'default'
@ -24,7 +25,9 @@ DEFAULT_NAME = 'default'
class ConfiguredAvailabilityZone(object):
def __init__(self, config_line):
if config_line:
if config_line and ':' in config_line:
# Older configuration - each line contains all the relevant
# values for one availability zones, separated by ':'
values = config_line.split(':')
if len(values) < 4 or len(values) > 5:
raise nsx_exc.NsxInvalidConfiguration(
@ -63,6 +66,29 @@ class ConfiguredAvailabilityZone(object):
"enabled"))
self.ha_datastore_id = values[4] if len(values) == 5 else None
elif config_line:
# Newer configuration - the name of the availability zone can be
# used to get the rest of the configuration for this AZ
self.name = config_line
az_info = config.get_nsxv_az_opts(self.name)
self.resource_pool = az_info.get('resource_pool_id')
if not self.resource_pool:
raise nsx_exc.NsxInvalidConfiguration(
opt_name="resource_pool_id",
opt_value='None',
reason=(_("resource_pool_id for availability zone %s "
"must be defined") % self.name))
self.datastore_id = az_info.get('datastore_id')
if not self.datastore_id:
raise nsx_exc.NsxInvalidConfiguration(
opt_name="datastore_id",
opt_value='None',
reason=(_("datastore_id for availability zone %s "
"must be defined") % self.name))
self.edge_ha = az_info.get('edge_ha', False)
# The HA datastore can be empty
self.ha_datastore_id = (az_info.get('ha_datastore_id')
if self.edge_ha else None)
else:
# use the default configuration
self.name = DEFAULT_NAME

View File

@ -18,6 +18,7 @@ from oslo_config import cfg
from neutron import context as neutron_context
from neutron.db import common_db_mixin as common_db
from vmware_nsx.common import config
from vmware_nsx import plugin
from vmware_nsx.plugins.nsx_v.vshield import vcns
@ -38,6 +39,11 @@ class NeutronDbClient(common_db.CommonDbMixin):
class NsxVPluginWrapper(plugin.NsxVPlugin):
def __init__(self):
config.register_nsxv_azs(cfg.CONF, cfg.CONF.nsxv.availability_zones)
super(NsxVPluginWrapper, self).__init__()
def _start_rpc_listeners(self):
pass

View File

@ -13,14 +13,98 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from neutron.tests import base
from vmware_nsx.common import config
from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.plugins.nsx_v import availability_zones as nsx_az
class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
def setUp(self):
super(NsxvAvailabilityZonesTestCase, self).setUp()
self.az_name = 'zone1'
self.group_name = 'az:%s' % self.az_name
config.register_nsxv_azs(cfg.CONF, [self.az_name])
def _config_az(self, resource_pool_id="respool", datastore_id="datastore",
edge_ha=True, ha_datastore_id="hastore"):
cfg.CONF.set_override("resource_pool_id", resource_pool_id,
group=self.group_name)
cfg.CONF.set_override("datastore_id", datastore_id,
group=self.group_name)
if edge_ha is not None:
cfg.CONF.set_override("edge_ha", edge_ha,
group=self.group_name)
cfg.CONF.set_override("ha_datastore_id", ha_datastore_id,
group=self.group_name)
def test_simple_availability_zone(self):
self._config_az()
az = nsx_az.ConfiguredAvailabilityZone(self.az_name)
self.assertEqual(self.az_name, az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(True, az.edge_ha)
self.assertEqual("hastore", az.ha_datastore_id)
def test_availability_zone_no_edge_ha(self):
self._config_az(edge_ha=False)
az = nsx_az.ConfiguredAvailabilityZone(self.az_name)
self.assertEqual(self.az_name, az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(False, az.edge_ha)
self.assertEqual(None, az.ha_datastore_id)
def test_availability_zone_no_ha_datastore(self):
self._config_az(ha_datastore_id=None)
az = nsx_az.ConfiguredAvailabilityZone(self.az_name)
self.assertEqual(self.az_name, az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(True, az.edge_ha)
self.assertEqual(None, az.ha_datastore_id)
def test_missing_group_section(self):
self.assertRaises(
nsx_exc.NsxInvalidConfiguration,
nsx_az.ConfiguredAvailabilityZone,
"doesnt_exist")
def test_availability_zone_missing_respool(self):
self._config_az(resource_pool_id=None)
self.assertRaises(
nsx_exc.NsxInvalidConfiguration,
nsx_az.ConfiguredAvailabilityZone,
self.az_name)
def test_availability_zone_missing_datastore(self):
self._config_az(datastore_id=None)
self.assertRaises(
nsx_exc.NsxInvalidConfiguration,
nsx_az.ConfiguredAvailabilityZone,
self.az_name)
def test_availability_zone_missing_edge_ha(self):
self._config_az(edge_ha=None)
az = nsx_az.ConfiguredAvailabilityZone(self.az_name)
self.assertEqual(self.az_name, az.name)
self.assertEqual("respool", az.resource_pool)
self.assertEqual("datastore", az.datastore_id)
self.assertEqual(False, az.edge_ha)
self.assertEqual(None, az.ha_datastore_id)
class NsxvAvailabilityZonesOldTestCase(base.BaseTestCase):
"""Test old way of configuring the availability zones
using a one-line configuration instead of different dynamic sections
"""
def test_simple_availability_zone(self):
az = nsx_az.ConfiguredAvailabilityZone(
"name:respool:datastore:true:hastore")

View File

@ -54,6 +54,7 @@ import six
import webob.exc
from vmware_nsx._i18n import _
from vmware_nsx.common import config
from vmware_nsx.common import exceptions as nsxv_exc
from vmware_nsx.common import nsx_constants
from vmware_nsx.common import utils as c_utils
@ -88,6 +89,22 @@ PLUGIN_NAME = 'vmware_nsx.plugin.NsxVPlugin'
_uuid = uuidutils.generate_uuid
def set_az_in_config(name, resource_pool_id="respool-7",
datastore_id="datastore-7",
edge_ha=False, ha_datastore_id=None):
group_name = 'az:%s' % name
cfg.CONF.set_override('availability_zones', [name], group="nsxv")
config.register_nsxv_azs(cfg.CONF, [name])
cfg.CONF.set_override("resource_pool_id", resource_pool_id,
group=group_name)
cfg.CONF.set_override("datastore_id", datastore_id,
group=group_name)
cfg.CONF.set_override("edge_ha", edge_ha,
group=group_name)
cfg.CONF.set_override("ha_datastore_id", ha_datastore_id,
group=group_name)
class NsxVPluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
def _create_network(self, fmt, name, admin_state_up,
@ -143,6 +160,7 @@ class NsxVPluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
self.default_res_pool = 'respool-28'
cfg.CONF.set_override("resource_pool_id", self.default_res_pool,
group="nsxv")
set_az_in_config('az7')
if service_plugins is not None:
# override the service plugins only if specified directly
super(NsxVPluginV2TestCase, self).setUp(
@ -646,8 +664,7 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxVPluginV2TestCase):
def test_create_network_with_az_hint(self):
az_name = 'az7'
az_config = az_name + ':respool-7:datastore-7:False'
cfg.CONF.set_override('availability_zones', [az_config], group="nsxv")
set_az_in_config(az_name)
p = directory.get_plugin()
p._availability_zones_data = nsx_az.ConfiguredAvailabilityZones()
ctx = context.get_admin_context()
@ -3158,8 +3175,7 @@ class TestExclusiveRouterTestCase(L3NatTest, L3NatTestCaseBase,
def test_create_router_with_az_hint(self):
az_name = 'az7'
az_config = az_name + ':respool-7:datastore-7:True'
cfg.CONF.set_override('availability_zones', [az_config], group="nsxv")
set_az_in_config(az_name)
p = directory.get_plugin()
p._availability_zones_data = nsx_az.ConfiguredAvailabilityZones()
p._get_edge_id_by_rtr_id = p.real_get_edge
@ -3367,9 +3383,7 @@ class TestVdrTestCase(L3NatTest, L3NatTestCaseBase,
def setUp(self, plugin=PLUGIN_NAME, ext_mgr=None, service_plugins=None):
# init the availability zones in the configuration of the plugin
self.az_name = 'az7'
az_config = self.az_name + ':respool-7:datastore-7:False'
cfg.CONF.set_override('availability_zones', [az_config], group="nsxv")
set_az_in_config(self.az_name)
super(TestVdrTestCase, self).setUp(
plugin=plugin, ext_mgr=ext_mgr, service_plugins=service_plugins)
self.plugin_instance.nsx_v.is_subnet_in_use = mock.Mock()
@ -3580,8 +3594,7 @@ class TestVdrTestCase(L3NatTest, L3NatTestCaseBase,
def _test_create_rotuer_with_az_hint(self, with_hint):
# init the availability zones in the plugin
az_name = 'az7'
az_config = az_name + ':respool-7:datastore-7:False'
cfg.CONF.set_override('availability_zones', [az_config], group="nsxv")
set_az_in_config(az_name)
p = directory.get_plugin()
p._availability_zones_data = nsx_az.ConfiguredAvailabilityZones()
@ -4837,8 +4850,7 @@ class TestSharedRouterTestCase(L3NatTest, L3NatTestCaseBase,
def _test_create_rotuer_with_az_hint(self, with_hint):
# init the availability zones in the plugin
az_name = 'az7'
az_config = az_name + ':respool-7:datastore-7:True'
cfg.CONF.set_override('availability_zones', [az_config], group="nsxv")
set_az_in_config(az_name)
p = directory.get_plugin()
p._availability_zones_data = nsx_az.ConfiguredAvailabilityZones()
@ -4911,8 +4923,7 @@ class TestRouterFlavorTestCase(extension.ExtensionTestCase,
# init the availability zones
self.az_name = 'az7'
az_config = self.az_name + ':respool-7:datastore-7:True'
cfg.CONF.set_override('availability_zones', [az_config], group="nsxv")
set_az_in_config(self.az_name)
self.plugin._availability_zones_data = (
nsx_az.ConfiguredAvailabilityZones())
self._iteration = 1