update vxlan (#57264)

* update vxlan

* add a changelog fragment for the PR 57264

* Update 57264-update-vxlan-to-fix-bugs.yml

update for change request

* Update ce_vxlan_vap.py

remove commented codes.
This commit is contained in:
xuxiaowei0512 2019-06-13 01:00:55 +08:00 committed by Nathaniel Case
parent e009936f87
commit 5bddd55703
8 changed files with 142 additions and 92 deletions

View file

@ -0,0 +1,8 @@
bugfixes:
- ce_dldp - tag named data of a xpath is unnecessay for old sotfware version to find a element from xml tree, but element can not be found with 'data' tag for new version, so remove.
- ce_dldp_interface - tag named data of a xpath is unnecessay for old sotfware version to find a element from xml tree, but element can not be found with 'data' tag for new version, so remove.
- ce_vxlan_arp - override 'get_config' to show specific configuration.
- ce_vxlan_gateway - override 'get_config' to show specific configuration.
- ce_vxlan_global - Netwrok_cli and netconf should be not mixed together, otherwise something bad will happen. Function get_nc_config uses netconf and load_config uses network_cli.
- ce_vxlan_tunnel - Netwrok_cli and netconf should be not mixed together, otherwise something bad will happen. Function get_nc_config uses netconf and load_config uses network_cli.
- ce_vxlan_vap - tag named data of a xpath is unnecessay for old sotfware version to find a element from xml tree, but element can not be found with 'data' tag for new version, so remove.

View file

@ -321,7 +321,7 @@ class Dldp(object):
# get global DLDP info
root = ElementTree.fromstring(xml_str)
topo = root.find("data/dldp/dldpSys")
topo = root.find("dldp/dldpSys")
if not topo:
self.module.fail_json(
msg="Error: Get current DLDP configration failed.")

View file

@ -454,7 +454,7 @@ class DldpInterface(object):
# get global DLDP info
root = ElementTree.fromstring(xml_str)
topo = root.find("data/dldp/dldpInterfaces/dldpInterface")
topo = root.find("dldp/dldpInterfaces/dldpInterface")
if topo is None:
self.module.fail_json(
msg="Error: Get current DLDP configration failed.")

View file

@ -150,8 +150,9 @@ changed:
import re
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.cloudengine.ce import get_config, load_config
from ansible.module_utils.network.cloudengine.ce import load_config
from ansible.module_utils.network.cloudengine.ce import ce_argument_spec
from ansible.module_utils.connection import exec_command
def is_config_exist(cmp_cfg, test_cfg):
@ -265,6 +266,22 @@ class VxlanArp(object):
if not self.module.check_mode:
load_config(self.module, commands)
def get_config(self, flags=None):
"""Retrieves the current config from the device or cache
"""
flags = [] if flags is None else flags
cmd = 'display current-configuration '
cmd += ' '.join(flags)
cmd = cmd.strip()
rc, out, err = exec_command(self.module, cmd)
if rc != 0:
self.module.fail_json(msg=err)
cfg = str(out).strip()
return cfg
def get_current_config(self):
"""get current configuration"""
@ -277,9 +294,14 @@ class VxlanArp(object):
exp += "|^bridge-domain %s$" % self.bridge_domain_id
flags.append(exp)
config = get_config(self.module, flags)
cfg_str = self.get_config(flags)
config = cfg_str.split("\n")
return config
exist_config = ""
for cfg in config:
if not cfg.startswith("display"):
exist_config += cfg
return exist_config
def cli_add_command(self, command, undo=False):
"""add command to self.update_cmd and self.commands"""

View file

@ -176,8 +176,9 @@ changed:
import re
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.cloudengine.ce import get_config, load_config
from ansible.module_utils.network.cloudengine.ce import load_config
from ansible.module_utils.network.cloudengine.ce import ce_argument_spec
from ansible.module_utils.connection import exec_command
def is_config_exist(cmp_cfg, test_cfg):
@ -377,6 +378,22 @@ class VxlanGateway(object):
if not self.module.check_mode:
load_config(self.module, commands)
def get_config(self, flags=None):
"""Retrieves the current config from the device or cache
"""
flags = [] if flags is None else flags
cmd = 'display current-configuration '
cmd += ' '.join(flags)
cmd = cmd.strip()
rc, out, err = exec_command(self.module, cmd)
if rc != 0:
self.module.fail_json(msg=err)
cfg = str(out).strip()
return cfg
def get_current_config(self):
"""get current configuration"""
@ -387,7 +404,7 @@ class VxlanGateway(object):
if self.vbdif_name:
exp += "|^interface %s$" % self.vbdif_name
flags.append(exp)
return get_config(self.module, flags)
return self.get_config(flags)
def cli_add_command(self, command, undo=False):
"""add command to self.update_cmd and self.commands"""
@ -579,6 +596,7 @@ class VxlanGateway(object):
if self.vbdif_bind_vpn:
cmd = "ip binding vpn-instance %s" % self.vbdif_bind_vpn
exist = is_config_exist(self.config, cmd)
if self.state == "present" and not exist:
if not vbdif_view:
self.cli_add_command(vbdif_cmd)

View file

@ -123,23 +123,10 @@ changed:
'''
import re
from xml.etree import ElementTree
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.cloudengine.ce import get_config, load_config, get_nc_config
from ansible.module_utils.network.cloudengine.ce import load_config
from ansible.module_utils.network.cloudengine.ce import ce_argument_spec
CE_NC_GET_BRIDGE_DOMAIN = """
<filter type="subtree">
<evc xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
<bds>
<bd>
<bdId></bdId>
</bd>
</bds>
</evc>
</filter>
"""
from ansible.module_utils.connection import exec_command
def is_config_exist(cmp_cfg, test_cfg):
@ -206,13 +193,29 @@ class VxlanGlobal(object):
if not self.module.check_mode:
load_config(self.module, commands)
def get_config(self, flags=None):
"""Retrieves the current config from the device or cache
"""
flags = [] if flags is None else flags
cmd = 'display current-configuration '
cmd += ' '.join(flags)
cmd = cmd.strip()
rc, out, err = exec_command(self.module, cmd)
if rc != 0:
self.module.fail_json(msg=err)
cfg = str(out).strip()
return cfg
def get_current_config(self):
"""get current configuration"""
flags = list()
exp = " include-default | include vxlan|assign | exclude undo"
flags.append(exp)
return get_config(self.module, flags)
return self.get_config(flags)
def cli_add_command(self, command, undo=False):
"""add command to self.update_cmd and self.commands"""
@ -228,27 +231,15 @@ class VxlanGlobal(object):
def get_bd_list(self):
"""get bridge domain list"""
flags = list()
bd_info = list()
conf_str = CE_NC_GET_BRIDGE_DOMAIN
xml_str = get_nc_config(self.module, conf_str)
if "<data/>" in xml_str:
exp = " include-default | include bridge-domain | exclude undo"
flags.append(exp)
bd_str = self.get_config(flags)
if not bd_str:
return bd_info
xml_str = xml_str.replace('\r', '').replace('\n', '').\
replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
# get bridge domain info
root = ElementTree.fromstring(xml_str)
bds = root.findall("data/evc/bds/bd/bdId")
if not bds:
return bd_info
for bridge_domain in bds:
if bridge_domain.tag == "bdId":
bd_info.append(bridge_domain.text)
bd_num = re.findall(r'bridge-domain\s*([0-9]+)', bd_str)
bd_info.append(bd_num)
return bd_info
def config_bridge_domain(self):

View file

@ -115,10 +115,10 @@ end_state:
type: dict
sample: {nve_interface_name": "Nve1", nve_mode": "mode-l3", "source_ip": "0.0.0.0"}
'''
import re
from xml.etree import ElementTree
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, get_config, ce_argument_spec
from ansible.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
CE_NC_GET_VNI_BD_INFO = """
<filter type="subtree">
@ -366,18 +366,6 @@ class VxlanTunnel(object):
if "<ok/>" not in xml_str:
self.module.fail_json(msg='Error: %s failed.' % xml_name)
def get_current_config(self, vni_id, peer_ip_list):
"""get current configuration"""
flags = list()
exp = " | include vni "
exp += vni_id
exp += " head-end peer-list "
for peer_ip in peer_ip_list:
exp += "| exclude %s " % peer_ip
flags.append(exp)
return get_config(self.module, flags)
def get_vni2bd_dict(self):
""" get vni2bd attributes dict."""
@ -393,7 +381,7 @@ class VxlanTunnel(object):
# get vni to bridge domain id info
root = ElementTree.fromstring(xml_str)
vni2bd_info["vni2BdInfos"] = list()
vni2bds = root.findall("data/nvo3/nvo3Vni2Bds/nvo3Vni2Bd")
vni2bds = root.findall("nvo3/nvo3Vni2Bds/nvo3Vni2Bd")
if vni2bds:
for vni2bd in vni2bds:
@ -430,7 +418,8 @@ class VxlanTunnel(object):
# get nve info
root = ElementTree.fromstring(xml_str)
nvo3 = root.find("data/nvo3/nvo3Nves/nvo3Nve")
nvo3 = root.find("nvo3/nvo3Nves/nvo3Nve")
if nvo3:
for nve in nvo3:
if nve.tag in ["srcAddr", "ifName", "nveType"]:
@ -440,7 +429,7 @@ class VxlanTunnel(object):
nve_info["vni_peer_protocols"] = list()
vni_members = root.findall(
"data/nvo3/nvo3Nves/nvo3Nve/vniMembers/vniMember")
"nvo3/nvo3Nves/nvo3Nve/vniMembers/vniMember")
if vni_members:
for member in vni_members:
vni_dict = dict()
@ -451,15 +440,22 @@ class VxlanTunnel(object):
# get vni peer address ip info
nve_info["vni_peer_ips"] = list()
vni_peers = root.findall(
"data/nvo3/nvo3Nves/nvo3Nve/vniMembers/vniMember/nvo3VniPeers/nvo3VniPeer")
if vni_peers:
for peer_address in vni_peers:
vni_peer_dict = dict()
for ele in peer_address:
if ele.tag in ["vniId", "peerAddr"]:
vni_peer_dict[ele.tag] = ele.text
nve_info["vni_peer_ips"].append(vni_peer_dict)
re_find = re.findall(r'<vniId>(.*?)</vniId>\s*'
r'<protocol>(.*?)</protocol>\s*'
r'<nvo3VniPeers>(.*?)</nvo3VniPeers>', xml_str)
if re_find:
for vni_peers in re_find:
vni_info = dict()
vni_peer = re.findall(r'<peerAddr>(.*?)</peerAddr>', vni_peers[2])
if vni_peer:
vni_info["vniId"] = vni_peers[0]
vni_peer_list = list()
for peer in vni_peer:
vni_peer_list.append(peer)
vni_info["peerAddr"] = vni_peer_list
nve_info["vni_peer_ips"].append(vni_info)
return nve_info
@ -563,7 +559,7 @@ class VxlanTunnel(object):
return False
if self.nve_info["ifName"] == nve_name:
for member in self.nve_info["vni_peer_ips"]:
if member["vniId"] == vni_id and member["peerAddr"] == peer_ip:
if member["vniId"] == vni_id and peer_ip in member["peerAddr"]:
return True
return False
@ -572,16 +568,25 @@ class VxlanTunnel(object):
if not self.nve_info:
return True
for peer_ip in peer_ip_list:
if self.nve_info["ifName"] == nve_name:
if not self.nve_info["vni_peer_ips"]:
if self.nve_info["ifName"] == nve_name:
if not self.nve_info["vni_peer_ips"]:
return True
nve_peer_info = list()
for nve_peer in self.nve_info["vni_peer_ips"]:
if nve_peer["vniId"] == vni_id:
nve_peer_info.append(nve_peer)
if not nve_peer_info:
return True
nve_peer_list = nve_peer_info[0]["peerAddr"]
for peer in peer_ip_list:
if peer not in nve_peer_list:
return True
for member in self.nve_info["vni_peer_ips"]:
if member["vniId"] != vni_id:
return True
elif member["vniId"] == vni_id and member["peerAddr"] != peer_ip:
return True
return False
return False
def config_merge_vni2bd(self, bd_id, vni_id):
"""config vni to bd id"""
@ -602,7 +607,10 @@ class VxlanTunnel(object):
recv_xml = set_nc_config(self.module, cfg_xml)
self.check_response(recv_xml, "MERGE_MODE")
self.updates_cmd.append("interface %s" % nve_name)
self.updates_cmd.append("mode l3")
if mode == "mode-l3":
self.updates_cmd.append("mode l3")
else:
self.updates_cmd.append("undo mode l3")
self.changed = True
def config_merge_source_ip(self, nve_name, source_ip):
@ -705,7 +713,17 @@ class VxlanTunnel(object):
for peer_ip in peer_ip_list:
if not self.is_vni_peer_list_exist(nve_name, vni_id, peer_ip):
self.module.fail_json(msg='Error: The %s does not exist' % peer_ip)
config = self.get_current_config(vni_id, peer_ip_list)
config = False
nve_peer_info = list()
for nve_peer in self.nve_info["vni_peer_ips"]:
if nve_peer["vniId"] == vni_id:
nve_peer_info = nve_peer.get("peerAddr")
for peer in nve_peer_info:
if peer not in peer_ip_list:
config = True
if not config:
cfg_xml = CE_NC_DELETE_VNI_PEER_ADDRESS_IP_HEAD % (
nve_name, vni_id)

View file

@ -451,9 +451,6 @@ class VxlanVap(object):
conf_str = CE_NC_GET_BD_VAP % self.bridge_domain_id
xml_str = get_nc_config(self.module, conf_str)
if "<data/>" in xml_str:
return vap_info
xml_str = xml_str.replace('\r', '').replace('\n', '').\
replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
@ -462,8 +459,7 @@ class VxlanVap(object):
vap_info["bdId"] = self.bridge_domain_id
root = ElementTree.fromstring(xml_str)
vap_info["vlanList"] = ""
vap_vlan = root.find("data/evc/bds/bd/bdBindVlan")
vap_info["vlanList"] = ""
vap_vlan = root.find("evc/bds/bd/bdBindVlan")
if vap_vlan:
for ele in vap_vlan:
if ele.tag == "vlanList":
@ -471,7 +467,7 @@ class VxlanVap(object):
# get vap: l2 su-interface
vap_ifs = root.findall(
"data/evc/bds/bd/servicePoints/servicePoint/ifName")
"evc/bds/bd/servicePoints/servicePoint/ifName")
if_list = list()
if vap_ifs:
for vap_if in vap_ifs:
@ -500,7 +496,7 @@ class VxlanVap(object):
# get l2 sub interface encapsulation info
root = ElementTree.fromstring(xml_str)
bds = root.find("data/ethernet/servicePoints/servicePoint")
bds = root.find("ethernet/servicePoints/servicePoint")
if not bds:
return intf_info
@ -510,7 +506,7 @@ class VxlanVap(object):
if intf_info.get("flowType") == "dot1q":
ce_vid = root.find(
"data/ethernet/servicePoints/servicePoint/flowDot1qs")
"ethernet/servicePoints/servicePoint/flowDot1qs")
intf_info["dot1qVids"] = ""
if ce_vid:
for ele in ce_vid:
@ -518,7 +514,7 @@ class VxlanVap(object):
intf_info["dot1qVids"] = ele.text
elif intf_info.get("flowType") == "qinq":
vids = root.find(
"data/ethernet/servicePoints/servicePoint/flowQinqs/flowQinq")
"ethernet/servicePoints/servicePoint/flowQinqs/flowQinq")
if vids:
for ele in vids:
if ele.tag in ["peVlanId", "ceVids"]:
@ -708,9 +704,6 @@ class VxlanVap(object):
def config_vap_vlan(self):
"""configure a VLAN as a service access point"""
if not self.vap_info:
self.module.fail_json(msg="Error: Bridge domain %s does not exist." % self.bridge_domain_id)
xml_str = ""
if self.state == "present":
if not is_vlan_in_bitmap(self.bind_vlan_id, self.vap_info["vlanList"]):