Merge "NSX|V network creation with availability zones hints"
This commit is contained in:
commit
8486010cd4
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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']
|
||||
|
|
Loading…
Reference in New Issue