Merge "NSX|V network creation with availability zones hints"

This commit is contained in:
Jenkins 2016-05-30 12:24:36 +00:00 committed by Gerrit Code Review
commit 8486010cd4
4 changed files with 126 additions and 21 deletions

View File

@ -148,6 +148,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
"advanced-service-providers",
"subnet_allocation",
"availability_zone",
"network_availability_zone",
"router_availability_zone"]
supported_qos_rule_types = [qos_consts.RULE_TYPE_BANDWIDTH_LIMIT,
@ -497,6 +498,10 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
pnet.SEGMENTATION_ID: binding.vlan_id}
for binding in bindings]
# update availability zones
network[az_ext.AVAILABILITY_ZONES] = (
self.get_network_availability_zones(context, network))
def _get_subnet_as_providers(self, context, subnet):
net_id = subnet.get('network_id')
if net_id is None:
@ -720,10 +725,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
# is here only for overriding the original api
result = {}
for az in self._availability_zones_data.keys():
# Add this availability zone as a router resource
resource = 'router'
key = (az, resource)
result[key] = True
# Add this availability zone as a router & network resource
for resource in ('router', 'network'):
result[(az, resource)] = True
return result
def _validate_availability_zones_in_obj(self, context, resource_type,
@ -751,6 +755,16 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
raise az_ext.AvailabilityZoneNotFound(
availability_zone=diff.pop())
def get_network_resource_pool(self, context, network_id):
network = self.get_network(context, network_id)
if az_ext.AZ_HINTS in network:
for hint in network[az_ext.AZ_HINTS]:
# For now we use only the first hint
return self.get_res_pool_id_by_name(hint)
# return the default
return cfg.CONF.nsxv.resource_pool_id
def create_network(self, context, network):
net_data = network['network']
tenant_id = net_data['tenant_id']
@ -758,6 +772,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
# Process the provider network extension
provider_type = self._convert_to_transport_zones_dict(net_data)
self._validate_provider_create(context, net_data)
self._validate_availability_zones_in_obj(context, 'network', net_data)
net_data['id'] = str(uuid.uuid4())
external = net_data.get(ext_net_extn.EXTERNAL)
@ -839,6 +854,19 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
self._process_network_port_security_create(
context, net_data, new_net)
# update the network with the availability zone hints
if az_ext.AZ_HINTS in net_data:
self.validate_availability_zones(context, 'network',
net_data[az_ext.AZ_HINTS])
az_hints = az_ext.convert_az_list_to_string(
net_data[az_ext.AZ_HINTS])
super(NsxVPluginV2, self).update_network(context,
new_net['id'],
{'network': {az_ext.AZ_HINTS: az_hints}})
new_net[az_ext.AZ_HINTS] = az_hints
# still no availability zones until subnets creation
new_net[az_ext.AVAILABILITY_ZONES] = []
# DB Operations for setting the network as external
self._process_l3_create(context, new_net, net_data)
if (net_data.get(mpnet.SEGMENTS) and
@ -1960,16 +1988,37 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
super(NsxVPluginV2, self).delete_router(context, id)
router_driver.delete_router(context, id)
def _get_availability_zone_by_edge(self, context, edge_id):
resource_pool = nsxv_db.get_edge_resource_pool(
context.session, edge_id)
if resource_pool:
av_zone = self.get_res_pool_name_by_id(resource_pool)
return av_zone
db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
attr.NETWORKS, ['_extend_availability_zone_hints'])
def _extend_availability_zone_hints(self, net_res, net_db):
net_res[az_ext.AZ_HINTS] = az_ext.convert_az_string_to_list(
net_db[az_ext.AZ_HINTS])
def get_network_availability_zones(self, context, net_db):
"""Return availability zones which a network belongs to."""
resource_id = (vcns_const.DHCP_EDGE_PREFIX + net_db["id"])[:36]
dhcp_edge_binding = nsxv_db.get_nsxv_router_binding(
context.session, resource_id)
if dhcp_edge_binding:
edge_id = dhcp_edge_binding['edge_id']
return [self._get_availability_zone_by_edge(context, edge_id)]
return []
def get_router_availability_zones(self, router):
"""Return availability zones which a router belongs to."""
context = n_context.get_admin_context()
edge_id = self._get_edge_id_by_rtr_id(context, router["id"])
if edge_id:
resource_pool = nsxv_db.get_edge_resource_pool(
context.session, edge_id)
if resource_pool:
av_zone = self.get_res_pool_name_by_id(resource_pool)
return [av_zone]
return [self._get_availability_zone_by_edge(context, edge_id)]
return []
def get_router(self, context, id, fields=None):

View File

@ -740,12 +740,13 @@ class EdgeManager(object):
self.nsxv_manager.delete_edge(
router_id, edge_id, jobdata=jobdata, dist=dist)
def _allocate_dhcp_edge_appliance(self, context, resource_id):
def _allocate_dhcp_edge_appliance(self, context, resource_id, res_pool):
resource_name = (vcns_const.DHCP_EDGE_PREFIX +
_uuid())[:vcns_const.EDGE_NAME_LEN]
self._allocate_edge_appliance(
context, resource_id, resource_name,
appliance_size=vcns_const.SERVICE_SIZE_MAPPING['dhcp'])
appliance_size=vcns_const.SERVICE_SIZE_MAPPING['dhcp'],
res_pool=res_pool)
def _free_dhcp_edge_appliance(self, context, network_id):
router_id = (vcns_const.DHCP_EDGE_PREFIX + network_id)[:36]
@ -989,12 +990,12 @@ class EdgeManager(object):
available_edge_ids.append(x)
return (conflict_edge_ids, available_edge_ids)
def _get_used_edges(self, context, subnet):
def _get_used_edges(self, context, subnet, resource_pool):
"""Returns conflicting and available edges for the subnet."""
conflicting = self.plugin._get_conflicting_networks_for_subnet(
context, subnet)
return self._get_available_edges(context, subnet['network_id'],
conflicting)
conflicting, resource_pool)
def remove_network_from_dhcp_edge(self, context, network_id, edge_id):
old_binding = nsxv_db.get_edge_vnic_binding(
@ -1045,8 +1046,11 @@ class EdgeManager(object):
nsxv_db.allocate_edge_vnic_with_tunnel_index(
context.session, edge_id, network_id)
def allocate_new_dhcp_edge(self, context, network_id, resource_id):
self._allocate_dhcp_edge_appliance(context, resource_id)
def allocate_new_dhcp_edge(self, context, network_id, resource_id,
res_pool):
if not res_pool:
res_pool = cfg.CONF.nsxv.resource_pool_id
self._allocate_dhcp_edge_appliance(context, resource_id, res_pool)
with locking.LockManager.get_lock('nsx-edge-pool'):
new_edge = nsxv_db.get_nsxv_router_binding(context.session,
resource_id)
@ -1062,6 +1066,7 @@ class EdgeManager(object):
If new edge was allocated, return resource_id, else return None
"""
res_pool = self.plugin.get_network_resource_pool(context, network_id)
# Check if the network has one related dhcp edge
resource_id = (vcns_const.DHCP_EDGE_PREFIX + network_id)[:36]
dhcp_edge_binding = nsxv_db.get_nsxv_router_binding(context.session,
@ -1072,7 +1077,8 @@ class EdgeManager(object):
with locking.LockManager.get_lock('nsx-edge-pool'):
edge_id = dhcp_edge_binding['edge_id']
(conflict_edge_ids,
available_edge_ids) = self._get_used_edges(context, subnet)
available_edge_ids) = self._get_used_edges(context, subnet,
res_pool)
LOG.debug("The available edges %s, the conflict edges %s "
"at present is using edge %s",
available_edge_ids, conflict_edge_ids, edge_id)
@ -1106,7 +1112,8 @@ class EdgeManager(object):
else:
with locking.LockManager.get_lock('nsx-edge-pool'):
(conflict_edge_ids,
available_edge_ids) = self._get_used_edges(context, subnet)
available_edge_ids) = self._get_used_edges(context, subnet,
res_pool)
LOG.debug('The available edges %s, the conflict edges %s',
available_edge_ids, conflict_edge_ids)
# There is available one
@ -1124,7 +1131,8 @@ class EdgeManager(object):
allocate_new_edge = True
if allocate_new_edge:
self.allocate_new_dhcp_edge(context, network_id, resource_id)
self.allocate_new_dhcp_edge(context, network_id, resource_id,
res_pool)
# If a new Edge was allocated, return resource_id
return resource_id
@ -1219,7 +1227,6 @@ class EdgeManager(object):
def configure_dhcp_for_vdr_network(
self, context, network_id, vdr_router_id):
# If network is already attached to a DHCP Edge, detach from it
resource_id = (vcns_const.DHCP_EDGE_PREFIX + network_id)[:36]
dhcp_edge_binding = nsxv_db.get_nsxv_router_binding(context.session,
@ -1241,8 +1248,10 @@ class EdgeManager(object):
context, dhcp_edge_id, resource_id, network_id)
else:
# Attach to DHCP Edge
resource_pool = self.plugin.get_network_resource_pool(context,
network_id)
dhcp_edge_id = self.allocate_new_dhcp_edge(
context, network_id, resource_id)
context, network_id, resource_id, resource_pool)
self.plugin.metadata_proxy_handler.configure_router_edge(
resource_id, context)

View File

@ -603,6 +603,46 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxVPluginV2TestCase):
self.assertTrue(fake_init_from_policy.called)
self.assertTrue(fake_dvs_update.called)
def test_create_network_with_bad_az_hint(self):
p = manager.NeutronManager.get_plugin()
ctx = context.get_admin_context()
data = {'network': {
'name': 'test-qos',
'tenant_id': self._tenant_id,
'port_security_enabled': False,
'admin_state_up': True,
'shared': False,
'availability_zone_hints': ['bad_hint']
}}
self.assertRaises(n_exc.NeutronException,
p.create_network,
ctx, data)
def test_create_network_with_az_hint(self):
p = manager.NeutronManager.get_plugin()
ctx = context.get_admin_context()
alter_pool_id = 'respool-7'
alter_pool_name = 'rs-7'
p._availability_zones_data = {'default': self.default_res_pool,
alter_pool_name: alter_pool_id}
data = {'network': {
'name': 'test-qos',
'tenant_id': self._tenant_id,
'port_security_enabled': False,
'admin_state_up': True,
'shared': False,
'availability_zone_hints': [alter_pool_name]
}}
# network creation should succeed
net = p.create_network(ctx, data)
self.assertEqual([alter_pool_name],
net['availability_zone_hints'])
# the availability zone is still empty until subnet creation
self.assertEqual([],
net['availability_zones'])
class TestVnicIndex(NsxVPluginV2TestCase,
test_vnic_index.VnicIndexDbTestCase):

View File

@ -84,6 +84,11 @@ class EdgeUtilsTestCaseMixin(testlib_api.SqlTestCase):
resource_pool=binding['resource_pool'])
class DummyPlugin(object):
def get_network_resource_pool(self, context, network_id):
return cfg.CONF.nsxv.resource_pool_id
class EdgeDHCPManagerTestCase(EdgeUtilsTestCaseMixin):
def setUp(self):
@ -115,6 +120,7 @@ class EdgeDHCPManagerTestCase(EdgeUtilsTestCaseMixin):
self._populate_vcns_router_binding(fake_edge_pool)
fake_network = self._create_network()
fake_subnet = self._create_subnet(fake_network['id'])
self.edge_manager.plugin = DummyPlugin()
with mock.patch.object(self.edge_manager,
'_get_used_edges', return_value=([], [])):
self.edge_manager.create_dhcp_edge_service(self.ctx,
@ -125,7 +131,8 @@ class EdgeDHCPManagerTestCase(EdgeUtilsTestCaseMixin):
self.nsxv_manager.update_edge.assert_called_once_with(
resource_id, 'edge-1', mock.ANY, None, jobdata=jobdata,
appliance_size=vcns_const.SERVICE_SIZE_MAPPING['dhcp'],
dist=False, set_errors=True, res_pool=None)
dist=False, set_errors=True,
res_pool=cfg.CONF.nsxv.resource_pool_id)
def test_get_random_available_edge(self):
available_edge_ids = ['edge-1', 'edge-2']