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:
parent
e009936f87
commit
5bddd55703
8 changed files with 142 additions and 92 deletions
8
changelogs/fragments/57264-update-vxlan-to-fix-bugs.yml
Normal file
8
changelogs/fragments/57264-update-vxlan-to-fix-bugs.yml
Normal 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.
|
|
@ -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.")
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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"""
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"]):
|
||||
|
|
Loading…
Reference in a new issue