Browse Source

Fix updating Ucast_Macs_Remote entry in removing port

In case of VM/router/DHCP ports, Ucast_Macs_Remote entory should be
removed on deleting these ports. In addition, this commit includes
some refactor.

Change-Id: Ief913c7605657e03f9d297cf5839e73d3c0fff42
tags/7.0.0^0
Yushiro FURUKAWA 1 year ago
parent
commit
25c19efb5d
9 changed files with 118 additions and 153 deletions
  1. +2
    -1
      networking_fujitsu/ml2/cfab/mech_cfab.py
  2. +2
    -16
      networking_fujitsu/ml2/common/ovsdb/ovsdb_writer.py
  3. +1
    -2
      networking_fujitsu/ml2/common/tunnel_caller.py
  4. +6
    -11
      networking_fujitsu/ml2/common/utils.py
  5. +19
    -31
      networking_fujitsu/ml2/fossw/client.py
  6. +14
    -20
      networking_fujitsu/ml2/fossw/fossw_vlandriver.py
  7. +12
    -12
      networking_fujitsu/ml2/fossw/fossw_vxlandriver.py
  8. +31
    -59
      networking_fujitsu/ml2/fossw/mech_fossw.py
  9. +31
    -1
      networking_fujitsu/tests/unit/ml2/fossw/test_mech_fossw.py

+ 2
- 1
networking_fujitsu/ml2/cfab/mech_cfab.py View File

@@ -1,4 +1,4 @@
# Copyright 2015-2017 FUJITSU LIMITED
# Copyright 2015-2018 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -127,6 +127,7 @@ class CFABMechanismDriver(api.MechanismDriver):
Case2: Otherwise
Associate the assigned MAC address to the portprofile.
"""

port = mech_context.current
network = mech_context.network
if utils.is_baremetal(port):

+ 2
- 16
networking_fujitsu/ml2/common/ovsdb/ovsdb_writer.py View File

@@ -1,4 +1,4 @@
# Copyright 2017 FUJITSU LIMITED
# Copyright 2017-2018 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -28,6 +28,7 @@ LOG = logging.getLogger(__name__)

class OVSDBWriter(base_connection.BaseConnection):
"""Performs transactions to OVSDB server tables."""

def __init__(self, ovsdb_ip, ovsdb_port):
super(OVSDBWriter, self).__init__(ovsdb_ip, ovsdb_port)

@@ -160,7 +161,6 @@ class OVSDBWriter(base_connection.BaseConnection):
:param logical_switch_name: Neutron network uuid, but delete all '-'
to make sure the length is within 32.
:type logical_switch_name: string

:returns: None
"""

@@ -182,7 +182,6 @@ class OVSDBWriter(base_connection.BaseConnection):
:param logical_switch_name: Neutron network uuid, but delete all '-'
to make sure the length is within 32.
:type logical_switch_name: string

:returns: UUID of ROW in Logical_Switch table.
:rtype: uuid
"""
@@ -212,7 +211,6 @@ class OVSDBWriter(base_connection.BaseConnection):

:param logical_switch_uuid: UUID of ROW in Logical_Switch table.
:type logical_switch_uuid: uuid

:returns: None
"""

@@ -240,7 +238,6 @@ class OVSDBWriter(base_connection.BaseConnection):
:param logical_switch_uuid: UUID of logical_switch in the binding-pair
mapping.
:type logical_switch_uuid: uuid

:returns: vlanid in the binding-pair mapping.
:rtype: integer
"""
@@ -290,7 +287,6 @@ class OVSDBWriter(base_connection.BaseConnection):
:param logical_switch_uuid: UUID of logical_switch in the binding-pair
mapping.
:type logical_switch_uuid: uuid

:returns: None
"""

@@ -315,7 +311,6 @@ class OVSDBWriter(base_connection.BaseConnection):

:param port_mac: MAC address of physical port.
:type port_mac: string

:returns: list of ROWs information of the given port_mac in
Ucast_Macs_Local table.
:rtype: list
@@ -345,7 +340,6 @@ class OVSDBWriter(base_connection.BaseConnection):

:param port_mac: MAC address of physical port.
:type port_mac: string

:returns: None
"""

@@ -365,7 +359,6 @@ class OVSDBWriter(base_connection.BaseConnection):

:param dst_ip: IP address of physical locator.
:type dst_ip: string

:returns: uuid of ROW of the given dst_ip in Physical_Locator table.
:rtype: uuid
"""
@@ -399,7 +392,6 @@ class OVSDBWriter(base_connection.BaseConnection):
:type locator_uuid: uuid
:param MAC_value: MAC address of NIC of baremetal server.
:type MAC_value: string

:returns: None
"""

@@ -429,7 +421,6 @@ class OVSDBWriter(base_connection.BaseConnection):
:type locator_ip: string
:param MAC_value: MAC address of NIC of baremetal server.
:type MAC_value: string

:returns: None
"""

@@ -457,7 +448,6 @@ class OVSDBWriter(base_connection.BaseConnection):

:param port_mac: MAC address of VM port.
:type port_mac: string

:returns: list of ROWs information of the given port_mac in
Ucast_Macs_Remote table.
:rtype: list
@@ -487,7 +477,6 @@ class OVSDBWriter(base_connection.BaseConnection):

:param port_mac: MAC address of VM port.
:type port_mac: string

:returns: None
"""

@@ -521,7 +510,6 @@ class OVSDBWriter(base_connection.BaseConnection):
:param locator_uuid: uuid of physical locator (remote VTEP) where
the port is binding to.
:type locator_uuid: uuid

:returns: None
"""

@@ -563,7 +551,6 @@ class OVSDBWriter(base_connection.BaseConnection):
:param locator_IP: IP address of physical locator (remote VTEP) where
the port is binding to.
:type locator_uuid: string

:returns: None
"""

@@ -596,7 +583,6 @@ class OVSDBWriter(base_connection.BaseConnection):
format: <slot/port>
example: 0/2
:type port_name: string

:returns: None
"""


+ 1
- 2
networking_fujitsu/ml2/common/tunnel_caller.py View File

@@ -1,4 +1,4 @@
# Copyright 2017 FUJITSU LIMITED
# Copyright 2017-2018 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -34,7 +34,6 @@ class TunnelCaller(object):
:type context: A Neutron context object.
:param tunnel_ip: An endpoint IP address of vxlan.
:type tunnel_ip: string

:returns: None
"""


+ 6
- 11
networking_fujitsu/ml2/common/utils.py View File

@@ -1,4 +1,4 @@
# Copyright 2015-2017 FUJITSU LIMITED
# Copyright 2015-2018 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@ def eliminate_val(source, reject):
:type source: string
:param reject: a list of integer to reject. ex. [1, 2]
:type reject: list of integer

:returns: a string separated with "," like an example
:rtype: string
"""
@@ -120,10 +119,10 @@ def get_network_type(network):

:param network: NetworkContext or network dict
:type network: NetworkContext or dict

:returns network_type: 'vlan', 'vxlan', 'local', 'flat' and 'geneve'
:rtype: string
"""

return _get_provider_attribute(network, 'NETWORK_TYPE')


@@ -132,10 +131,10 @@ def get_segmentation_id(network):

:param network: NetworkContext or network dict
:type network: NetworkContext or dict

:returns segmentation_id: VLANID('vlan') or VNI('vxlan')
:rtype: integer
"""

return _get_provider_attribute(network, 'SEGMENTATION_ID')


@@ -144,10 +143,10 @@ def get_physical_network(network):

:param network: NetworkContext or network dict
:type network: NetworkContext or dict

:returns physical_network: physical network name for the network
:rtype: string
"""

return _get_provider_attribute(network, 'PHYSICAL_NETWORK')


@@ -156,7 +155,6 @@ def get_physical_connectivity(port):

:param port: a dictionary of neutron port
:type port: dictionary

:returns lli: "local_link_information" as follows
[{"switch_id": "MAC_of_switch", "port_id": "1/1/0/1",
"switch_info": "switch_name"}]
@@ -180,7 +178,6 @@ def has_lli(port):

:param port: a port dictionary
:type port: dictionary

:returns True(a port has 'local_link_information') or False(otherwise)
:rtype: boolean
"""
@@ -193,7 +190,6 @@ def is_baremetal(port):

:param port: a dictionary of neutron port
:type port: dictionary

:returns: True(vnic_type is baremetal) or False(otherwise)
:rtype: boolean
"""
@@ -207,7 +203,6 @@ def is_lag(local_link_information):

:param local_link_information: physical connectivity information
:type local_link_information: list of dict

:returns: True(mode is LAG) or False(otherwise)
:rtype: boolean
"""
@@ -216,13 +211,13 @@ def is_lag(local_link_information):


def is_unbound(context):
"""Judge current port object is unbound or not.
"""Judge current port object is changed into 'unbound' status or not.

:param context: port context
:type context: PortContext object

:returns: True(port is unbound) or False(otherwise)
:rtype: boolean
"""

return (context.current[pb_def.VIF_TYPE] == pb_def.VIF_TYPE_UNBOUND and
context.original[pb_def.VIF_TYPE] == pb_def.VIF_TYPE_OTHER)

+ 19
- 31
networking_fujitsu/ml2/fossw/client.py View File

@@ -1,4 +1,4 @@
# Copyright 2017 FUJITSU LIMITED
# Copyright 2017-2018 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -50,13 +50,13 @@ class FOSSWClient(object):
If exists session for specified target, reuse it otherwise reconnect.
In order to get command result correctly, execute 'terminal length 0'
at the beginning of the session.

:param ip: a ip address of FOS switch
:type ip: string
:returns: None
:rtype: None

"""
if not self.lookup(ip):
if not self._lookup(ip):
self._reconnect(ip)
self._exec_command(TERMINAL_LENGTH_0)

@@ -67,8 +67,8 @@ class FOSSWClient(object):
:type ip: string
:returns: None
:rtypes: None

"""

self.disconnect()
method = "connect"
retry_count = 0
@@ -112,8 +112,8 @@ class FOSSWClient(object):

:returns: None
:rtypes: None

"""

if self.ssh:
self.ssh.close()
self.ssh = None
@@ -159,15 +159,13 @@ class FOSSWClient(object):
raise FOSSWClientException(method)
return formatted

def lookup(self, target):
def _lookup(self, target):
"""Check exist session for specified IP.

:param target: IP address of a target host
:type target: string

:returns: exist(True) or not exist(False)
:rtype: bool

"""
if self.ssh:
if self.ssh._host_keys:
@@ -181,10 +179,8 @@ class FOSSWClient(object):

:param segmentation_id: id of VLAN to be created.
:type segmentation_id: string

:returns: received message from FOS switch
:rtype: string

"""
self.change_mode(MODE_VLAN)
cmd = self._format_command("vlan {vlanid}", vlanid=segmentation_id)
@@ -195,11 +191,10 @@ class FOSSWClient(object):

:param segmentation_id: id of VLAN to be deleted.
:type segmentation_id: string

:returns: None
:rtype: None

"""

self.change_mode(MODE_VLAN)
cmd = self._format_command("no vlan {vlanid}", vlanid=segmentation_id)
if "Failed to delete" in self._exec_command(cmd):
@@ -212,11 +207,10 @@ class FOSSWClient(object):
:type segmentation_id: string
:param port_id: the number of physical port on FOS switch
:type port_id: string

:returns: None
:rtype: None

"""

method = "set_vlan"
self.change_mode(MODE_INTERFACE, port_id)
self._exec_command("switchport mode access")
@@ -232,11 +226,10 @@ class FOSSWClient(object):

:param port_id: the number of physical port on FOS switch
:type port_id: string

:returns: None
:rtype: None

"""

self.change_mode(MODE_INTERFACE, port_id)
self._exec_command("no switchport access vlan")
self._exec_command("no switchport mode")
@@ -248,11 +241,10 @@ class FOSSWClient(object):
:type port: string
:param logicalport: the number of logical port on FOS switch
:type logicalport: string

:returns: None
:rtype: None

"""

self.change_mode(MODE_INTERFACE, ifname=logicalport)
self._exec_command("no port-channel static")

@@ -268,10 +260,10 @@ class FOSSWClient(object):
:param logicalport: the number of logicalport
(optional, default: "none")
:type logicalport: string

:returns: the ID of VPC or None.
:rtype: string
"""

# TODO(yushiro): Replace regexp
for i in iter(range(1, MAX_VPC_ID + 1)):
cmd = 'show vpc {vid} | include "Port channel"'.format(vid=str(i))
@@ -297,11 +289,10 @@ class FOSSWClient(object):
:type logicalport: string
:param vpcid: id of VPC
:type vpcid: string

:returns: None
:rtype: None

"""

self.change_mode(MODE_INTERFACE, ifname=logicalport)
self._exec_command("vpc {vpcid}".format(vpcid=vpcid))

@@ -310,8 +301,8 @@ class FOSSWClient(object):

:returns: IP address of peerlink partner
:rtype: string

"""

# TODO(yushiro): Replace regexp
ret = self._exec_command('show vpc peer-keepalive | include "Peer '
'IP address"')
@@ -331,8 +322,8 @@ class FOSSWClient(object):
:returns: the number of logical port which associated with specified
physical port
:rtype: string

"""

# Find related lag_port with specified portname
if portname:
cmd = "show running-config interface %s" % portname
@@ -349,8 +340,8 @@ class FOSSWClient(object):

:returns: MAC address of FOS switch
:rtype: string

"""

cmd = 'show hardware eeprom | include "Base MAC Address"'
res = self._exec_command(cmd)
if res:
@@ -364,11 +355,10 @@ class FOSSWClient(object):
:type port: string
:param logicalport: the number of logical port on FOS switch
:type logicalport: string

:returns: None
:rtype: None

"""

self.change_mode(MODE_INTERFACE, ifname=port)
res = self._exec_command(
"deleteport {lo_port}".format(lo_port=logicalport))
@@ -386,11 +376,10 @@ class FOSSWClient(object):
:type logicalport: string
:param vpcid: id of VPC
:type vpcid: string

:returns: None
:rtype: None

"""

self.change_mode(MODE_INTERFACE, ifname=logicalport)
res = self._exec_command("no vpc {vpcid}".format(vpcid=vpcid))
if "Failed to remove" in res:
@@ -403,8 +392,8 @@ class FOSSWClient(object):

:returns: None
:rtypes: None

"""

self._exec_command("copy system:running-config nvram:startup-config")
self._exec_command("y")
self._exec_command("")
@@ -417,11 +406,10 @@ class FOSSWClient(object):
:param ifname: the number of physical port on FOS switch
(optional, default: None)
:type ifname: string

:returns: None
:rtype: None

"""

# Move to Privileged EXEC mode.
prompt = self._exec_command(END)
if ") >" in prompt:

+ 14
- 20
networking_fujitsu/ml2/fossw/fossw_vlandriver.py View File

@@ -1,4 +1,4 @@
# Copyright 2017 FUJITSU LIMITED
# Copyright 2017-2018 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -46,14 +46,13 @@ class FOSSWVlanDriver(object):
def get_switch_mac_ip_pair(self, ips):
"""Get and create pair of switch's MAC address and IP address.

:param ips: list of IP address of FOS switch
:type ips: list of IP address strings

:returns: the dictionary which stores pair of MAC address and IP
address
:rtype: dictionary of MAC address and IP address

:param ips: List of IP address of FOS switch
:type ips: List of IP address strings
:returns: A dictionary which stores pair of MAC address and IP
address like {'fe:54:00:23:33:9a': '192.168.50.1'}
:rtype: A dictionary of MAC address and IP address
"""

switches_mac_ip_pair = {}
for ip in ips:
self.client.connect(ip)
@@ -73,11 +72,10 @@ class FOSSWVlanDriver(object):
:type ip: string
:param vlanid: ID of VLAN to be created
:type vlanid: string

:returns: None
:rtype: None

"""

method = 'create_vlan'
try:
self.client.connect(ip)
@@ -96,11 +94,10 @@ class FOSSWVlanDriver(object):
:type ip: string
:param vlanid: ID of VLAN to be deleted
:type vlanid: string

:returns: None
:rtype: None

"""

method = 'delete_vlan'
try:
self.client.connect(ip)
@@ -122,11 +119,10 @@ class FOSSWVlanDriver(object):
:param ip_mac_pairs: the pair of MAC address and IP address of FOS
switch
:type ip_mac_pairs: dictionary

:returns: None
:rtype: None

"""

method = "setup_vlan"
sw_mac = lli[0]['switch_id']
port_id = lli[0]['port_id']
@@ -158,11 +154,10 @@ class FOSSWVlanDriver(object):
:param vlanid: the VLANID to configure. If it is not set, it will skip
VLAN configuration.
:type vlanid: Integer

:returns: mac_lag_map MAC address and LAG port ID pair
:rtype: dictionary

"""

method = "setup_lag"
mlag = False
unique_mac_list = sorted(list(set([lli['switch_id'] for lli in llis])))
@@ -238,11 +233,10 @@ class FOSSWVlanDriver(object):
:param ip_mac_pairs: the pair of MAC address and IP address of FOS
switches
:type ip_mac_pairs: dictionary

:returns: Result of validation
:rtype: Boolean

"""

try:
ips = self._validate_lli_macs_with_config(macs, ip_mac_pairs)
self.client.connect(ips[0])
@@ -264,6 +258,7 @@ class FOSSWVlanDriver(object):
switches
:type ip_mac_pairs: dictionary
"""

method = "clear_vlan"
sw_mac = lli[0]['switch_id']
port_id = lli[0]['port_id']
@@ -292,11 +287,10 @@ class FOSSWVlanDriver(object):
:param ip_mac_pairs: the pair of MAC address and IP address of FOS
switches
:type ip_mac_pairs: dictionary

:returns: None
:rtype: None

"""

method = "clear_lag"
mlag = None
unique_mac_list = sorted(list(set([lli['switch_id'] for lli in llis])))

+ 12
- 12
networking_fujitsu/ml2/fossw/fossw_vxlandriver.py View File

@@ -1,4 +1,4 @@
# Copyright 2017 FUJITSU LIMITED
# Copyright 2017-2018 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -66,6 +66,7 @@ class FOSSWVxlanDriver(object):

def save_all_fossw(self):
"""Save running-config to startup-config in all FOS switches."""

for fossw_ip in self.fossw_ips:
self.client.connect(fossw_ip)
self.client.save_running_config()
@@ -75,6 +76,7 @@ class FOSSWVxlanDriver(object):
"""Update Neutron DB ml2_vxlan_endpoints table

Update with VTEPs of all FOS switches.

:returns: None
"""

@@ -125,11 +127,11 @@ class FOSSWVxlanDriver(object):

We consider net_uuid is always unique, and both vni and net_uuid
must be immutable. So there is not a update case.

:param net_uuid: The uuid of Neutron network.
:type net_uuid: string
:param vni: The segment ID of Neutron network.
:type vni: integer

:returns: None
"""

@@ -145,9 +147,9 @@ class FOSSWVxlanDriver(object):

We only consider deleting the existing Logical_Switch ROW.
Also note that even it does not exit, the jsonrpc returns no error.

:param net_uuid: The uuid of Neutron network.
:type: string

:returns: None
"""

@@ -182,14 +184,13 @@ class FOSSWVxlanDriver(object):
to.
:type vni: integer
:param lli: The local_link_information of the port.
If it is a VM port, then [{}] should be given.
If it is a VM port, then [] should be given.
:type lli: list
:param port: Dictionary of a port
:type port: dictionary
:param ip_mac_pairs: List of MAC(key) - IP(value) pairs of all FOS
switches.
:type ip_mac_pairs: dictionary

:returns: None
"""

@@ -247,6 +248,7 @@ class FOSSWVxlanDriver(object):
def _update_ucast_macs_remote(self, logical_switch_name, mac, tunnel_ip,
port_ips, ignore=None):
"""Update Ucast_Macs_Remote table in all FOS switches OVSDB."""

for fossw_ip in self.fossw_ips:
if ignore == fossw_ip:
continue
@@ -263,7 +265,7 @@ class FOSSWVxlanDriver(object):
ls_uuid, mac, port_ips, tunnel_ip)

def reset_physical_port(self, lli, port, ip_mac_pairs, save=True):
"""Remove setting of raw of Physical_Port table in FOS switch OVSDB.
"""Remove setting of row of Physical_Port table in FOS switch OVSDB.

ROWs with the same MAC address in Ucast_Macs_Local table and
Ucast_Macs_Remote table are the target to extinct.
@@ -275,16 +277,16 @@ class FOSSWVxlanDriver(object):
:param ip_mac_pairs: List of MAC(key) - IP(value) pairs of all FOS
switches.
:type ip_mac_pairs: dictionary

:returns: None
"""

if lli:
target = ip_mac_pairs[lli[0]['switch_id']]
port_id = lli[0]['port_id']
# If this method is callef from reset_physical_port_with_lag,
# sw_port_id should be logical port(for LAG)
sw_port_id = lli[0]['port_id']
ovsdb_cli = ovsdb_writer.OVSDBWriter(target, self.ovsdb_port)
# TODO(yushiro): Need to send lag port in case of LAG
ovsdb_cli.reset_physical_port(port_id)
ovsdb_cli.reset_physical_port(sw_port_id)

mac = port["mac_address"]

@@ -316,7 +318,6 @@ class FOSSWVxlanDriver(object):
:param req_id: A request ID of network context which use for generate
new context.
:type req_id: string

:returns: None
"""

@@ -338,7 +339,6 @@ class FOSSWVxlanDriver(object):
:param ip_mac_pairs: List of MAC(key) - IP(value) pairs of all FOS
switches.
:type ip_mac_pairs: dictionary

:returns: None
"""


+ 31
- 59
networking_fujitsu/ml2/fossw/mech_fossw.py View File

@@ -1,4 +1,4 @@
# Copyright 2017 FUJITSU LIMITED
# Copyright 2017-2018 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -115,10 +115,8 @@ class FOSSWMechanismDriver(api.MechanismDriver):

:param mech_context: context of network
:type mech_context: NetworkContext

:returns: None
:rtype: None

"""

network = net_context.current
@@ -143,11 +141,10 @@ class FOSSWMechanismDriver(api.MechanismDriver):

:param vlanid: the ID of VLAN to be created
:type vlanid: string

:returns: None
:rtype: None

"""

method = 'create_network_postcommit'
for ip in self.ips:
try:
@@ -159,6 +156,7 @@ class FOSSWMechanismDriver(api.MechanismDriver):

@log_helpers.log_method_call
def create_network_postcommit_vxlan(self, net_uuid, seg_id):

method = 'create_network_postcommit'
try:
self._vxlan_driver.create_logical_switch(net_uuid, seg_id)
@@ -181,7 +179,6 @@ class FOSSWMechanismDriver(api.MechanismDriver):

:param net_context: context of network
:type net_context: NetworkContext

:returns: None
:rtype: None
"""
@@ -206,11 +203,10 @@ class FOSSWMechanismDriver(api.MechanismDriver):

:param vlanid: the ID of VLAN to be deleted
:type vlanid: string

:returns: None
:rtypes: None

"""

method = 'delete_network_postcommit'
for ip in self.ips:
try:
@@ -234,16 +230,17 @@ class FOSSWMechanismDriver(api.MechanismDriver):
def delete_port_postcommit(self, mech_context):
"""Calls cleanup process for FOS switch.

Case1: Baremetal deploy with VLAN
Clear VLAN/LAG for specified physical port.
Case2:
Clear VXLAN/LAG for specified physical port.
Case3: Otherwise
Do nothing.
Case1: 'network_type' is 'vlan' and the port is for baremetal
Call clear VLAN/LAG for specified physical port.
Case2: 'network_type' is 'vxlan' and the port is for baremetal
Call clear VXLAN/LAG for specified physical port.
Case3: 'network_type' is 'vxlan' and the port is for VM/DHCP/router
Call clear VXLAN/LAG for specified physical port.
Case4: Otherwise
Ignore

:param mech_context: context of port
:type mech_context: PortContext

:returns: None
:rtype: None
"""
@@ -266,6 +263,7 @@ class FOSSWMechanismDriver(api.MechanismDriver):
@log_helpers.log_method_call
def update_port_postcommit(self, context):
"""Update specified physical port on switch."""

method = 'update_port_postcommit'
port = context.current
network = context.network
@@ -291,7 +289,7 @@ class FOSSWMechanismDriver(api.MechanismDriver):
if (network_type != nl_const.TYPE_VXLAN or
vif_type == pb_def.VIF_TYPE_UNBOUND):
return
# currently supports only one segment per network
# Currently this driver supports only one segment per network.
# Setup VXLAN for port which bound with DHCP, router, and vms.
try:
self._vxlan_driver.update_physical_port(
@@ -313,7 +311,6 @@ class FOSSWMechanismDriver(api.MechanismDriver):
:param params: a dictionary of the return value for
get_physical_net_params
:type params: dictionary

:returns: None
:rtype: None
"""
@@ -363,8 +360,6 @@ class FOSSWMechanismDriver(api.MechanismDriver):
try:
call_target = target if params['lag'] else 'clear_vlan'
clear_method = getattr(self._vlan_driver, call_target)
LOG.info("call %(target)s. params: %(params)s",
{'target': call_target, 'params': params})
clear_method(params['local_link_info'], self.switches_mac_ip_pair)
except Exception:
LOG.exception("Failed to clear vlan(%s)", params['vlanid'])
@@ -378,18 +373,20 @@ class FOSSWMechanismDriver(api.MechanismDriver):
network = context.network
if port[pb_def.VIF_TYPE] == pb_def.VIF_TYPE_UNBOUND:
return
if not utils.has_lli(port):
LOG.warning('local_link_information not found in port %s', port)
return
# Returns empty list if port doesn't include 'local_link_information'
lli = utils.get_physical_connectivity(port)
try:
if utils.is_lag(lli):
mac_lag_map = self._vlan_driver.clear_lag(
ret = self._vlan_driver.clear_lag(
lli, self.switches_mac_ip_pair)
self._vxlan_driver.reset_physical_port_with_lag(
lli, port, self.switches_mac_ip_pair,
mac_lag_map=mac_lag_map)
lli, port, self.switches_mac_ip_pair, mac_lag_map=ret)
else:
# In case of baremetal port
# - 'lli' exists and 'vnic_type' is 'baremetal'
# In case of router/DHCP/VM port
# - 'lli' is [](empty list)
# - This method only removes Ucast_macs_Remote entry
self._vxlan_driver.reset_physical_port(
lli, port, self.switches_mac_ip_pair)
except Exception:
@@ -415,10 +412,10 @@ class FOSSWMechanismDriver(api.MechanismDriver):
:type port: dictionary
:param network: a network object
:type network: NetworkContext

:returns: A dictionary parameters for baremetal deploy
:rtype: dictionary
"""

port = context.original if use_original else context.current
network = context.network
vlanid = utils.get_segmentation_id(network)
@@ -437,31 +434,22 @@ class FOSSWMechanismDriver(api.MechanismDriver):
network = context.network
if not is_supported(network):
return
LOG.debug("Attempting to bind port %(port)s with vnic_type "
"%(vnic_type)s on network %(network)s",
{'port': port['id'], 'vnic_type': port[pb_def.VNIC_TYPE],
'network': port['network_id']})

network_type = utils.get_network_type(network)
to_bind = False

if network_type == nl_const.TYPE_VXLAN:
# vxlan driver handles not only baremetal port, but vm, dhcp,
# router ports.
# VXLAN driver handles not only baremetal port, but VM/DHCP/router
self.setup_vxlan(context)
to_bind = True
if utils.is_baremetal(port) and network_type == nl_const.TYPE_VLAN:
if network_type == nl_const.TYPE_VLAN and utils.is_baremetal(port):
self.setup_vlan(self.get_physical_net_params(context))
to_bind = True
if to_bind:
context.set_binding(context.segments_to_bind[0][api.ID],
pb_def.VIF_TYPE_OTHER, {},
status=nl_const.PORT_STATUS_ACTIVE)

context.set_binding(context.segments_to_bind[0][api.ID],
pb_def.VIF_TYPE_OTHER, {},
status=nl_const.PORT_STATUS_ACTIVE)

@log_helpers.log_method_call
def setup_vxlan(self, context):
"""Update VXLAN from specified physical port on switch."""
# currently supports only one segment per network
port = context.current
seg_id = utils.get_segmentation_id(context.network)
lli = utils.get_physical_connectivity(port)
@@ -486,8 +474,7 @@ def is_supported(network):

:param network: a network object
:type network: NetworkContext

:returns: True if network_type is supported and segmentation_id is included
:returns: True if network_type is supported and segmentation_id exists
otherwise False
:rtype: boolean
"""
@@ -497,18 +484,3 @@ def is_supported(network):
LOG.warning("Network type(%s) is not supported. Skip it.", net_type)
return False
return True if utils.get_segmentation_id(network) else False


def validate_baremetal_deploy(port_context, use_original=False):
"""Validate baremetal deploy.

:param port_context: a PortContext object
:type port_context: PortContext

:returns: True if enable to baremetal deploy otherwise False
:rtype: boolean
"""

port = port_context.original if use_original else port_context.current
network = port_context.network
return utils.is_baremetal(port) and is_supported(network)

+ 31
- 1
networking_fujitsu/tests/unit/ml2/fossw/test_mech_fossw.py View File

@@ -1,4 +1,4 @@
# Copyright 2017 FUJITSU LIMITED
# Copyright 2017-2018 FUJITSU LIMITED
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -507,6 +507,26 @@ class TestFOSSWBaremetalPortsVxlan(TestFujitsuMechDriverV2):
ml2_exc.MechanismDriverError,
self.mech.update_port_postcommit, ctx)

def test_update_port_raises_setup_vlan(self):
ctx = self.prepare_dummy_context(net_type='vxlan',
vif_type='unbound',
set_original=True)
# Raise in setup_vlan method
self.mech._vxlan_driver.reset_physical_port.side_effect = Exception
self.assertRaises(
ml2_exc.MechanismDriverError,
self.mech.update_port_postcommit, ctx)

def test_update_port_raises_setup_vxlan(self):
ctx = self.prepare_dummy_context(net_type='vxlan',
vif_type='unbound',
set_original=True)
# Raise in setup_vxlan method
self.mech._vxlan_driver.reset_physical_port.side_effect = Exception
self.assertRaises(
ml2_exc.MechanismDriverError,
self.mech.update_port_postcommit, ctx)

def test_delete_port(self):
ctx = self.prepare_dummy_context(net_type='vxlan')
self.mech.delete_port_postcommit(ctx)
@@ -528,6 +548,16 @@ class TestFOSSWBaremetalPortsVxlan(TestFujitsuMechDriverV2):
self.mech.switches_mac_ip_pair
)

def test_delete_port_with_bound_not_baremetal(self):
ctx = self.prepare_dummy_context(net_type='vxlan', vif_type='ovs')
ctx.current['binding:profile'] = {}
self.mech.delete_port_postcommit(ctx)
self.mech._vxlan_driver.reset_physical_port.assert_called_once_with(
[],
ctx.current,
self.mech.switches_mac_ip_pair
)

def test_delete_port_raises_reset_physical_port(self):
ctx = self.prepare_dummy_context(net_type='vxlan', vif_type='normal')
self.mech._vxlan_driver.reset_physical_port.side_effect = Exception

Loading…
Cancel
Save