Add the switch to use necnwa_router or l3_router.

Add a new boolean switch use_necnwa_router in necnwa.ini.
If use_necnwa_router is True, NWA plugin uses a necnwa_router,
otherwise, the plugin uses OpenStack L3 router.

Change-Id: I494e72c33b1db96c46869d86948b4c9c9c8d4285
This commit is contained in:
Shinji YANAGIDA 2016-06-01 20:43:47 +09:00
parent c6db30f389
commit 619a1633a3
8 changed files with 112 additions and 214 deletions

View File

@ -37,6 +37,11 @@ function neutron_plugin_configure_common {
}
function neutron_plugin_configure_service {
if [ -n "$NECNWA_L3_PLUGIN" ]; then
iniset /$Q_PLUGIN_CONF_FILE NWA use_necnwa_router False
else
iniset /$Q_PLUGIN_CONF_FILE NWA use_necnwa_router True
fi
iniset /$Q_PLUGIN_CONF_FILE NWA server_url $NECNWA_SERVER_URL
iniset /$Q_PLUGIN_CONF_FILE NWA access_key_id $NECNWA_ACCESS_KEY_ID
iniset /$Q_PLUGIN_CONF_FILE NWA secret_access_key $NECNWA_SECRET_ACCESS_KEY

View File

@ -2,6 +2,7 @@
type_drivers = vlan
tenant_network_types = vlan
mechanism_drivers = necnwa,openvswitch
path_mtu = 0
[ml2_type_flat]
@ -19,11 +20,9 @@ enable_security_group = True
server_url = http://192.168.122.166:12081
access_key_id = mjivAk6O3G4Ko/0mD8mHUyQwqugEPgTe0FSli8REyN4=
secret_access_key = /3iSORtq1E3F+SQtQg6YN00eM3GUda0EKqWDUV/mvqo=
use_necnwa_router = True
resource_group_name = OpenStack/DC/APP
scenario_polling_timer = 5
scenario_polling_count = 300
region_name = T01DC
ironic_az_prefix = DC01_BMT
resource_group_file = resource_group.json
lbaas_driver = networking_nec.plugins.necnwa.agent.necnwa_lbaas_agent_driver.NECNWALBaaSAgentDriver
fwaas_driver = networking_nec.plugins.necnwa.agent.necnwa_fwaas_agent_driver.NECNWAFirewallAgentDriver

View File

@ -46,6 +46,9 @@ NWA_opts = [
help=_("Timer value for polling scenario status.")),
cfg.IntOpt('scenario_polling_count', default=6,
help=_("Count value for polling scenario status.")),
cfg.BoolOpt('use_necnwa_router',
help=_("Using necnwa_router insted of the l3-router"),
default=True),
cfg.StrOpt('ironic_az_prefix',
help=_("The prefix name of device_owner used in ironic"),
default='BM_'),

View File

@ -41,6 +41,7 @@ class NECNWAMechanismDriver(ovs.OpenvswitchMechanismDriver):
self.resource_groups = nwa_com_utils.load_json_from_file(
'resource_group', cfg.CONF.NWA.resource_group_file,
cfg.CONF.NWA.resource_group, default_value=[])
self.necnwa_router = cfg.CONF.NWA.use_necnwa_router
def _get_l2api_proxy(self, context, tenant_id):
proxy = context._plugin.get_nwa_proxy(tenant_id,
@ -52,15 +53,22 @@ class NECNWAMechanismDriver(ovs.OpenvswitchMechanismDriver):
context.network._plugin_context)
return nwa_l3_proxy_api.NwaL3ProxyApi(proxy.client)
def is_router(self, device_owner):
return device_owner in (constants.DEVICE_OWNER_ROUTER_INTF,
constants.DEVICE_OWNER_ROUTER_GW)
def create_port_precommit(self, context):
if not self.necnwa_router:
return
device_owner = context._port['device_owner']
if device_owner not in (constants.DEVICE_OWNER_ROUTER_INTF,
constants.DEVICE_OWNER_ROUTER_GW):
if not self.is_router(device_owner):
LOG.warning(_LW("device owner missmatch device_owner=%s"),
device_owner)
return
self._l3_create_tenant_fw(context)
self._bind_segment_to_vif_type(context)
physical_network = self._find_nwa_physical_network(context)
if physical_network:
self._bind_segment_to_vif_type(context, physical_network)
def update_port_precommit(self, context):
new_port = context.current
@ -82,8 +90,7 @@ class NECNWAMechanismDriver(ovs.OpenvswitchMechanismDriver):
{'tid': tenant_id, 'nid': nwa_tenant_id,
'dev': device_owner})
if device_owner in (constants.DEVICE_OWNER_ROUTER_GW,
constants.DEVICE_OWNER_ROUTER_INTF):
if self.necnwa_router and self.is_router(device_owner):
self._l3_delete_tenant_fw(context)
elif device_owner == constants.DEVICE_OWNER_FLOATINGIP:
pass
@ -93,50 +100,48 @@ class NECNWAMechanismDriver(ovs.OpenvswitchMechanismDriver):
self._l2_delete_general_dev(context)
def try_to_bind_segment_for_agent(self, context, segment, agent):
if self._bind_segment_to_vif_type(context, agent):
device_owner = context._port['device_owner']
if device_owner not in (constants.DEVICE_OWNER_ROUTER_GW,
constants.DEVICE_OWNER_ROUTER_INTF):
device_owner = context._port['device_owner']
if not self.necnwa_router or not self.is_router(device_owner):
physical_network = self._find_nwa_physical_network(context, agent)
if physical_network:
self._bind_segment_to_vif_type(context, physical_network)
self._bind_port_nwa_debug_message(context)
self._l2_create_general_dev(context)
return True
LOG.warning(_LW("binding segment not found for agent=%s"), agent)
LOG.warning(_LW("binding segment not found for agent=%s"), agent)
return super(
NECNWAMechanismDriver, self
).try_to_bind_segment_for_agent(context, segment, agent)
def _bind_segment_to_vif_type(self, context, agent=None):
def _find_nwa_physical_network(self, context, ovs_agent=None):
mappings = {}
if agent:
mappings = agent['configurations'].get('bridge_mappings', {})
if ovs_agent:
mappings = ovs_agent['configurations'].get('bridge_mappings', {})
for res in self.resource_groups:
if agent and res['ResourceGroupName'] not in mappings:
continue
if res['device_owner'] != context._port['device_owner']:
if ovs_agent and res['ResourceGroupName'] not in mappings:
continue
if res['device_owner'] == context._port['device_owner']:
return res['ResourceGroupName']
network_id = context.network.current['id']
dummy_segment = db.get_dynamic_segment(
context.network._plugin_context.session,
network_id, physical_network=res['ResourceGroupName'])
LOG.debug("1st: dummy segment is %s", dummy_segment)
if not dummy_segment:
dummy_segment = {
api.PHYSICAL_NETWORK: res['ResourceGroupName'],
api.NETWORK_TYPE: plugin_const.TYPE_VLAN,
api.SEGMENTATION_ID: 0
}
db.add_network_segment(
context.network._plugin_context.session,
network_id, dummy_segment, is_dynamic=True)
LOG.debug("2nd: dummy segment is %s", dummy_segment)
context.set_binding(dummy_segment[api.ID],
self.vif_type,
{portbindings.CAP_PORT_FILTER: True,
portbindings.OVS_HYBRID_PLUG: True})
return True
return False
def _bind_segment_to_vif_type(self, context, physical_network):
network_id = context.network.current['id']
session = context.network._plugin_context.session
dummy_segment = db.get_dynamic_segment(
session, network_id, physical_network=physical_network)
LOG.debug("1st: dummy segment is %s", dummy_segment)
if not dummy_segment:
dummy_segment = {
api.PHYSICAL_NETWORK: physical_network,
api.NETWORK_TYPE: plugin_const.TYPE_VLAN,
api.SEGMENTATION_ID: 0
}
db.add_network_segment(
session, network_id, dummy_segment, is_dynamic=True)
LOG.debug("2nd: dummy segment is %s", dummy_segment)
context.set_binding(dummy_segment[api.ID],
self.vif_type,
{portbindings.CAP_PORT_FILTER: True,
portbindings.OVS_HYBRID_PLUG: True})
def _bind_port_nwa_debug_message(self, context):
network_name, network_id = nwa_l2_utils.get_network_info(context)

View File

@ -12,18 +12,19 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron.db import api as db_api
from oslo_config import cfg
from neutron.extensions import portbindings
from neutron.extensions import portsecurity as psec
from neutron import manager
from neutron.plugins.ml2 import db as db_ml2
from neutron.plugins.ml2 import driver_api as api
from neutron.plugins.ml2 import rpc
from neutron.services.qos import qos_consts
from neutron_lib import constants
from oslo_log import log as logging
from networking_nec._i18n import _LW
from networking_nec.nwa.l2 import db_api as necnwa_api
from networking_nec._i18n import _LW, _LI
LOG = logging.getLogger(__name__)
@ -32,6 +33,10 @@ class NwaML2ServerRpcCallbacks(rpc.RpcCallbacks):
RPC_VERSION = '1.0'
def __init__(self, notifier, type_manager, necnwa_router=True):
super(NwaML2ServerRpcCallbacks, self).__init__(notifier, type_manager)
self.necnwa_router = cfg.CONF.NWA.use_necnwa_router
def get_device_details(self, rpc_context, **kwargs):
"""Agent requests device details."""
agent_id = kwargs.get('agent_id')
@ -51,19 +56,19 @@ class NwaML2ServerRpcCallbacks(rpc.RpcCallbacks):
host,
cached_networks)
if not port_context:
LOG.warning(_LW("Device %(device)s requested by agent "
"%(agent_id)s not found in database"),
{'device': device, 'agent_id': agent_id})
LOG.debug("Device %(device)s requested by agent "
"%(agent_id)s not found in database",
{'device': device, 'agent_id': agent_id})
return {'device': device}
segment = port_context.bottom_bound_segment
port = port_context.current
# caching information about networks for future use
if cached_networks is not None:
if port['network_id'] not in cached_networks:
cached_networks[port['network_id']] = (
port_context.network.current)
if not segment:
LOG.warning(_LW("Device %(device)s requested by agent "
"%(agent_id)s on network %(network_id)s not "
@ -71,17 +76,14 @@ class NwaML2ServerRpcCallbacks(rpc.RpcCallbacks):
{'device': device,
'agent_id': agent_id,
'network_id': port['network_id'],
'vif_type': port[portbindings.VIF_TYPE]})
'vif_type': port_context.vif_type})
return {'device': device}
elif segment['segmentation_id'] == 0:
LOG.warning(_LW("Device %(device)s requested by agent "
"%(agent_id)s, segment %(segment_id)s has "
"network %(network_id)s not no segment from NWA"),
{'device': device, 'agent_id': agent_id,
'segment_id': segment['id'],
'network_id': port['network_id']})
return {'device': device}
if segment['segmentation_id'] == 0:
entry = {'device': device}
LOG.info(_LI('The segmentation_id is not yet finalized, '
'it is replaced to return %s'), entry)
return entry
if not host or host == port_context.host:
new_status = (constants.PORT_STATUS_BUILD if port['admin_state_up']
@ -93,11 +95,14 @@ class NwaML2ServerRpcCallbacks(rpc.RpcCallbacks):
plugin.update_port_status(rpc_context,
port_id,
new_status,
host)
host,
port_context.network.current)
network_qos_policy_id = port_context.network._network.get(
qos_consts.QOS_POLICY_ID)
entry = {'device': device,
'network_id': port['network_id'],
'port_id': port_id,
'port_id': port['id'],
'mac_address': port['mac_address'],
'admin_state_up': port['admin_state_up'],
'network_type': segment[api.NETWORK_TYPE],
@ -107,107 +112,17 @@ class NwaML2ServerRpcCallbacks(rpc.RpcCallbacks):
'device_owner': port['device_owner'],
'allowed_address_pairs': port['allowed_address_pairs'],
'port_security_enabled': port.get(psec.PORTSECURITY, True),
'qos_policy_id': port.get(qos_consts.QOS_POLICY_ID),
'network_qos_policy_id': network_qos_policy_id,
'profile': port[portbindings.PROFILE]}
LOG.debug("Returning: %s", entry)
return entry
def _get_device_details(self, rpc_context, **kwargs):
"""Agent requests device details."""
agent_id = kwargs.get('agent_id')
device = kwargs.get('device')
host = kwargs.get('host')
LOG.debug("Device %(device)s details requested by agent "
"%(agent_id)s with host %(host)s",
{'device': device, 'agent_id': agent_id, 'host': host})
plugin = manager.NeutronManager.get_plugin()
port_id = plugin._device_to_port_id(device)
port_context = plugin.get_bound_port_context(rpc_context,
port_id,
host)
if not port_context:
LOG.warning(_LW("Device %(device)s requested by agent "
"%(agent_id)s not found in database"),
{'device': device, 'agent_id': agent_id})
return {'device': device}
port = port_context.current
session = db_api.get_session()
with session.begin(subtransactions=True):
segments = db_ml2.get_network_segments(session, port['network_id'],
filter_dynamic=True)
if not segments:
LOG.warning(_LW("Device %(device)s requested by agent "
"%(agent_id)s has network %(network_id)s not "
"no segment"),
{'device': device, 'agent_id': agent_id,
'network_id': port['network_id']})
return {'device': device}
elif len(segments) != 1:
LOG.warning(_LW("Device %(device)s requested by agent "
"%(agent_id)s has network %(network_id)s not "
"no segment size miss mach"),
{'device': device, 'agent_id': agent_id,
'network_id': port['network_id']})
return {'device': device}
elif segments[0]['segmentation_id'] == 0:
LOG.warning(_LW("Device %(device)s requested by agent "
"%(agent_id)s, segment %(segment_id)s has "
"network %(network_id)s not "
"no segment from NWA"),
{'device': device, 'agent_id': agent_id,
'segment_id': segments[0]['id'],
'network_id': port['network_id']})
return {'device': device}
binding = necnwa_api.ensure_port_binding(session, port_id)
if not binding.segment_id:
LOG.warning(_LW("Device %(device)s requested by agent "
"%(agent_id)s on network %(network_id)s not "
"bound, vif_type: %(vif_type)s"),
{'device': device,
'agent_id': agent_id,
'network_id': port['network_id'],
'vif_type': binding.vif_type})
return {'device': device}
port = port_context.current
new_status = (constants.PORT_STATUS_BUILD if port['admin_state_up']
else constants.PORT_STATUS_DOWN)
if (
port['status'] != new_status and
port['status'] != constants.PORT_STATUS_ACTIVE
):
plugin.update_port_status(rpc_context,
port_id,
new_status,
host)
entry = {'device': device,
'network_id': port['network_id'],
'port_id': port_id,
'mac_address': port['mac_address'],
'admin_state_up': port['admin_state_up'],
'network_type': segments[0]['network_type'],
'segmentation_id': segments[0]['segmentation_id'],
'physical_network': segments[0]['physical_network'],
'fixed_ips': port['fixed_ips'],
'device_owner': port['device_owner'],
'profile': port[portbindings.PROFILE]}
if 'security_groups' in port:
entry['security_groups'] = port['security_groups']
LOG.debug("Returning: %s", entry)
return entry
def update_device_up(self, rpc_context, **kwargs):
"""Device is up on agent."""
# agent_id = kwargs.get('agent_id')
# device = kwargs.get('device')
# plugin = manager.NeutronManager.get_plugin()
# port_id = plugin._device_to_port_id(device)
return
if self.necnwa_router:
return
super(NwaML2ServerRpcCallbacks, self).update_device_up(rpc_context,
**kwargs)

View File

@ -42,6 +42,10 @@ class TestNWAConfig(base.BaseTestCase):
def test_section_default_NWA_scenario_polling_count(self):
self.assertEqual(cfg.CONF.NWA.scenario_polling_count, 6)
def test_section_default_NWA_use_necnwa_router(self):
self.assertIsInstance(cfg.CONF.NWA.use_necnwa_router, bool)
self.assertTrue(cfg.CONF.NWA.use_necnwa_router)
def test_section_default_NWA_ironic_az_prefix(self):
self.assertEqual(cfg.CONF.NWA.ironic_az_prefix, 'BM_')

View File

@ -535,25 +535,35 @@ class TestNECNWAMechanismDriver(TestMechNwa):
self.context, self.network_segments[2], self.host_agents[0])
self.assertEqual(rb, True)
def test__bind_segment_to_vif_type(self):
def test__find_nwa_physical_network(self):
pod3_eth1 = self.host_agents[0]
rb = self.driver._bind_segment_to_vif_type(self.context, pod3_eth1)
self.assertEqual(rb, True)
physnet = self.driver._find_nwa_physical_network(self.context,
pod3_eth1)
self.assertEqual(physnet, 'Common/App/Pod3')
def test__bind_segment_to_vif_type_no_match(self):
rb = self.driver._bind_segment_to_vif_type(self.context,
self.host_agents[1])
self.assertEqual(rb, False)
def test__find_nwa_physical_network_no_match(self):
physnet = self.driver._find_nwa_physical_network(self.context,
self.host_agents[1])
self.assertIsNone(physnet)
def test__bind_segment_to_vif_type_agent_none(self):
rb = self.driver._bind_segment_to_vif_type(self.context)
self.assertEqual(rb, True)
def test__find_nwa_physical_network_agent_none(self):
physnet = self.driver._find_nwa_physical_network(self.context)
self.assertEqual(physnet, 'Common/App/Pod3')
@patch('neutron.plugins.ml2.db.get_dynamic_segment')
def test__bind_segment_to_vif_type_dummy_segment_none(self, gds):
gds.return_value = None
rb = self.driver._bind_segment_to_vif_type(self.context)
self.assertEqual(rb, True)
physnet = 'Common/App/Pod3'
rd = self.driver._bind_segment_to_vif_type(self.context, physnet)
self.assertIsNone(rd)
@patch('neutron.plugins.ml2.db.get_dynamic_segment')
@patch('neutron.plugins.ml2.db.add_network_segment')
def test__bind_segment_to_vif_type_dummy_segment_exists(self, ans, gds):
gds.return_value = self.network_segments[1]
physnet = 'Common/KVM/Pod1-2'
self.driver._bind_segment_to_vif_type(self.context, physnet)
self.assertEqual(0, ans.call_count)
@patch('networking_nec.nwa.l2.db_api.get_nwa_tenant_binding')
def _test__bind_port_nwa(self, gntb):

View File

@ -58,6 +58,7 @@ class TestNECNWAServerRpcCallbacks(base.BaseTestCase):
self.port_context = PortContext
self.port_context.bottom_bound_segment = mock.MagicMock()
self.port_context.current = mock.MagicMock()
self.port_context.network = mock.MagicMock()
@mock.patch('networking_nec.nwa.l2.plugin.'
'NECNWAL2Plugin.get_bound_port_context')
@ -114,49 +115,6 @@ class TestNECNWAServerRpcCallbacks(base.BaseTestCase):
"sample"})
self.assertTrue(device)
@mock.patch('neutron.plugins.ml2.plugin.Ml2Plugin.update_port_status')
@mock.patch('neutron.plugins.ml2.db.get_network_segments')
@mock.patch('neutron.db.api.get_session')
@mock.patch('networking_nec.nwa.l2.plugin.'
'NECNWAL2Plugin.get_bound_port_context')
@mock.patch('networking_nec.nwa.l2.plugin.'
'NECNWAL2Plugin._device_to_port_id')
@mock.patch('neutron.manager.NeutronManager.get_plugin')
def test__get_device_details_segment_zero(self, f1, f2, f3, f4, f5, f6):
rpc_context = mock.MagicMock()
f1.return_value = self.l2_plugin
f2.return_value = None
f3.current = True
f4.begin.return_value = None
f5.return_value = [{'segmentation_id': 0, 'id': 'seg-id'}]
device = self.rpc._get_device_details(rpc_context, kwargs={'test':
"sample"})
self.assertTrue(device)
@mock.patch('neutron.plugins.ml2.plugin.Ml2Plugin.update_port_status')
@mock.patch('neutron.plugins.ml2.db.get_network_segments')
@mock.patch('neutron.db.api.get_session')
@mock.patch('networking_nec.nwa.l2.plugin.'
'NECNWAL2Plugin.get_bound_port_context')
@mock.patch('networking_nec.nwa.l2.plugin.'
'NECNWAL2Plugin._device_to_port_id')
@mock.patch('neutron.manager.NeutronManager.get_plugin')
def test__get_device_details_segment_no_zero(self, f1, f2, f3, f4, f5, f6):
rpc_context = mock.MagicMock()
f1.return_value = self.l2_plugin
f2.return_value = None
f3.current = True
f4.begin.return_value = None
f5.return_value = [{'segmentation_id': 1,
'id': 'seg-id',
'network_type': 'vlan',
'physical_network': 'OpenStack/DC1/APP'}]
device = self.rpc._get_device_details(rpc_context, kwargs={'test':
"sample"})
self.assertTrue(device)
@mock.patch('neutron.plugins.ml2.plugin.Ml2Plugin.update_port_status')
@mock.patch('neutron.plugins.ml2.db.get_network_segments')
@mock.patch('neutron.db.api.get_session')
@ -263,7 +221,6 @@ class TestNECNWAServerRpcCallbacks(base.BaseTestCase):
@mock.patch('neutron.manager.NeutronManager.get_plugin')
def test_get_device_details_port_state_change(self, f1, f2, f3, f4, f5,
f6, f7):
rpc_context = mock.MagicMock()
f1.return_value = self.l2_plugin
f2.return_value = None