Skip to content

Commit

Permalink
Merge pull request #292 from SUNET/hotfix.1.4.1
Browse files Browse the repository at this point in the history
Hotfix.1.4.1
  • Loading branch information
indy-independence authored Mar 1, 2023
2 parents a30b4ad + 1b59651 commit 7ae5859
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 25 deletions.
9 changes: 9 additions & 0 deletions docs/changelog/index.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Changelog
=========

Version 1.4.1
-------------

Bug fixes:

- Fixed interface range expansion logic for downlink ports during init
- Allow setting of untagged_vlan to null in interfaces API (#290)
- Fix duplicate generation of underlay BGP peers (#291)

Version 1.4.0
-------------

Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ APScheduler==3.9.1
coverage==6.4.4
Flask-Cors==3.0.10
Flask-JWT-Extended==4.4.4
flask-restx==0.5.1
flask-restx==1.0.5
flask==2.1.2
Flask-SocketIO==5.3.1
gevent==21.12.0
Expand Down Expand Up @@ -31,5 +31,5 @@ SQLAlchemy==1.4.41
sqlalchemy-stubs==0.4
SQLAlchemy-Utils==0.38.3
pydantic==1.10.2
Werkzeug==2.1.2
Werkzeug==2.2.3
greenlet==1.1.3
18 changes: 11 additions & 7 deletions src/cnaas_nms/api/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,19 @@ def put(self, hostname):
"Specified VXLAN {} is not present in {}".format(if_dict["data"]["vxlan"], hostname)
)
if "untagged_vlan" in if_dict["data"]:
vlan_id = resolve_vlanid(if_dict["data"]["untagged_vlan"], device_settings["vxlans"])
if vlan_id:
intfdata["untagged_vlan"] = if_dict["data"]["untagged_vlan"]
if if_dict["data"]["untagged_vlan"] is None:
if "untagged_vlan" in intfdata:
del intfdata["untagged_vlan"]
else:
errors.append(
"Specified VLAN name {} is not present in {}".format(
if_dict["data"]["untagged_vlan"], hostname
vlan_id = resolve_vlanid(if_dict["data"]["untagged_vlan"], device_settings["vxlans"])
if vlan_id:
intfdata["untagged_vlan"] = if_dict["data"]["untagged_vlan"]
else:
errors.append(
"Specified VLAN name {} is not present in {}".format(
if_dict["data"]["untagged_vlan"], hostname
)
)
)
if "tagged_vlan_list" in if_dict["data"]:
if isinstance(if_dict["data"]["tagged_vlan_list"], list):
vlan_id_list = resolve_vlanid_list(
Expand Down
8 changes: 4 additions & 4 deletions src/cnaas_nms/db/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ def as_dict(self) -> dict:
d[col.name] = value
return d

def get_neighbors(self, session, linknets: Optional[List[dict]] = None) -> List[Device]:
def get_neighbors(self, session, linknets: Optional[List[dict]] = None) -> Set[Device]:
"""Look up neighbors from cnaas_nms.db.linknet.Linknets and return them as a list of Device objects."""
if not linknets:
linknets = self.get_linknets(session)
ret = []
ret: Set = set()
for linknet in linknets:
if isinstance(linknet, cnaas_nms.db.linknet.Linknet):
device_a_id = linknet.device_a_id
Expand All @@ -125,9 +125,9 @@ def get_neighbors(self, session, linknets: Optional[List[dict]] = None) -> List[
device_a_id = linknet["device_a_id"]
device_b_id = linknet["device_b_id"]
if device_a_id == self.id:
ret.append(session.query(Device).filter(Device.id == device_b_id).one())
ret.add(session.query(Device).filter(Device.id == device_b_id).one())
else:
ret.append(session.query(Device).filter(Device.id == device_a_id).one())
ret.add(session.query(Device).filter(Device.id == device_a_id).one())
return ret

def get_linknets(self, session) -> List[cnaas_nms.db.linknet.Linknet]:
Expand Down
8 changes: 4 additions & 4 deletions src/cnaas_nms/db/settings_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
r"[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|" # 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
r":((:[0-9a-fA-F]{1,4}){1,7}|:))"
)
FQDN_REGEX = r"([a-z0-9-]{1,63}\.)([a-z-][a-z0-9-]{1,62}\.?)+"
FQDN_REGEX = r"([a-zA-Z0-9-]{1,63}\.)([a-z-][a-z0-9-]{1,62}\.?)+"
HOST_REGEX = f"^({IPV4_REGEX}|{IPV6_REGEX}|{FQDN_REGEX})$"
HOSTNAME_REGEX = r"^([a-z0-9-]{1,63})(\.[a-z0-9-]{1,63})*$"
DOMAIN_NAME_REGEX = r"^([a-z0-9-]{1,63})(\.[a-z0-9-]{1,63})+$"
HOSTNAME_REGEX = r"^([a-zA-Z0-9-]{1,63})(\.[a-z0-9-]{1,63})*$"
DOMAIN_NAME_REGEX = r"^([a-zA-Z0-9-]{1,63})(\.[a-z0-9-]{1,63})+$"
host_schema = Field(..., regex=HOST_REGEX, max_length=253, description="Hostname, FQDN or IP address")
hostname_schema = Field(..., regex=HOSTNAME_REGEX, max_length=253, description="Hostname or FQDN")
domain_name_schema = Field(None, regex=DOMAIN_NAME_REGEX, max_length=251, description="DNS domain name")
Expand Down Expand Up @@ -58,7 +58,7 @@
ebgp_multihop_schema = Field(None, ge=1, le=255, description="Numeric IP TTL, 1-255")
maximum_routes_schema = Field(None, ge=0, le=4294967294, description="Maximum number of routes to receive from peer")

GROUP_NAME = r"^([a-zA-Z0-9_]{1,63}\.?)+$"
GROUP_NAME = r"^([a-zA-Z0-9_-]{1,63}\.?)+$"
group_name = Field(..., regex=GROUP_NAME, max_length=253)
group_priority_schema = Field(
0, ge=0, le=100, description="Group priority 0-100, default 0, higher value means higher priority"
Expand Down
4 changes: 2 additions & 2 deletions src/cnaas_nms/db/tests/test_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ def test_get_neighbors(self):
Linknet(device_a=device1, device_b=device2)
device1 = session.query(Device).filter(Device.hostname == "test-device1").one()
device2 = session.query(Device).filter(Device.hostname == "test-device2").one()
self.assertEqual([device2], device1.get_neighbors(session))
self.assertEqual([device1], device2.get_neighbors(session))
self.assertEqual(set([device2]), device1.get_neighbors(session))
self.assertEqual(set([device1]), device2.get_neighbors(session))

def test_is_stack(self):
with sqla_session() as session:
Expand Down
11 changes: 6 additions & 5 deletions src/cnaas_nms/devicehandler/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import cnaas_nms.devicehandler.nornir_helper
from cnaas_nms.db.device import Device, DeviceType
from cnaas_nms.db.device_vars import expand_interface_settings
from cnaas_nms.db.interface import Interface, InterfaceConfigType, InterfaceError
from cnaas_nms.tools.log import get_logger

Expand Down Expand Up @@ -241,7 +242,7 @@ def verify_peer_iftype(
# Make sure interface with peers are configured in settings for CORE and DIST devices
if remote_dev.device_type in [DeviceType.DIST, DeviceType.CORE]:
match = False
for intf in remote_device_settings["interfaces"]:
for intf in expand_interface_settings(remote_device_settings["interfaces"]):
if intf["name"] == remote_if:
match = True
if not match:
Expand All @@ -250,7 +251,7 @@ def verify_peer_iftype(
)
if local_dev.device_type in [DeviceType.DIST, DeviceType.CORE]:
match = False
for intf in local_device_settings["interfaces"]:
for intf in expand_interface_settings(local_device_settings["interfaces"]):
if intf["name"] == local_if:
match = True
if not match:
Expand All @@ -263,13 +264,13 @@ def verify_peer_iftype(
DeviceType.DIST,
DeviceType.CORE,
]:
for intf in local_device_settings["interfaces"]:
for intf in expand_interface_settings(local_device_settings["interfaces"]):
if intf["name"] == local_if and intf["ifclass"] != "fabric":
raise InterfaceError(
"Local device interface is not configured as fabric: "
"{} {} ifclass: {}".format(local_dev.hostname, intf["name"], intf["ifclass"])
)
for intf in remote_device_settings["interfaces"]:
for intf in expand_interface_settings(remote_device_settings["interfaces"]):
if intf["name"] == remote_if and intf["ifclass"] != "fabric":
raise InterfaceError(
"Peer device interface is not configured as fabric: "
Expand All @@ -279,7 +280,7 @@ def verify_peer_iftype(
# Make sure that an access switch is connected to an interface
# configured as "downlink" on the remote end
if local_dev.device_type == DeviceType.ACCESS and remote_dev.device_type == DeviceType.DIST:
for intf in remote_device_settings["interfaces"]:
for intf in expand_interface_settings(remote_device_settings["interfaces"]):
if intf["name"] == remote_if and intf["ifclass"] != "downlink":
raise InterfaceError(
"Peer device interface is not configured as downlink: "
Expand Down
2 changes: 1 addition & 1 deletion src/cnaas_nms/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = "1.4.0"
__version__ = "1.4.1"
__version_info__ = tuple([field for field in __version__.split(".")])
__api_version__ = "v1.0"

0 comments on commit 7ae5859

Please sign in to comment.