#!/usr/bin/env python # # Copyright (C) 2016 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 . import aiohttp from gns3server.utils import macaddress_to_int, int_to_macaddress from .atm_port import ATMPort from .frame_relay_port import FrameRelayPort from .gigabitethernet_port import GigabitEthernetPort from .fastethernet_port import FastEthernetPort from .ethernet_port import EthernetPort from .serial_port import SerialPort from .pos_port import POSPort import logging log = logging.getLogger(__name__) PORTS = { 'atm': ATMPort, 'frame_relay': FrameRelayPort, 'fastethernet': FastEthernetPort, 'gigabitethernet': GigabitEthernetPort, 'ethernet': EthernetPort, 'serial': SerialPort } class PortFactory: """ Factory to create an Port object based on the type """ def __new__(cls, name, interface_number, adapter_number, port_number, port_type, **kwargs): return PORTS[port_type](name, interface_number, adapter_number, port_number, **kwargs) class StandardPortFactory: """ Create ports for standard device """ def __new__(cls, properties, port_by_adapter, first_port_name, port_name_format, port_segment_size, custom_adapters): ports = [] adapter_number = interface_number = segment_number = 0 if "ethernet_adapters" in properties: ethernet_adapters = properties["ethernet_adapters"] else: ethernet_adapters = properties.get("adapters", 1) for adapter_number in range(adapter_number, ethernet_adapters + adapter_number): custom_adapter_settings = {} for custom_adapter in custom_adapters: if custom_adapter["adapter_number"] == adapter_number: custom_adapter_settings = custom_adapter break for port_number in range(0, port_by_adapter): if first_port_name and adapter_number == 0: port_name = custom_adapter_settings.get("port_name", first_port_name) port = PortFactory(port_name, segment_number, adapter_number, port_number, "ethernet", short_name=port_name) else: try: port_name = port_name_format.format( interface_number, segment_number, adapter=adapter_number, **cls._generate_replacement(interface_number, segment_number)) except (ValueError, KeyError) as e: raise aiohttp.web.HTTPConflict(text="Invalid port name format {}: {}".format(port_name_format, str(e))) port_name = custom_adapter_settings.get("port_name", port_name) port = PortFactory(port_name, segment_number, adapter_number, port_number, "ethernet") interface_number += 1 if port_segment_size: if interface_number % port_segment_size == 0: segment_number += 1 interface_number = 0 else: segment_number += 1 port.adapter_type = custom_adapter_settings.get("adapter_type", properties.get("adapter_type", None)) mac_address = custom_adapter_settings.get("mac_address") if not mac_address and "mac_address" in properties: mac_address = int_to_macaddress(macaddress_to_int(properties["mac_address"]) + adapter_number) port.mac_address = mac_address ports.append(port) if len(ports): adapter_number += 1 if "serial_adapters" in properties: for adapter_number in range(adapter_number, properties["serial_adapters"] + adapter_number): for port_number in range(0, port_by_adapter): ports.append(PortFactory("Serial{}/{}".format(segment_number, port_number), segment_number, adapter_number, port_number, "serial")) segment_number += 1 return ports @staticmethod def _generate_replacement(interface_number, segment_number): """ This will generate replacement string for {port0} => {port9} {segment0} => {segment9} """ replacements = {} for i in range(0, 9): replacements["port" + str(i)] = interface_number + i replacements["segment" + str(i)] = segment_number + i return replacements class DynamipsPortFactory: """ Create port for dynamips devices """ ADAPTER_MATRIX = { "C1700-MB-1FE": {"nb_ports": 1, "port": FastEthernetPort}, "C1700-MB-WIC1": {"nb_ports": 0, "port": None}, "C2600-MB-1E": {"nb_ports": 1, "port": EthernetPort}, "C2600-MB-1FE": {"nb_ports": 1, "port": FastEthernetPort}, "C2600-MB-2E": {"nb_ports": 2, "port": EthernetPort}, "C2600-MB-2FE": {"nb_ports": 2, "port": FastEthernetPort}, "C7200-IO-2FE": {"nb_ports": 2, "port": FastEthernetPort}, "C7200-IO-FE": {"nb_ports": 1, "port": FastEthernetPort}, "C7200-IO-GE-E": {"nb_ports": 1, "port": GigabitEthernetPort}, "GT96100-FE": {"nb_ports": 2, "port": FastEthernetPort}, "Leopard-2FE": {"nb_ports": 2, "port": FastEthernetPort}, "NM-16ESW": {"nb_ports": 16, "port": FastEthernetPort}, "NM-1E": {"nb_ports": 1, "port": EthernetPort}, "NM-1FE-TX": {"nb_ports": 1, "port": FastEthernetPort}, "NM-4E": {"nb_ports": 4, "port": EthernetPort}, "NM-4T": {"nb_ports": 4, "port": SerialPort}, "PA-2FE-TX": {"nb_ports": 2, "port": FastEthernetPort}, "PA-4E": {"nb_ports": 4, "port": EthernetPort}, "PA-4T+": {"nb_ports": 4, "port": SerialPort}, "PA-8E": {"nb_ports": 8, "port": EthernetPort}, "PA-8T": {"nb_ports": 8, "port": SerialPort}, "PA-A1": {"nb_ports": 1, "port": ATMPort}, "PA-FE-TX": {"nb_ports": 1, "port": FastEthernetPort}, "PA-GE": {"nb_ports": 1, "port": GigabitEthernetPort}, "PA-POS-OC3": {"nb_ports": 1, "port": POSPort}, } WIC_MATRIX = {"WIC-1ENET": {"nb_ports": 1, "port": EthernetPort}, "WIC-1T": {"nb_ports": 1, "port": SerialPort}, "WIC-2T": {"nb_ports": 2, "port": SerialPort} } def __new__(cls, properties): ports = [] adapter_number = 0 wic_slot = 1 wic_port_number = wic_slot * 16 display_wic_port_number = 0 for name in sorted(properties.keys()): if name.startswith("slot") and properties[name]: port_class = cls.ADAPTER_MATRIX[properties[name]]["port"] if port_class: for port_number in range(0, cls.ADAPTER_MATRIX[properties[name]]["nb_ports"]): name = "{}{}/{}".format(port_class.long_name_type(), adapter_number, port_number) port = port_class(name, adapter_number, adapter_number, port_number) port.short_name = "{}{}/{}".format(port.short_name_type, adapter_number, port_number) ports.append(port) adapter_number += 1 elif name.startswith("wic") and properties[name]: port_class = cls.WIC_MATRIX[properties[name]]["port"] if port_class: for port_number in range(0, cls.WIC_MATRIX[properties[name]]["nb_ports"]): name = "{}{}/{}".format(port_class.long_name_type(), 0, display_wic_port_number) port = port_class(name, 0, 0, wic_port_number) port.short_name = "{}{}/{}".format(port.short_name_type, 0, display_wic_port_number) ports.append(port) display_wic_port_number += 1 wic_port_number += 1 wic_slot += 1 wic_port_number = wic_slot * 16 return ports