mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 22:11:14 +02:00
Convert topologies < 3.0 to have valid node hostnames
This commit is contained in:
4 files changed
+206
-2
No files matched your search
@@ -495,7 +495,7 @@ class Project:
|
||||
|
||||
if base_name is None:
|
||||
return None
|
||||
base_name = re.sub(r"[ ]", "", base_name)
|
||||
base_name = re.sub(r"[ ]", "", base_name) # remove spaces in node name
|
||||
if base_name in self._allocated_node_names:
|
||||
base_name = re.sub(r"[0-9]+$", "{0}", base_name)
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ from .drawing import Drawing
|
||||
from .node import Node
|
||||
from .link import Link
|
||||
|
||||
from gns3server.utils.hostname import is_ios_hostname_valid, is_rfc1123_hostname_valid, to_rfc1123_hostname, to_ios_hostname
|
||||
from gns3server.schemas.controller.topology import Topology
|
||||
from gns3server.schemas.compute.dynamips_nodes import DynamipsCreate
|
||||
|
||||
@@ -43,7 +44,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
GNS3_FILE_FORMAT_REVISION = 9
|
||||
GNS3_FILE_FORMAT_REVISION = 10
|
||||
|
||||
|
||||
class DynamipsNodeValidation(DynamipsCreate):
|
||||
@@ -186,6 +187,10 @@ def load_topology(path):
|
||||
if variables:
|
||||
topo["variables"] = [var for var in variables if var.get("name")]
|
||||
|
||||
# Version before GNS3 3.0
|
||||
if topo["revision"] < 10:
|
||||
topo = _convert_2_2_0(topo, path)
|
||||
|
||||
try:
|
||||
_check_topology_schema(topo, path)
|
||||
except ControllerError as e:
|
||||
@@ -201,6 +206,31 @@ def load_topology(path):
|
||||
return topo
|
||||
|
||||
|
||||
def _convert_2_2_0(topo, topo_path):
|
||||
"""
|
||||
Convert topologies from GNS3 2.2.x to 3.0
|
||||
|
||||
Changes:
|
||||
* Removed acpi_shutdown option from Qemu, VMware and VirtualBox
|
||||
|
||||
"""
|
||||
|
||||
topo["revision"] = 10
|
||||
|
||||
for node in topo.get("topology", {}).get("nodes", []):
|
||||
# make sure console_type is not None but "none" string
|
||||
if "properties" in node:
|
||||
if node["node_type"] in ("qemu", "docker") and not is_rfc1123_hostname_valid(node["name"]):
|
||||
new_name = to_rfc1123_hostname(node["name"])
|
||||
log.info(f"Convert node name {node['name']} to {new_name} (RFC1123)")
|
||||
node["name"] = new_name
|
||||
if node["node_type"] in ("dynamips", "iou") and not is_ios_hostname_valid(node["name"] ):
|
||||
new_name = to_ios_hostname(node["name"])
|
||||
log.info(f"Convert node name {node['name']} to {new_name} (IOS)")
|
||||
node["name"] = new_name
|
||||
return topo
|
||||
|
||||
|
||||
def _convert_2_1_0(topo, topo_path):
|
||||
"""
|
||||
Convert topologies from GNS3 2.1.x to 2.2
|
||||
|
||||
@@ -32,6 +32,28 @@ def is_ios_hostname_valid(hostname: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def to_ios_hostname(name):
|
||||
"""
|
||||
Convert name to an IOS hostname
|
||||
"""
|
||||
|
||||
# Replace invalid characters with hyphens
|
||||
name = re.sub(r'[^a-zA-Z0-9-]', '-', name)
|
||||
|
||||
# Ensure the hostname starts with a letter
|
||||
if not re.search(r'^[a-zA-Z]', name):
|
||||
name = 'a' + name
|
||||
|
||||
# Ensure the hostname ends with a letter or digit
|
||||
if not re.search(r'[a-zA-Z0-9]$', name):
|
||||
name = name.rstrip('-') + '0'
|
||||
|
||||
# Truncate the hostname to 63 characters
|
||||
name = name[:63]
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def is_rfc1123_hostname_valid(hostname: str) -> bool:
|
||||
"""
|
||||
Check if a hostname is valid according to RFC 1123
|
||||
@@ -57,3 +79,34 @@ def is_rfc1123_hostname_valid(hostname: str) -> bool:
|
||||
|
||||
allowed = re.compile(r"(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$")
|
||||
return all(allowed.match(label) for label in labels)
|
||||
|
||||
|
||||
def to_rfc1123_hostname(name: str) -> str:
|
||||
"""
|
||||
Convert name to RFC 1123 hostname
|
||||
"""
|
||||
|
||||
# Replace invalid characters with hyphens
|
||||
name = re.sub(r'[^a-zA-Z0-9-.]', '-', name)
|
||||
|
||||
# Remove trailing dot if it exists
|
||||
name = name.rstrip('.')
|
||||
|
||||
# Ensure each label is not longer than 63 characters
|
||||
labels = name.split('.')
|
||||
labels = [label[:63] for label in labels]
|
||||
|
||||
# Remove leading and trailing hyphens from each label if they exist
|
||||
labels = [label.strip('-') for label in labels]
|
||||
|
||||
# Check if the TLD is all-numeric and if so, replace it with "invalid"
|
||||
if re.match(r"[0-9]+$", labels[-1]):
|
||||
labels[-1] = 'invalid'
|
||||
|
||||
# Join the labels back together
|
||||
name = '.'.join(labels)
|
||||
|
||||
# Ensure the total length is not longer than 253 characters
|
||||
name = name[:253]
|
||||
|
||||
return name
|
||||
Reference in new issue
Block a user