port_fault_status and switch_fault_status
port_fault_status and switch_fault_status implementation. reflect the same status in neutron db from ovsdb. raises appropriate error message while creating l2gateway connection if switch_fault_status and port_fault_status is not UP. Change-Id: Icc77392afeb62bd2b0b0b816a63f8f02b442b0d8stable/ocata
parent
c43e6f293b
commit
91214d2bc7
|
@ -73,7 +73,8 @@ def add_physical_switch(context, record_dict):
|
|||
uuid=record_dict['uuid'],
|
||||
name=record_dict['name'],
|
||||
tunnel_ip=record_dict['tunnel_ip'],
|
||||
ovsdb_identifier=record_dict['ovsdb_identifier'])
|
||||
ovsdb_identifier=record_dict['ovsdb_identifier'],
|
||||
switch_fault_status=record_dict['switch_fault_status'])
|
||||
session.add(physical_switch)
|
||||
|
||||
|
||||
|
@ -117,10 +118,29 @@ def add_physical_port(context, record_dict):
|
|||
uuid=record_dict['uuid'],
|
||||
name=record_dict['name'],
|
||||
physical_switch_id=record_dict['physical_switch_id'],
|
||||
ovsdb_identifier=record_dict['ovsdb_identifier'])
|
||||
ovsdb_identifier=record_dict['ovsdb_identifier'],
|
||||
port_fault_status=record_dict['port_fault_status'])
|
||||
session.add(physical_port)
|
||||
|
||||
|
||||
def update_physical_ports_status(context, record_dict):
|
||||
"""Update physical port fault status."""
|
||||
with context.session.begin(subtransactions=True):
|
||||
(context.session.query(models.PhysicalPorts).
|
||||
filter(models.PhysicalPorts.uuid == record_dict['uuid']).
|
||||
update({'port_fault_status': record_dict['port_fault_status']},
|
||||
synchronize_session=False))
|
||||
|
||||
|
||||
def update_physical_switch_status(context, record_dict):
|
||||
"""Update physical switch fault status."""
|
||||
with context.session.begin(subtransactions=True):
|
||||
(context.session.query(models.PhysicalSwitches).
|
||||
filter(models.PhysicalSwitches.uuid == record_dict['uuid']).
|
||||
update({'switch_fault_status': record_dict['switch_fault_status']},
|
||||
synchronize_session=False))
|
||||
|
||||
|
||||
def delete_physical_port(context, record_dict):
|
||||
"""Delete physical port that matches the supplied uuid."""
|
||||
session = context.session
|
||||
|
|
|
@ -35,6 +35,7 @@ class PhysicalSwitches(model_base.BASEV2):
|
|||
tunnel_ip = sa.Column(sa.String(64), nullable=False)
|
||||
ovsdb_identifier = sa.Column(sa.String(64), nullable=False,
|
||||
primary_key=True)
|
||||
switch_fault_status = sa.Column(sa.String(length=16), nullable=True)
|
||||
__table_args__ = (sa.UniqueConstraint(uuid,
|
||||
ovsdb_identifier),)
|
||||
|
||||
|
@ -46,6 +47,7 @@ class PhysicalPorts(model_base.BASEV2):
|
|||
physical_switch_id = sa.Column(sa.String(36), nullable=False)
|
||||
ovsdb_identifier = sa.Column(sa.String(64), nullable=False,
|
||||
primary_key=True)
|
||||
port_fault_status = sa.Column(sa.String(length=16), nullable=True)
|
||||
__table_args__ = (sa.UniqueConstraint(uuid,
|
||||
ovsdb_identifier),)
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ def upgrade():
|
|||
nullable=True),
|
||||
sa.Column('ovsdb_identifier', sa.String(length=64),
|
||||
nullable=False),
|
||||
sa.Column('switch_fault_status', sa.String(length=16),
|
||||
nullable=True),
|
||||
sa.PrimaryKeyConstraint('uuid', 'ovsdb_identifier'))
|
||||
|
||||
op.create_table('physical_ports',
|
||||
|
@ -53,6 +55,8 @@ def upgrade():
|
|||
nullable=True),
|
||||
sa.Column('ovsdb_identifier', sa.String(length=64),
|
||||
nullable=False),
|
||||
sa.Column('port_fault_status', sa.String(length=16),
|
||||
nullable=True),
|
||||
sa.PrimaryKeyConstraint('uuid', 'ovsdb_identifier'))
|
||||
|
||||
op.create_table('logical_switches',
|
||||
|
|
|
@ -298,7 +298,8 @@ class OVSDBMonitor(base_connection.BaseConnection):
|
|||
old_row = uuid_dict.get('old', None)
|
||||
if new_row:
|
||||
port = ovsdb_schema.PhysicalPort(uuid, new_row.get('name'), None,
|
||||
None)
|
||||
None,
|
||||
new_row.get('port_fault_status'))
|
||||
switch_id = port_map.get(uuid, None)
|
||||
if switch_id:
|
||||
port.physical_switch_id = switch_id
|
||||
|
@ -328,7 +329,8 @@ class OVSDBMonitor(base_connection.BaseConnection):
|
|||
elif old_row:
|
||||
# Port is deleted permanently from OVSDB server
|
||||
port = ovsdb_schema.PhysicalPort(uuid, old_row.get('name'), None,
|
||||
None)
|
||||
None,
|
||||
old_row.get('port_fault_status'))
|
||||
deleted_physical_ports = data_dict.get('deleted_physical_ports')
|
||||
deleted_physical_ports.append(port)
|
||||
|
||||
|
@ -356,10 +358,9 @@ class OVSDBMonitor(base_connection.BaseConnection):
|
|||
for inner_port in port:
|
||||
if inner_port != 'uuid':
|
||||
all_ports.append(inner_port)
|
||||
phys_switch = ovsdb_schema.PhysicalSwitch(uuid,
|
||||
new_row.get('name'),
|
||||
new_row.get('tunnel_ips')
|
||||
)
|
||||
phys_switch = ovsdb_schema.PhysicalSwitch(
|
||||
uuid, new_row.get('name'), new_row.get('tunnel_ips'),
|
||||
new_row.get('switch_fault_status'))
|
||||
# Now, store mapping of physical ports to
|
||||
# physical switch so that it is useful while
|
||||
# processing Physical_Switch record
|
||||
|
@ -379,10 +380,9 @@ class OVSDBMonitor(base_connection.BaseConnection):
|
|||
elif old_row:
|
||||
# Physical switch is deleted permanently from OVSDB
|
||||
# server
|
||||
phys_switch = ovsdb_schema.PhysicalSwitch(uuid,
|
||||
old_row.get('name'),
|
||||
old_row.get('tunnel_ips')
|
||||
)
|
||||
phys_switch = ovsdb_schema.PhysicalSwitch(
|
||||
uuid, old_row.get('name'), old_row.get('tunnel_ips'),
|
||||
old_row.get('switch_fault_status'))
|
||||
deleted_physical_switches = data_dict.get(
|
||||
'deleted_physical_switches')
|
||||
deleted_physical_switches.append(phys_switch)
|
||||
|
|
|
@ -40,3 +40,5 @@ L2_GATEWAYS_CONNECTION = "%ss" % EXT_ALIAS
|
|||
BUFFER_SIZE = 4096
|
||||
MAX_RETRIES = 500
|
||||
L2_GATEWAY_SERVICE_PLUGIN = "Neutron L2 gateway Service Plugin"
|
||||
PORT_FAULT_STATUS_UP = "UP"
|
||||
SWITCH_FAULT_STATUS_UP = "UP"
|
||||
|
|
|
@ -21,18 +21,21 @@ class PhysicalLocator(object):
|
|||
|
||||
|
||||
class PhysicalSwitch(object):
|
||||
def __init__(self, uuid, name, tunnel_ip):
|
||||
def __init__(self, uuid, name, tunnel_ip, switch_fault_status):
|
||||
self.uuid = uuid
|
||||
self.name = name
|
||||
self.tunnel_ip = tunnel_ip
|
||||
self.switch_fault_status = switch_fault_status
|
||||
|
||||
|
||||
class PhysicalPort(object):
|
||||
def __init__(self, uuid, name, phys_switch_id, vlan_binding_dicts):
|
||||
def __init__(self, uuid, name, phys_switch_id, vlan_binding_dicts,
|
||||
port_fault_status):
|
||||
self.uuid = uuid
|
||||
self.name = name
|
||||
self.physical_switch_id = phys_switch_id
|
||||
self.vlan_bindings = []
|
||||
self.port_fault_status = port_fault_status
|
||||
if vlan_binding_dicts:
|
||||
for vlan_binding in vlan_binding_dicts:
|
||||
v_binding = VlanBinding(vlan_binding['vlan'],
|
||||
|
|
|
@ -60,6 +60,16 @@ class L2GatewayInterfaceNotFound(exceptions.NeutronException):
|
|||
message = _("L2 Gateway interface not found on '%(interface_id)s'")
|
||||
|
||||
|
||||
class L2GatewayPhysicalPortFaultStatus(exceptions.NeutronException):
|
||||
message = _("Physical Port '%(int_name)s' in Physical switch "
|
||||
"'%(device_name)s' port_fault_status is '%(fault_status)s'")
|
||||
|
||||
|
||||
class L2GatewayPhysicalSwitchFaultStatus(exceptions.NeutronException):
|
||||
message = _("Physical Switch '%(device_name)s' switch_fault_status is "
|
||||
"'%(fault_status)s'")
|
||||
|
||||
|
||||
class L2GatewayConnectionNotFound(exceptions.NotFound):
|
||||
message = _("The connection %(id)s not found on the l2 gateway")
|
||||
|
||||
|
|
|
@ -89,6 +89,8 @@ class OVSDBData(object):
|
|||
self._process_deleted_local_macs,
|
||||
'deleted_remote_macs':
|
||||
self._process_deleted_remote_macs,
|
||||
'modified_physical_switches':
|
||||
self._process_modified_physical_switches,
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -193,6 +195,7 @@ class OVSDBData(object):
|
|||
pp_dict[n_const.OVSDB_IDENTIFIER] = self.ovsdb_identifier
|
||||
modified_port = db.get_physical_port(context, pp_dict)
|
||||
if modified_port:
|
||||
db.update_physical_ports_status(context, pp_dict)
|
||||
port_vlan_bindings = physical_port.get('vlan_bindings')
|
||||
vlan_bindings = db.get_all_vlan_bindings_by_physical_port(
|
||||
context, pp_dict)
|
||||
|
@ -206,6 +209,11 @@ class OVSDBData(object):
|
|||
else:
|
||||
db.add_physical_port(context, pp_dict)
|
||||
|
||||
def _process_modified_physical_switches(self, context,
|
||||
modified_physical_switches):
|
||||
for physical_switch in modified_physical_switches:
|
||||
db.update_physical_switch_status(context, physical_switch)
|
||||
|
||||
def _process_deleted_logical_switches(self,
|
||||
context,
|
||||
deleted_logical_switches):
|
||||
|
|
|
@ -258,9 +258,37 @@ class L2GatewayPlugin(l2gateway_db.L2GatewayMixin):
|
|||
logical_switch_uuid,
|
||||
mac_list)
|
||||
|
||||
def _check_port_fault_status_and_switch_fault_status(self, context,
|
||||
l2_gateway_id):
|
||||
l2gw = self.get_l2_gateway(context, l2_gateway_id)
|
||||
devices = l2gw['devices']
|
||||
rec_dict = {}
|
||||
for device in devices:
|
||||
device_name = device['device_name']
|
||||
dev_db = db.get_physical_switch_by_name(context, device_name)
|
||||
rec_dict['physical_switch_id'] = dev_db['uuid']
|
||||
rec_dict['ovsdb_identifier'] = dev_db['ovsdb_identifier']
|
||||
status = dev_db.get('switch_fault_status')
|
||||
if status != constants.SWITCH_FAULT_STATUS_UP:
|
||||
raise l2gw_exc.L2GatewayPhysicalSwitchFaultStatus(
|
||||
device_name=device_name, fault_status=status)
|
||||
for interface_list in device['interfaces']:
|
||||
int_name = interface_list.get('name')
|
||||
rec_dict['interface_name'] = int_name
|
||||
port_db = db.get_physical_port_by_name_and_ps(context,
|
||||
rec_dict)
|
||||
port_status = port_db['port_fault_status']
|
||||
if (port_db['port_fault_status']) != (
|
||||
constants.PORT_FAULT_STATUS_UP):
|
||||
raise l2gw_exc.L2GatewayPhysicalPortFaultStatus(
|
||||
int_name=int_name, device_name=device_name,
|
||||
fault_status=port_status)
|
||||
|
||||
def _validate_connection(self, context, gw_connection):
|
||||
seg_id = gw_connection.get('segmentation_id', None)
|
||||
l2_gw_id = gw_connection.get('l2_gateway_id')
|
||||
self._check_port_fault_status_and_switch_fault_status(context,
|
||||
l2_gw_id)
|
||||
check_vlan = self._is_vlan_configured_on_any_interface_for_l2gw(
|
||||
context, l2_gw_id)
|
||||
nw_map = {}
|
||||
|
@ -358,7 +386,8 @@ class L2GatewayPlugin(l2gateway_db.L2GatewayMixin):
|
|||
uuid=pp_dict.get('uuid'),
|
||||
name=pp_dict.get('interface_name'),
|
||||
phys_switch_id=pp_dict.get('physical_switch_id'),
|
||||
vlan_binding_dicts=None))
|
||||
vlan_binding_dicts=None,
|
||||
port_fault_status=None))
|
||||
physical_port['vlan_bindings'] = port_list
|
||||
else:
|
||||
vlan_id = gw_connection.get('segmentation_id')
|
||||
|
@ -377,7 +406,8 @@ class L2GatewayPlugin(l2gateway_db.L2GatewayMixin):
|
|||
uuid=pp_dict.get('uuid'),
|
||||
name=pp_dict.get('interface_name'),
|
||||
phys_switch_id=pp_dict.get('physical_switch_id'),
|
||||
vlan_binding_dicts=None))
|
||||
vlan_binding_dicts=None,
|
||||
port_fault_status=None))
|
||||
physical_port['vlan_bindings'] = port_list
|
||||
return physical_port
|
||||
|
||||
|
|
|
@ -374,6 +374,7 @@ class TestOVSDBMonitor(base.BaseTestCase):
|
|||
add = {'new': {'uuid': 'fake_id',
|
||||
'name': 'fake_name',
|
||||
'physical_switch_id': 'fake_switch_id',
|
||||
'port_fault_status': 'fake_status',
|
||||
'vlan_bindings': [["some"], []]}}
|
||||
delete = {'old': {'uuid': 'fake_id_old',
|
||||
'name': 'fake_name_old',
|
||||
|
@ -393,7 +394,8 @@ class TestOVSDBMonitor(base.BaseTestCase):
|
|||
add,
|
||||
port_map,
|
||||
data_dict)
|
||||
phy_port.assert_called_with(fake_id, 'fake_name', None, None)
|
||||
phy_port.assert_called_with(fake_id, 'fake_name', None, None,
|
||||
'fake_status')
|
||||
self.assertIn(phy_port.return_value,
|
||||
data_dict.get('new_physical_ports'))
|
||||
|
||||
|
@ -422,6 +424,7 @@ class TestOVSDBMonitor(base.BaseTestCase):
|
|||
add = {'new': {'uuid': 'fake_id',
|
||||
'name': 'fake_name',
|
||||
'tunnel_ips': 'fake_tunnel_ip',
|
||||
'switch_fault_status': 'fake_status',
|
||||
'ports': ['set', 'set',
|
||||
physical_port]}}
|
||||
delete = {'old': {'uuid': 'fake_id_old',
|
||||
|
@ -441,6 +444,8 @@ class TestOVSDBMonitor(base.BaseTestCase):
|
|||
data_dict)
|
||||
self.assertIn(phy_switch.return_value,
|
||||
data_dict['new_physical_switches'])
|
||||
phy_switch.assert_called_with('fake_id', 'fake_name',
|
||||
'fake_tunnel_ip', 'fake_status')
|
||||
# test modify
|
||||
self.l2gw_ovsdb._process_physical_switch(fake_id,
|
||||
modify,
|
||||
|
|
|
@ -364,14 +364,18 @@ class TestOVSDBData(base.BaseTestCase):
|
|||
mock.patch.object(lib,
|
||||
'get_all_vlan_bindings_by_physical_port'),
|
||||
mock.patch.object(lib,
|
||||
'add_vlan_binding')) as (
|
||||
get_pp, add_pp, get_vlan, add_vlan):
|
||||
'add_vlan_binding'),
|
||||
mock.patch.object(lib,
|
||||
'update_physical_ports_status')
|
||||
) as (
|
||||
get_pp, add_pp, get_vlan, add_vlan, update_pp_status):
|
||||
self.ovsdb_data._process_modified_physical_ports(
|
||||
self.context, fake_modified_physical_ports)
|
||||
self.assertIn(n_const.OVSDB_IDENTIFIER, fake_dict2)
|
||||
self.assertEqual(fake_dict2[n_const.OVSDB_IDENTIFIER],
|
||||
'fake_ovsdb_id')
|
||||
get_pp.assert_called_with(self.context, fake_dict2)
|
||||
update_pp_status.assert_called_with(self.context, fake_dict2)
|
||||
self.assertFalse(add_pp.called)
|
||||
get_vlan.assert_called_with(self.context, fake_dict2)
|
||||
self.assertIn(n_const.OVSDB_IDENTIFIER, fake_dict1)
|
||||
|
|
|
@ -25,6 +25,7 @@ from networking_l2gw.db.l2gateway.ovsdb import lib as db
|
|||
from networking_l2gw.services.l2gateway import agent_scheduler
|
||||
from networking_l2gw.services.l2gateway.common import config
|
||||
from networking_l2gw.services.l2gateway.common import l2gw_validators
|
||||
from networking_l2gw.services.l2gateway import exceptions as l2gw_exc
|
||||
from networking_l2gw.services.l2gateway import plugin as l2gw_plugin
|
||||
|
||||
from oslo_utils import importutils
|
||||
|
@ -202,9 +203,12 @@ class TestL2GatewayPlugin(base.BaseTestCase):
|
|||
return_value=fake_tenant_id),
|
||||
mock.patch.object(l2gateway_db.L2GatewayMixin,
|
||||
'get_l2_gateway_connections',
|
||||
return_value=False)) as (
|
||||
is_vlan, val_ntwk, get_net_seg, get_network, get_l2gw,
|
||||
ret_gw_conn, get_ten_id, get_l2_gw_conn):
|
||||
return_value=False),
|
||||
mock.patch.object(
|
||||
self.plugin,
|
||||
'_check_port_fault_status_and_switch_fault_status')
|
||||
) as (is_vlan, val_ntwk, get_net_seg, get_network, get_l2gw,
|
||||
ret_gw_conn, get_ten_id, get_l2_gw_conn, check_pf_sf):
|
||||
self.plugin._validate_connection(self.context, fake_connection)
|
||||
is_vlan.assert_called_with(self.context, 'fake_l2gw_id')
|
||||
val_ntwk.assert_called_with(fake_connection, False)
|
||||
|
@ -212,6 +216,7 @@ class TestL2GatewayPlugin(base.BaseTestCase):
|
|||
'fake_network_id')
|
||||
get_network.assert_called_with(self.context, 'fake_network_id')
|
||||
get_l2gw.assert_called_with(self.context, 'fake_l2gw_id')
|
||||
check_pf_sf.assert_called_with(self.context, 'fake_l2gw_id')
|
||||
ret_gw_conn.assert_called_with(self.context,
|
||||
'fake_l2gw_id',
|
||||
fake_connection)
|
||||
|
@ -632,6 +637,69 @@ class TestL2GatewayPlugin(base.BaseTestCase):
|
|||
self.assertTrue(update_rpc.called)
|
||||
del_conn.assert_called_with(self.db_context, fake_conn_dict)
|
||||
|
||||
def test_create_l2gateway_connection_with_switch_fault_status_down(self):
|
||||
self.db_context = ctx.get_admin_context()
|
||||
fake_l2gw_conn_dict = {'l2_gateway_connection': {
|
||||
'id': 'fake_id', 'network_id': 'fake_network_id',
|
||||
'l2_gateway_id': 'fake_l2gw_id'}}
|
||||
fake_device = {'devices': [{'device_name': 'fake_device',
|
||||
'interfaces': [{'name': 'fake_interface'}]}]}
|
||||
fake_physical_port = {'uuid': 'fake_id',
|
||||
'name': 'fake_name',
|
||||
'physical_switch_id': 'fake_switch1',
|
||||
'port_fault_status': 'UP'}
|
||||
fake_physical_switch = {'uuid': 'fake_id',
|
||||
'name': 'fake_name',
|
||||
'tunnel_ip': 'fake_tunnel_ip',
|
||||
'ovsdb_identifier': 'fake_ovsdb_id',
|
||||
'switch_fault_status': 'DOWN'}
|
||||
with contextlib.nested(
|
||||
mock.patch.object(l2gateway_db.L2GatewayMixin,
|
||||
'_admin_check',
|
||||
return_value=True),
|
||||
mock.patch.object(l2gateway_db.L2GatewayMixin, 'get_l2_gateway',
|
||||
return_value=fake_device),
|
||||
mock.patch.object(db, 'get_physical_port_by_name_and_ps',
|
||||
return_value=fake_physical_port),
|
||||
mock.patch.object(db, 'get_physical_switch_by_name',
|
||||
return_value=fake_physical_switch)
|
||||
) as (get_l2gw, admin_check, phy_port, phy_switch):
|
||||
self.assertRaises(l2gw_exc.L2GatewayPhysicalSwitchFaultStatus,
|
||||
self.plugin.create_l2_gateway_connection,
|
||||
self.db_context,
|
||||
fake_l2gw_conn_dict)
|
||||
|
||||
def test_create_l2gateway_connection_with_port_fault_status_down(self):
|
||||
self.db_context = ctx.get_admin_context()
|
||||
fake_l2gw_conn_dict = {'l2_gateway_connection': {
|
||||
'id': 'fake_id', 'network_id': 'fake_network_id',
|
||||
'l2_gateway_id': 'fake_l2gw_id'}}
|
||||
fake_device = {'devices': [{'device_name': 'fake_device',
|
||||
'interfaces': [{'name': 'fake_interface'}]}]}
|
||||
fake_physical_port = {'uuid': 'fake_id',
|
||||
'name': 'fake_name',
|
||||
'physical_switch_id': 'fake_switch1',
|
||||
'port_fault_status': 'DOWN'}
|
||||
fake_physical_switch = {'uuid': 'fake_id',
|
||||
'name': 'fake_name',
|
||||
'tunnel_ip': 'fake_tunnel_ip',
|
||||
'ovsdb_identifier': 'fake_ovsdb_id',
|
||||
'switch_fault_status': 'UP'}
|
||||
with contextlib.nested(
|
||||
mock.patch.object(l2gateway_db.L2GatewayMixin,
|
||||
'_admin_check',
|
||||
return_value=True),
|
||||
mock.patch.object(l2gateway_db.L2GatewayMixin, 'get_l2_gateway',
|
||||
return_value=fake_device),
|
||||
mock.patch.object(db, 'get_physical_port_by_name_and_ps',
|
||||
return_value=fake_physical_port),
|
||||
mock.patch.object(db, 'get_physical_switch_by_name',
|
||||
return_value=fake_physical_switch)
|
||||
) as (get_l2gw, admin_check, phy_port, phy_switch):
|
||||
self.assertRaises(l2gw_exc.L2GatewayPhysicalPortFaultStatus,
|
||||
self.plugin.create_l2_gateway_connection,
|
||||
self.db_context, fake_l2gw_conn_dict)
|
||||
|
||||
def test_create_l2_gateway_connection(self):
|
||||
self.db_context = ctx.get_admin_context()
|
||||
fake_l2gw_conn_dict = {'l2_gateway_connection': {
|
||||
|
|
Loading…
Reference in New Issue