2026-01-25 18:01:48 +01:00

232 lines
7.0 KiB
Python

"""CLI command generators for Cisco devices"""
from typing import List, Dict, Any, Optional
def generate_hostname_cli(hostname: str) -> List[str]:
"""Generate hostname configuration command"""
return [f"hostname {hostname}"]
def generate_vlan_cli(vlans: List[Dict[str, Any]]) -> List[str]:
"""
Generate VLAN configuration commands
Args:
vlans: List of dicts with keys:
- id (int)
- name (str)
Returns:
List of CLI commands
"""
commands = []
for vlan in vlans:
vlan_id = vlan.get("id")
vlan_name = vlan.get("name", f"VLAN{vlan_id}")
commands.append(f"vlan {vlan_id}")
commands.append(f" name {vlan_name}")
commands.append("!")
return commands
def generate_interface_cli(interfaces: List[Dict[str, Any]]) -> List[str]:
"""
Generate interface configuration commands
Args:
interfaces: List of dicts with keys:
- name (str): e.g., "GigabitEthernet0/1"
- description (str)
- type (str): "access" or "trunk"
- vlan (int): VLAN ID for access ports
- trunk_vlans (list): VLAN IDs for trunk
- ip_address (str): IP address (e.g., "10.0.0.1/24")
- enabled (bool)
Returns:
List of CLI commands
"""
commands = []
for iface in interfaces:
iface_name = iface.get("name")
description = iface.get("description")
iface_type = iface.get("type", "access")
enabled = iface.get("enabled", True)
commands.append(f"interface {iface_name}")
if description:
commands.append(f" description {description}")
# Switchport configuration
if iface_type == "access":
commands.append(" switchport mode access")
vlan = iface.get("vlan")
if vlan:
commands.append(f" switchport access vlan {vlan}")
elif iface_type == "trunk":
commands.append(" switchport mode trunk")
trunk_vlans = iface.get("trunk_vlans")
if trunk_vlans:
vlan_list = ",".join(map(str, trunk_vlans))
commands.append(f" switchport trunk allowed vlan {vlan_list}")
# IP configuration
ip_address = iface.get("ip_address")
if ip_address:
# Assume CIDR notation, convert to netmask
# e.g., "10.0.0.1/24" -> "10.0.0.1 255.255.255.0"
commands.append(f" ip address {ip_address.replace('/', ' ')}")
# Enable/disable
if not enabled:
commands.append(" shutdown")
else:
commands.append(" no shutdown")
commands.append("!")
return commands
def generate_routing_cli(routes: List[Dict[str, Any]]) -> List[str]:
"""
Generate static routing commands
Args:
routes: List of dicts with keys:
- destination (str): CIDR notation
- gateway (str): Next-hop IP
- metric (int): Optional metric/distance
Returns:
List of CLI commands
"""
commands = []
for route in routes:
destination = route.get("destination")
gateway = route.get("gateway")
metric = route.get("metric")
cmd = f"ip route {destination} {gateway}"
if metric:
cmd += f" {metric}"
commands.append(cmd)
return commands
def generate_nat_cli(nat_config: Dict[str, Any]) -> List[str]:
"""
Generate NAT (Network Address Translation) commands
Args:
nat_config: Dict with keys:
- inside_interface (str): Inside interface name
- outside_interface (str): Outside interface name
- inside_addresses (list): List of inside networks in CIDR
- outside_address (str): Single public IP for overload
Returns:
List of CLI commands
"""
commands = []
# Mark inside/outside interfaces
inside_iface = nat_config.get("inside_interface")
outside_iface = nat_config.get("outside_interface")
if inside_iface:
commands.append(f"interface {inside_iface}")
commands.append(" ip nat inside")
commands.append("!")
if outside_iface:
commands.append(f"interface {outside_iface}")
commands.append(" ip nat outside")
commands.append("!")
# NAT rules
inside_addresses = nat_config.get("inside_addresses", [])
outside_address = nat_config.get("outside_address")
for idx, inside_network in enumerate(inside_addresses, start=1):
acl_id = 100 + idx
commands.append(f"ip access-list standard NAT_INSIDE")
commands.append(f" {idx} permit {inside_network}")
commands.append("!")
if outside_address:
commands.append("ip nat inside source list 101 interface GigabitEthernet0/0 overload")
return commands
def generate_acl_cli(acls: List[Dict[str, Any]]) -> List[str]:
"""
Generate ACL (Access Control List) commands
Args:
acls: List of dicts with keys:
- name (str) or acl_id (int)
- type (str): "standard" or "extended"
- rules (list): List of dicts:
- action (str): "permit" or "deny"
- protocol (str): "ip", "tcp", "udp", etc.
- source (str): IP/CIDR or "any"
- destination (str): IP/CIDR (extended only)
- port (int): Port number (extended + protocol-specific)
Returns:
List of CLI commands
"""
commands = []
for acl in acls:
acl_type = acl.get("type", "standard")
acl_name = acl.get("name")
acl_id = acl.get("acl_id")
# ACL header
if acl_type == "standard":
if acl_id:
acl_header = f"access-list {acl_id}"
else:
acl_header = f"ip access-list standard {acl_name}"
else: # extended
if acl_id:
acl_header = f"access-list {acl_id}"
else:
acl_header = f"ip access-list extended {acl_name}"
# If named ACL, enter config mode
if acl_name:
commands.append(acl_header)
# ACL rules
for rule_idx, rule in enumerate(acl.get("rules", []), start=1):
action = rule.get("action", "permit")
protocol = rule.get("protocol", "ip")
source = rule.get("source", "any")
if acl_type == "standard":
cmd = f" {rule_idx} {action} {source}"
else: # extended
destination = rule.get("destination", "any")
cmd = f" {rule_idx} {action} {protocol} {source} {destination}"
# Add port if applicable
port = rule.get("port")
if port:
cmd += f" eq {port}"
commands.append(cmd)
if acl_name:
commands.append("!")
return commands