mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-01 04:38:12 +00:00
Merge pull request #2406 from GNS3/feature/convert-invalid-node-names
Convert node hostnames for topologies
This commit is contained in:
commit
9a3bd2ee0c
@ -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,30 @@ 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:
|
||||
* Convert Qemu and Docker node names to be a valid RFC1123 hostnames.
|
||||
* Convert Dynamips and IOU node names to be a valid IOS hostnames.
|
||||
"""
|
||||
|
||||
topo["revision"] = 10
|
||||
|
||||
for node in topo.get("topology", {}).get("nodes", []):
|
||||
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
|
||||
|
@ -23,11 +23,11 @@
|
||||
"label": {
|
||||
"rotation": 0,
|
||||
"style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
|
||||
"text": "remote_busybox-1",
|
||||
"text": "remote-busybox-1",
|
||||
"x": -20,
|
||||
"y": -25
|
||||
},
|
||||
"name": "remote_busybox-1",
|
||||
"name": "remote-busybox-1",
|
||||
"node_id": "d397ef5a-84f1-4b6b-9d44-671937ec7781",
|
||||
"node_type": "docker",
|
||||
"port_name_format": "Ethernet{0}",
|
||||
|
@ -11,7 +11,7 @@
|
||||
"label": {
|
||||
"color": "#ff000000",
|
||||
"font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
|
||||
"text": "remote_busybox-1",
|
||||
"text": "remote-busybox-1",
|
||||
"x": -20.4453125,
|
||||
"y": -25.0
|
||||
},
|
||||
@ -32,7 +32,7 @@
|
||||
"console_resolution": "1024x768",
|
||||
"console_type": "telnet",
|
||||
"image": "busybox:latest",
|
||||
"name": "remote_busybox-1"
|
||||
"name": "remote-busybox-1"
|
||||
},
|
||||
"server_id": 2,
|
||||
"type": "DockerVM",
|
||||
|
222
tests/topologies/3_0_hostnames/after/3_0_hostnames.gns3
Normal file
222
tests/topologies/3_0_hostnames/after/3_0_hostnames.gns3
Normal file
@ -0,0 +1,222 @@
|
||||
{
|
||||
"auto_close": true,
|
||||
"auto_open": false,
|
||||
"auto_start": false,
|
||||
"drawing_grid_size": 25,
|
||||
"grid_size": 75,
|
||||
"name": "test-hostnames",
|
||||
"project_id": "8b83e3ac-6b6a-4d6b-9938-bd630a6e458e",
|
||||
"revision": 10,
|
||||
"scene_height": 1000,
|
||||
"scene_width": 2000,
|
||||
"show_grid": false,
|
||||
"show_interface_labels": false,
|
||||
"show_layers": false,
|
||||
"snap_to_grid": false,
|
||||
"supplier": null,
|
||||
"topology": {
|
||||
"computes": [],
|
||||
"drawings": [],
|
||||
"links": [],
|
||||
"nodes": [
|
||||
{
|
||||
"compute_id": "local",
|
||||
"console": 5000,
|
||||
"console_auto_start": false,
|
||||
"console_type": "telnet",
|
||||
"custom_adapters": [],
|
||||
"first_port_name": null,
|
||||
"height": 45,
|
||||
"label": {
|
||||
"rotation": 0,
|
||||
"style": "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
|
||||
"text": "42Router_A-1",
|
||||
"x": -20,
|
||||
"y": -25
|
||||
},
|
||||
"locked": false,
|
||||
"name": "a42Router-A-1",
|
||||
"node_id": "adb89fbb-92ba-419b-96ca-1ad0f03ce3f6",
|
||||
"node_type": "dynamips",
|
||||
"port_name_format": "Ethernet{0}",
|
||||
"port_segment_size": 0,
|
||||
"properties": {
|
||||
"auto_delete_disks": false,
|
||||
"aux": null,
|
||||
"clock_divisor": 8,
|
||||
"disk0": 0,
|
||||
"disk1": 0,
|
||||
"dynamips_id": 1,
|
||||
"exec_area": 64,
|
||||
"idlemax": 500,
|
||||
"idlepc": "0x60aa1da0",
|
||||
"idlesleep": 30,
|
||||
"image": "c3745-adventerprisek9-mz.124-25d.image",
|
||||
"image_md5sum": "ddbaf74274822b50fa9670e10c75b08f",
|
||||
"iomem": 5,
|
||||
"mac_addr": "c401.fff5.0000",
|
||||
"mmap": true,
|
||||
"nvram": 256,
|
||||
"platform": "c3745",
|
||||
"ram": 256,
|
||||
"slot0": "GT96100-FE",
|
||||
"slot1": "NM-1FE-TX",
|
||||
"slot2": "NM-4T",
|
||||
"slot3": null,
|
||||
"slot4": null,
|
||||
"sparsemem": true,
|
||||
"system_id": "FTX0945W0MY",
|
||||
"usage": "",
|
||||
"wic0": "WIC-1T",
|
||||
"wic1": "WIC-1T",
|
||||
"wic2": "WIC-1T"
|
||||
},
|
||||
"symbol": ":/symbols/classic/router.svg",
|
||||
"template_id": "24f09d1a-64e1-4dc4-ae49-e785c1dbc0c5",
|
||||
"width": 66,
|
||||
"x": -130,
|
||||
"y": -64,
|
||||
"z": 1
|
||||
},
|
||||
{
|
||||
"compute_id": "local",
|
||||
"console": 5001,
|
||||
"console_auto_start": false,
|
||||
"console_type": "telnet",
|
||||
"custom_adapters": [
|
||||
{
|
||||
"adapter_number": 0,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 1,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 2,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 3,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 4,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 5,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 6,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 7,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 8,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 9,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 10,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 11,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 12,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 13,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 14,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 15,
|
||||
"adapter_type": "e1000"
|
||||
}
|
||||
],
|
||||
"first_port_name": "",
|
||||
"height": 48,
|
||||
"label": {
|
||||
"rotation": 0,
|
||||
"style": "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
|
||||
"text": "Switch_10.0.0.1",
|
||||
"x": -36,
|
||||
"y": -25
|
||||
},
|
||||
"locked": false,
|
||||
"name": "Switch-10.0.0.invalid",
|
||||
"node_id": "ccda4e49-770f-4237-956b-cc7281630468",
|
||||
"node_type": "qemu",
|
||||
"port_name_format": "Gi0/{0}",
|
||||
"port_segment_size": 4,
|
||||
"properties": {
|
||||
"adapter_type": "e1000",
|
||||
"adapters": 16,
|
||||
"bios_image": "",
|
||||
"bios_image_md5sum": null,
|
||||
"boot_priority": "c",
|
||||
"cdrom_image": "",
|
||||
"cdrom_image_md5sum": null,
|
||||
"cpu_throttling": 0,
|
||||
"cpus": 1,
|
||||
"create_config_disk": false,
|
||||
"hda_disk_image": "vios_l2-adventerprisek9-m.03.2017.qcow2",
|
||||
"hda_disk_image_md5sum": "8f14b50083a14688dec2fc791706bb3e",
|
||||
"hda_disk_interface": "virtio",
|
||||
"hdb_disk_image": "",
|
||||
"hdb_disk_image_md5sum": null,
|
||||
"hdb_disk_interface": "none",
|
||||
"hdc_disk_image": "",
|
||||
"hdc_disk_image_md5sum": null,
|
||||
"hdc_disk_interface": "none",
|
||||
"hdd_disk_image": "",
|
||||
"hdd_disk_image_md5sum": null,
|
||||
"hdd_disk_interface": "none",
|
||||
"initrd": "",
|
||||
"initrd_md5sum": null,
|
||||
"kernel_command_line": "",
|
||||
"kernel_image": "",
|
||||
"kernel_image_md5sum": null,
|
||||
"legacy_networking": false,
|
||||
"linked_clone": true,
|
||||
"mac_address": "0c:da:4e:49:00:00",
|
||||
"on_close": "power_off",
|
||||
"options": "",
|
||||
"platform": "x86_64",
|
||||
"process_priority": "normal",
|
||||
"qemu_path": "/bin/qemu-system-x86_64",
|
||||
"ram": 768,
|
||||
"replicate_network_connection_state": true,
|
||||
"tpm": false,
|
||||
"uefi": false,
|
||||
"usage": "There is no default password and enable password. There is no default configuration present. SUPER UPDATED!"
|
||||
},
|
||||
"symbol": ":/symbols/classic/multilayer_switch.svg",
|
||||
"template_id": "9db64790-65f4-4d38-a1ac-2f6ce45b70db",
|
||||
"width": 51,
|
||||
"x": -13,
|
||||
"y": 54,
|
||||
"z": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "topology",
|
||||
"variables": null,
|
||||
"version": "2.2.49",
|
||||
"zoom": 100
|
||||
}
|
222
tests/topologies/3_0_hostnames/before/3_0_hostnames.gns3
Normal file
222
tests/topologies/3_0_hostnames/before/3_0_hostnames.gns3
Normal file
@ -0,0 +1,222 @@
|
||||
{
|
||||
"auto_close": true,
|
||||
"auto_open": false,
|
||||
"auto_start": false,
|
||||
"drawing_grid_size": 25,
|
||||
"grid_size": 75,
|
||||
"name": "test-hostnames",
|
||||
"project_id": "8b83e3ac-6b6a-4d6b-9938-bd630a6e458e",
|
||||
"revision": 9,
|
||||
"scene_height": 1000,
|
||||
"scene_width": 2000,
|
||||
"show_grid": false,
|
||||
"show_interface_labels": false,
|
||||
"show_layers": false,
|
||||
"snap_to_grid": false,
|
||||
"supplier": null,
|
||||
"topology": {
|
||||
"computes": [],
|
||||
"drawings": [],
|
||||
"links": [],
|
||||
"nodes": [
|
||||
{
|
||||
"compute_id": "local",
|
||||
"console": 5000,
|
||||
"console_auto_start": false,
|
||||
"console_type": "telnet",
|
||||
"custom_adapters": [],
|
||||
"first_port_name": null,
|
||||
"height": 45,
|
||||
"label": {
|
||||
"rotation": 0,
|
||||
"style": "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
|
||||
"text": "42Router_A-1",
|
||||
"x": -20,
|
||||
"y": -25
|
||||
},
|
||||
"locked": false,
|
||||
"name": "42Router_A-1",
|
||||
"node_id": "adb89fbb-92ba-419b-96ca-1ad0f03ce3f6",
|
||||
"node_type": "dynamips",
|
||||
"port_name_format": "Ethernet{0}",
|
||||
"port_segment_size": 0,
|
||||
"properties": {
|
||||
"auto_delete_disks": false,
|
||||
"aux": null,
|
||||
"clock_divisor": 8,
|
||||
"disk0": 0,
|
||||
"disk1": 0,
|
||||
"dynamips_id": 1,
|
||||
"exec_area": 64,
|
||||
"idlemax": 500,
|
||||
"idlepc": "0x60aa1da0",
|
||||
"idlesleep": 30,
|
||||
"image": "c3745-adventerprisek9-mz.124-25d.image",
|
||||
"image_md5sum": "ddbaf74274822b50fa9670e10c75b08f",
|
||||
"iomem": 5,
|
||||
"mac_addr": "c401.fff5.0000",
|
||||
"mmap": true,
|
||||
"nvram": 256,
|
||||
"platform": "c3745",
|
||||
"ram": 256,
|
||||
"slot0": "GT96100-FE",
|
||||
"slot1": "NM-1FE-TX",
|
||||
"slot2": "NM-4T",
|
||||
"slot3": null,
|
||||
"slot4": null,
|
||||
"sparsemem": true,
|
||||
"system_id": "FTX0945W0MY",
|
||||
"usage": "",
|
||||
"wic0": "WIC-1T",
|
||||
"wic1": "WIC-1T",
|
||||
"wic2": "WIC-1T"
|
||||
},
|
||||
"symbol": ":/symbols/classic/router.svg",
|
||||
"template_id": "24f09d1a-64e1-4dc4-ae49-e785c1dbc0c5",
|
||||
"width": 66,
|
||||
"x": -130,
|
||||
"y": -64,
|
||||
"z": 1
|
||||
},
|
||||
{
|
||||
"compute_id": "local",
|
||||
"console": 5001,
|
||||
"console_auto_start": false,
|
||||
"console_type": "telnet",
|
||||
"custom_adapters": [
|
||||
{
|
||||
"adapter_number": 0,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 1,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 2,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 3,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 4,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 5,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 6,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 7,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 8,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 9,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 10,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 11,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 12,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 13,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 14,
|
||||
"adapter_type": "e1000"
|
||||
},
|
||||
{
|
||||
"adapter_number": 15,
|
||||
"adapter_type": "e1000"
|
||||
}
|
||||
],
|
||||
"first_port_name": "",
|
||||
"height": 48,
|
||||
"label": {
|
||||
"rotation": 0,
|
||||
"style": "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
|
||||
"text": "Switch_10.0.0.1",
|
||||
"x": -36,
|
||||
"y": -25
|
||||
},
|
||||
"locked": false,
|
||||
"name": "Switch_10.0.0.1",
|
||||
"node_id": "ccda4e49-770f-4237-956b-cc7281630468",
|
||||
"node_type": "qemu",
|
||||
"port_name_format": "Gi0/{0}",
|
||||
"port_segment_size": 4,
|
||||
"properties": {
|
||||
"adapter_type": "e1000",
|
||||
"adapters": 16,
|
||||
"bios_image": "",
|
||||
"bios_image_md5sum": null,
|
||||
"boot_priority": "c",
|
||||
"cdrom_image": "",
|
||||
"cdrom_image_md5sum": null,
|
||||
"cpu_throttling": 0,
|
||||
"cpus": 1,
|
||||
"create_config_disk": false,
|
||||
"hda_disk_image": "vios_l2-adventerprisek9-m.03.2017.qcow2",
|
||||
"hda_disk_image_md5sum": "8f14b50083a14688dec2fc791706bb3e",
|
||||
"hda_disk_interface": "virtio",
|
||||
"hdb_disk_image": "",
|
||||
"hdb_disk_image_md5sum": null,
|
||||
"hdb_disk_interface": "none",
|
||||
"hdc_disk_image": "",
|
||||
"hdc_disk_image_md5sum": null,
|
||||
"hdc_disk_interface": "none",
|
||||
"hdd_disk_image": "",
|
||||
"hdd_disk_image_md5sum": null,
|
||||
"hdd_disk_interface": "none",
|
||||
"initrd": "",
|
||||
"initrd_md5sum": null,
|
||||
"kernel_command_line": "",
|
||||
"kernel_image": "",
|
||||
"kernel_image_md5sum": null,
|
||||
"legacy_networking": false,
|
||||
"linked_clone": true,
|
||||
"mac_address": "0c:da:4e:49:00:00",
|
||||
"on_close": "power_off",
|
||||
"options": "",
|
||||
"platform": "x86_64",
|
||||
"process_priority": "normal",
|
||||
"qemu_path": "/bin/qemu-system-x86_64",
|
||||
"ram": 768,
|
||||
"replicate_network_connection_state": true,
|
||||
"tpm": false,
|
||||
"uefi": false,
|
||||
"usage": "There is no default password and enable password. There is no default configuration present. SUPER UPDATED!"
|
||||
},
|
||||
"symbol": ":/symbols/classic/multilayer_switch.svg",
|
||||
"template_id": "9db64790-65f4-4d38-a1ac-2f6ce45b70db",
|
||||
"width": 51,
|
||||
"x": -13,
|
||||
"y": 54,
|
||||
"z": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "topology",
|
||||
"variables": null,
|
||||
"version": "2.2.49",
|
||||
"zoom": 100
|
||||
}
|
121
tests/utils/test_hostname.py
Normal file
121
tests/utils/test_hostname.py
Normal file
@ -0,0 +1,121 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2024 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from gns3server.utils import hostname
|
||||
|
||||
|
||||
def test_ios_hostname_valid_with_valid_hostnames():
|
||||
assert hostname.is_ios_hostname_valid("router1")
|
||||
assert hostname.is_ios_hostname_valid("switch-2")
|
||||
assert hostname.is_ios_hostname_valid("a1-b2-c3")
|
||||
|
||||
|
||||
def test_ios_hostname_valid_with_invalid_hostnames():
|
||||
assert not hostname.is_ios_hostname_valid("-router")
|
||||
assert not hostname.is_ios_hostname_valid("router-")
|
||||
assert not hostname.is_ios_hostname_valid("123router")
|
||||
assert not hostname.is_ios_hostname_valid("router@123")
|
||||
assert not hostname.is_ios_hostname_valid("router.router")
|
||||
|
||||
|
||||
def test_ios_hostname_valid_with_long_hostnames():
|
||||
assert hostname.is_ios_hostname_valid("a" * 63)
|
||||
assert not hostname.is_ios_hostname_valid("a" * 64)
|
||||
|
||||
|
||||
def test_ios_hostname_conversion_with_valid_characters():
|
||||
assert hostname.to_ios_hostname("validHostname123") == "validHostname123"
|
||||
|
||||
|
||||
def test_ios_hostname_conversion_starts_with_digit():
|
||||
assert hostname.to_ios_hostname("1InvalidStart") == "a1InvalidStart"
|
||||
|
||||
|
||||
def test_ios_hostname_conversion_starts_with_special_character():
|
||||
assert hostname.to_ios_hostname("@InvalidStart") == "a-InvalidStart"
|
||||
|
||||
|
||||
def test_ios_hostname_conversion_ends_with_special_character():
|
||||
assert hostname.to_ios_hostname("InvalidEnd-") == "InvalidEnd0"
|
||||
|
||||
|
||||
def test_ios_hostname_conversion_contains_special_characters():
|
||||
assert hostname.to_ios_hostname("Invalid@Hostname!") == "Invalid-Hostname0"
|
||||
|
||||
|
||||
def test_ios_hostname_conversion_exceeds_max_length():
|
||||
long_name = "a" * 64
|
||||
assert hostname.to_ios_hostname(long_name) == "a" * 63
|
||||
|
||||
|
||||
def test_ios_hostname_conversion_just_right_length():
|
||||
exact_length_name = "a" * 63
|
||||
assert hostname.to_ios_hostname(exact_length_name) == "a" * 63
|
||||
|
||||
|
||||
def test_rfc1123_hostname_validity_with_valid_hostnames():
|
||||
assert hostname.is_rfc1123_hostname_valid("example.com")
|
||||
assert hostname.is_rfc1123_hostname_valid("subdomain.example.com")
|
||||
assert hostname.is_rfc1123_hostname_valid("example-hyphen.com")
|
||||
assert hostname.is_rfc1123_hostname_valid("example.com.")
|
||||
assert hostname.is_rfc1123_hostname_valid("123.com")
|
||||
|
||||
|
||||
def test_rfc1123_hostname_validity_with_invalid_hostnames():
|
||||
assert not hostname.is_rfc1123_hostname_valid("-example.com")
|
||||
assert not hostname.is_rfc1123_hostname_valid("example-.com")
|
||||
assert not hostname.is_rfc1123_hostname_valid("example..com")
|
||||
assert not hostname.is_rfc1123_hostname_valid("example_com")
|
||||
assert not hostname.is_rfc1123_hostname_valid("example.123")
|
||||
|
||||
|
||||
def test_rfc1123_hostname_validity_with_long_hostnames():
|
||||
long_hostname = "a" * 63 + "." + "b" * 63 + "." + "c" * 63 + "." + "d" * 61 # 253 characters
|
||||
too_long_hostname = long_hostname + "e"
|
||||
assert hostname.is_rfc1123_hostname_valid(long_hostname)
|
||||
assert not hostname.is_rfc1123_hostname_valid(too_long_hostname)
|
||||
|
||||
|
||||
def test_rfc1123_conversion_hostname_with_valid_characters():
|
||||
assert hostname.to_rfc1123_hostname("valid-hostname.example.com") == "valid-hostname.example.com"
|
||||
|
||||
|
||||
def test_rfc1123_conversion_hostname_with_invalid_characters_replaced():
|
||||
assert hostname.to_rfc1123_hostname("invalid_hostname!@#$.example") == "invalid-hostname.example"
|
||||
|
||||
|
||||
def test_rfc1123_conversion_hostname_with_trailing_dot_removed():
|
||||
assert hostname.to_rfc1123_hostname("hostname.example.com.") == "hostname.example.com"
|
||||
|
||||
|
||||
def test_rfc1123_conversion_hostname_with_labels_exceeding_63_characters():
|
||||
long_label = "a" * 64 + ".example.com"
|
||||
expected_label = "a" * 63 + ".example.com"
|
||||
assert hostname.to_rfc1123_hostname(long_label) == expected_label
|
||||
|
||||
|
||||
def test_rfc1123_conversion_hostname_with_total_length_exceeding_253_characters():
|
||||
long_hostname = "a" * 50 + "." + "b" * 50 + "." + "c" * 50 + "." + "d" * 50 + "." + "e" * 50
|
||||
assert len(hostname.to_rfc1123_hostname(long_hostname)) <= 253
|
||||
|
||||
|
||||
def test_rfc1123_conversion_hostname_with_all_numeric_tld_replaced():
|
||||
assert hostname.to_rfc1123_hostname("hostname.123") == "hostname.invalid"
|
||||
|
||||
|
||||
def rfc1123_hostname_with_multiple_consecutive_invalid_characters():
|
||||
assert hostname.to_rfc1123_hostname("hostname!!!.example..com") == "hostname---.example.com"
|
Loading…
Reference in New Issue
Block a user