New Dynamips integration part 1

This commit is contained in:
Jeremy committed 2015-02-09 18:24:13 -07:00
1 parent 648850c411
commit 46cbcd6132
82 files changed
+2677 -9407

No files matched your search

+611
View File
@@ -0,0 +1,611 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 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/>.
"""
Dynamips server module.
"""
import sys
import os
import base64
import tempfile
import shutil
import glob
import socket
from gns3server.config import Config
# from .hypervisor import Hypervisor
# from .hypervisor_manager import HypervisorManager
# from .dynamips_error import DynamipsError
#
# # Nodes
# from .nodes.router import Router
# from .nodes.c1700 import C1700
# from .nodes.c2600 import C2600
# from .nodes.c2691 import C2691
# from .nodes.c3600 import C3600
# from .nodes.c3725 import C3725
# from .nodes.c3745 import C3745
# from .nodes.c7200 import C7200
# from .nodes.bridge import Bridge
# from .nodes.ethernet_switch import EthernetSwitch
# from .nodes.atm_switch import ATMSwitch
# from .nodes.atm_bridge import ATMBridge
# from .nodes.frame_relay_switch import FrameRelaySwitch
# from .nodes.hub import Hub
#
# # Adapters
# from .adapters.c7200_io_2fe import C7200_IO_2FE
# from .adapters.c7200_io_fe import C7200_IO_FE
# from .adapters.c7200_io_ge_e import C7200_IO_GE_E
# from .adapters.nm_16esw import NM_16ESW
# from .adapters.nm_1e import NM_1E
# from .adapters.nm_1fe_tx import NM_1FE_TX
# from .adapters.nm_4e import NM_4E
# from .adapters.nm_4t import NM_4T
# from .adapters.pa_2fe_tx import PA_2FE_TX
# from .adapters.pa_4e import PA_4E
# from .adapters.pa_4t import PA_4T
# from .adapters.pa_8e import PA_8E
# from .adapters.pa_8t import PA_8T
# from .adapters.pa_a1 import PA_A1
# from .adapters.pa_fe_tx import PA_FE_TX
# from .adapters.pa_ge import PA_GE
# from .adapters.pa_pos_oc3 import PA_POS_OC3
# from .adapters.wic_1t import WIC_1T
# from .adapters.wic_2t import WIC_2T
# from .adapters.wic_1enet import WIC_1ENET
#
# # NIOs
# from .nios.nio_udp import NIO_UDP
# from .nios.nio_udp_auto import NIO_UDP_auto
# from .nios.nio_unix import NIO_UNIX
# from .nios.nio_vde import NIO_VDE
# from .nios.nio_tap import NIO_TAP
# from .nios.nio_generic_ethernet import NIO_GenericEthernet
# from .nios.nio_linux_ethernet import NIO_LinuxEthernet
# from .nios.nio_fifo import NIO_FIFO
# from .nios.nio_mcast import NIO_Mcast
# from .nios.nio_null import NIO_Null
#
# from .backends import vm
# from .backends import ethsw
# from .backends import ethhub
# from .backends import frsw
# from .backends import atmsw
import time
import asyncio
import logging
log = logging.getLogger(__name__)
from pkg_resources import parse_version
from ..base_manager import BaseManager
from .dynamips_error import DynamipsError
from .hypervisor import Hypervisor
from .nodes.router import Router
class Dynamips(BaseManager):
_VM_CLASS = Router
def __init__(self):
super().__init__()
self._dynamips_path = None
# FIXME: temporary
self._working_dir = "/tmp"
self._dynamips_path = "/usr/local/bin/dynamips"
def find_dynamips(self):
# look for Dynamips
dynamips_path = self.config.get_section_config("Dynamips").get("dynamips_path")
if not dynamips_path:
dynamips_path = shutil.which("dynamips")
if not dynamips_path:
raise DynamipsError("Could not find Dynamips")
if not os.path.isfile(dynamips_path):
raise DynamipsError("Dynamips {} is not accessible".format(dynamips_path))
if not os.access(dynamips_path, os.X_OK):
raise DynamipsError("Dynamips is not executable")
self._dynamips_path = dynamips_path
return dynamips_path
@asyncio.coroutine
def _wait_for_hypervisor(self, host, port, timeout=10.0):
"""
Waits for an hypervisor to be started (accepting a socket connection)
:param host: host/address to connect to the hypervisor
:param port: port to connect to the hypervisor
"""
begin = time.time()
connection_success = False
last_exception = None
while time.time() - begin < timeout:
yield from asyncio.sleep(0.01)
try:
_, writer = yield from asyncio.open_connection(host, port)
writer.close()
except OSError as e:
last_exception = e
continue
connection_success = True
break
if not connection_success:
raise DynamipsError("Couldn't connect to hypervisor on {}:{} :{}".format(host, port, last_exception))
else:
log.info("Dynamips server ready after {:.4f} seconds".format(time.time() - begin))
@asyncio.coroutine
def start_new_hypervisor(self):
"""
Creates a new Dynamips process and start it.
:returns: the new hypervisor instance
"""
try:
# let the OS find an unused port for the Dynamips hypervisor
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind(("127.0.0.1", 0))
port = sock.getsockname()[1]
except OSError as e:
raise DynamipsError("Could not find free port for the Dynamips hypervisor: {}".format(e))
hypervisor = Hypervisor(self._dynamips_path, self._working_dir, "127.0.0.1", port)
log.info("Ceating new hypervisor {}:{} with working directory {}".format(hypervisor.host, hypervisor.port, self._working_dir))
yield from hypervisor.start()
yield from self._wait_for_hypervisor("127.0.0.1", port)
log.info("Hypervisor {}:{} has successfully started".format(hypervisor.host, hypervisor.port))
yield from hypervisor.connect()
if parse_version(hypervisor.version) < parse_version('0.2.11'):
raise DynamipsError("Dynamips version must be >= 0.2.11, detected version is {}".format(hypervisor.version))
return hypervisor
# class Dynamips(IModule):
# """
# Dynamips module.
#
# :param name: module name
# :param args: arguments for the module
# :param kwargs: named arguments for the module
# """
#
# def stop(self, signum=None):
# """
# Properly stops the module.
#
# :param signum: signal number (if called by the signal handler)
# """
#
# if not sys.platform.startswith("win32"):
# self._callback.stop()
#
# # automatically save configs for all router instances
# for router_id in self._routers:
# router = self._routers[router_id]
# try:
# router.save_configs()
# except DynamipsError:
# continue
#
# # stop all Dynamips hypervisors
# if self._hypervisor_manager:
# self._hypervisor_manager.stop_all_hypervisors()
#
# self.delete_dynamips_files()
# IModule.stop(self, signum) # this will stop the I/O loop
#
# def get_device_instance(self, device_id, instance_dict):
# """
# Returns a device instance.
#
# :param device_id: device identifier
# :param instance_dict: dictionary containing the instances
#
# :returns: device instance
# """
#
# if device_id not in instance_dict:
# log.debug("device ID {} doesn't exist".format(device_id), exc_info=1)
# self.send_custom_error("Device ID {} doesn't exist".format(device_id))
# return None
# return instance_dict[device_id]
#
# def delete_dynamips_files(self):
# """
# Deletes useless Dynamips files from the working directory
# """
#
# files = glob.glob(os.path.join(self._working_dir, "dynamips", "*.ghost"))
# files += glob.glob(os.path.join(self._working_dir, "dynamips", "*_lock"))
# files += glob.glob(os.path.join(self._working_dir, "dynamips", "ilt_*"))
# files += glob.glob(os.path.join(self._working_dir, "dynamips", "c[0-9][0-9][0-9][0-9]_*_rommon_vars"))
# files += glob.glob(os.path.join(self._working_dir, "dynamips", "c[0-9][0-9][0-9][0-9]_*_ssa"))
# for file in files:
# try:
# log.debug("deleting file {}".format(file))
# os.remove(file)
# except OSError as e:
# log.warn("could not delete file {}: {}".format(file, e))
# continue
#
# @IModule.route("dynamips.reset")
# def reset(self, request=None):
# """
# Resets the module (JSON-RPC notification).
#
# :param request: JSON request (not used)
# """
#
# # automatically save configs for all router instances
# for router_id in self._routers:
# router = self._routers[router_id]
# try:
# router.save_configs()
# except DynamipsError:
# continue
#
# # stop all Dynamips hypervisors
# if self._hypervisor_manager:
# self._hypervisor_manager.stop_all_hypervisors()
#
# # resets the instance counters
# Router.reset()
# EthernetSwitch.reset()
# Hub.reset()
# FrameRelaySwitch.reset()
# ATMSwitch.reset()
# NIO_UDP.reset()
# NIO_UDP_auto.reset()
# NIO_UNIX.reset()
# NIO_VDE.reset()
# NIO_TAP.reset()
# NIO_GenericEthernet.reset()
# NIO_LinuxEthernet.reset()
# NIO_FIFO.reset()
# NIO_Mcast.reset()
# NIO_Null.reset()
#
# self._routers.clear()
# self._ethernet_switches.clear()
# self._frame_relay_switches.clear()
# self._atm_switches.clear()
#
# self.delete_dynamips_files()
#
# self._hypervisor_manager = None
# self._working_dir = self._projects_dir
# log.info("dynamips module has been reset")
#
# def start_hypervisor_manager(self):
# """
# Starts the hypervisor manager.
# """
#
# # check if Dynamips path exists
# if not os.path.isfile(self._dynamips):
# raise DynamipsError("Dynamips executable {} doesn't exist".format(self._dynamips))
#
# # check if Dynamips is executable
# if not os.access(self._dynamips, os.X_OK):
# raise DynamipsError("Dynamips {} is not executable".format(self._dynamips))
#
# workdir = os.path.join(self._working_dir, "dynamips")
# try:
# os.makedirs(workdir)
# except FileExistsError:
# pass
# except OSError as e:
# raise DynamipsError("Could not create working directory {}".format(e))
#
# # check if the working directory is writable
# if not os.access(workdir, os.W_OK):
# raise DynamipsError("Cannot write to working directory {}".format(workdir))
#
# log.info("starting the hypervisor manager with Dynamips working directory set to '{}'".format(workdir))
# self._hypervisor_manager = HypervisorManager(self._dynamips, workdir, self._host, self._console_host)
#
# for name, value in self._hypervisor_manager_settings.items():
# if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value:
# setattr(self._hypervisor_manager, name, value)
#
# @IModule.route("dynamips.settings")
# def settings(self, request):
# """
# Set or update settings.
#
# Optional request parameters:
# - path (path to the Dynamips executable)
# - working_dir (path to a working directory)
# - project_name
#
# :param request: JSON request
# """
#
# if request is None:
# self.send_param_error()
# return
#
# log.debug("received request {}".format(request))
#
# #TODO: JSON schema validation
# if not self._hypervisor_manager:
#
# if "path" in request:
# self._dynamips = request.pop("path")
#
# if "working_dir" in request:
# self._working_dir = request.pop("working_dir")
# log.info("this server is local")
# else:
# self._working_dir = os.path.join(self._projects_dir, request["project_name"])
# log.info("this server is remote with working directory path to {}".format(self._working_dir))
#
# self._hypervisor_manager_settings = request
#
# else:
# if "project_name" in request:
# # for remote server
# new_working_dir = os.path.join(self._projects_dir, request["project_name"])
#
# if self._projects_dir != self._working_dir != new_working_dir:
#
# # trick to avoid file locks by Dynamips on Windows
# if sys.platform.startswith("win"):
# self._hypervisor_manager.working_dir = tempfile.gettempdir()
#
# if not os.path.isdir(new_working_dir):
# try:
# self.delete_dynamips_files()
# shutil.move(self._working_dir, new_working_dir)
# except OSError as e:
# log.error("could not move working directory from {} to {}: {}".format(self._working_dir,
# new_working_dir,
# e))
# return
#
# elif "working_dir" in request:
# # for local server
# new_working_dir = request.pop("working_dir")
#
# try:
# self._hypervisor_manager.working_dir = new_working_dir
# except DynamipsError as e:
# log.error("could not change working directory: {}".format(e))
# return
#
# self._working_dir = new_working_dir
#
# # apply settings to the hypervisor manager
# for name, value in request.items():
# if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value:
# setattr(self._hypervisor_manager, name, value)
#
# @IModule.route("dynamips.echo")
# def echo(self, request):
# """
# Echo end point for testing purposes.
#
# :param request: JSON request
# """
#
# if request is None:
# self.send_param_error()
# else:
# log.debug("received request {}".format(request))
# self.send_response(request)
#
# def create_nio(self, node, request):
# """
# Creates a new NIO.
#
# :param node: node requesting the NIO
# :param request: the original request with the
# necessary information to create the NIO
#
# :returns: a NIO object
# """
#
# nio = None
# if request["nio"]["type"] == "nio_udp":
# lport = request["nio"]["lport"]
# rhost = request["nio"]["rhost"]
# rport = request["nio"]["rport"]
# try:
# #TODO: handle IPv6
# with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
# sock.connect((rhost, rport))
# except OSError as e:
# raise DynamipsError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
# # check if we have an allocated NIO UDP auto
# nio = node.hypervisor.get_nio_udp_auto(lport)
# if not nio:
# # otherwise create an NIO UDP
# nio = NIO_UDP(node.hypervisor, lport, rhost, rport)
# else:
# nio.connect(rhost, rport)
# elif request["nio"]["type"] == "nio_generic_ethernet":
# ethernet_device = request["nio"]["ethernet_device"]
# if sys.platform.startswith("win"):
# # replace the interface name by the GUID on Windows
# interfaces = get_windows_interfaces()
# npf_interface = None
# for interface in interfaces:
# if interface["name"] == ethernet_device:
# npf_interface = interface["id"]
# if not npf_interface:
# raise DynamipsError("Could not find interface {} on this host".format(ethernet_device))
# else:
# ethernet_device = npf_interface
# nio = NIO_GenericEthernet(node.hypervisor, ethernet_device)
# elif request["nio"]["type"] == "nio_linux_ethernet":
# if sys.platform.startswith("win"):
# raise DynamipsError("This NIO type is not supported on Windows")
# ethernet_device = request["nio"]["ethernet_device"]
# nio = NIO_LinuxEthernet(node.hypervisor, ethernet_device)
# elif request["nio"]["type"] == "nio_tap":
# tap_device = request["nio"]["tap_device"]
# nio = NIO_TAP(node.hypervisor, tap_device)
# elif request["nio"]["type"] == "nio_unix":
# local_file = request["nio"]["local_file"]
# remote_file = request["nio"]["remote_file"]
# nio = NIO_UNIX(node.hypervisor, local_file, remote_file)
# elif request["nio"]["type"] == "nio_vde":
# control_file = request["nio"]["control_file"]
# local_file = request["nio"]["local_file"]
# nio = NIO_VDE(node.hypervisor, control_file, local_file)
# elif request["nio"]["type"] == "nio_null":
# nio = NIO_Null(node.hypervisor)
# return nio
#
# def allocate_udp_port(self, node):
# """
# Allocates a UDP port in order to create an UDP NIO.
#
# :param node: the node that needs to allocate an UDP port
#
# :returns: dictionary with the allocated host/port info
# """
#
# port = node.hypervisor.allocate_udp_port()
# host = node.hypervisor.host
#
# log.info("{} [id={}] has allocated UDP port {} with host {}".format(node.name,
# node.id,
# port,
# host))
# response = {"lport": port}
# return response
#
# def set_ghost_ios(self, router):
# """
# Manages Ghost IOS support.
#
# :param router: Router instance
# """
#
# if not router.mmap:
# raise DynamipsError("mmap support is required to enable ghost IOS support")
#
# ghost_instance = router.formatted_ghost_file()
# all_ghosts = []
#
# # search of an existing ghost instance across all hypervisors
# for hypervisor in self._hypervisor_manager.hypervisors:
# all_ghosts.extend(hypervisor.ghosts)
#
# if ghost_instance not in all_ghosts:
# # create a new ghost IOS instance
# ghost = Router(router.hypervisor, "ghost-" + ghost_instance, router.platform, ghost_flag=True)
# ghost.image = router.image
# # for 7200s, the NPE must be set when using an NPE-G2.
# if router.platform == "c7200":
# ghost.npe = router.npe
# ghost.ghost_status = 1
# ghost.ghost_file = ghost_instance
# ghost.ram = router.ram
# try:
# ghost.start()
# ghost.stop()
# except DynamipsError:
# raise
# finally:
# ghost.clean_delete()
#
# if router.ghost_file != ghost_instance:
# # set the ghost file to the router
# router.ghost_status = 2
# router.ghost_file = ghost_instance
#
# def create_config_from_file(self, local_base_config, router, destination_config_path):
# """
# Creates a config file from a local base config
#
# :param local_base_config: path the a local base config
# :param router: router instance
# :param destination_config_path: path to the destination config file
#
# :returns: relative path to the created config file
# """
#
# log.info("creating config file {} from {}".format(destination_config_path, local_base_config))
# config_path = destination_config_path
# config_dir = os.path.dirname(destination_config_path)
# try:
# os.makedirs(config_dir)
# except FileExistsError:
# pass
# except OSError as e:
# raise DynamipsError("Could not create configs directory: {}".format(e))
#
# try:
# with open(local_base_config, "r", errors="replace") as f:
# config = f.read()
# with open(config_path, "w") as f:
# config = "!\n" + config.replace("\r", "")
# config = config.replace('%h', router.name)
# f.write(config)
# except OSError as e:
# raise DynamipsError("Could not save the configuration from {} to {}: {}".format(local_base_config, config_path, e))
# return "configs" + os.sep + os.path.basename(config_path)
#
# def create_config_from_base64(self, config_base64, router, destination_config_path):
# """
# Creates a config file from a base64 encoded config.
#
# :param config_base64: base64 encoded config
# :param router: router instance
# :param destination_config_path: path to the destination config file
#
# :returns: relative path to the created config file
# """
#
# log.info("creating config file {} from base64".format(destination_config_path))
# config = base64.decodebytes(config_base64.encode("utf-8")).decode("utf-8")
# config = "!\n" + config.replace("\r", "")
# config = config.replace('%h', router.name)
# config_dir = os.path.dirname(destination_config_path)
# try:
# os.makedirs(config_dir)
# except FileExistsError:
# pass
# except OSError as e:
# raise DynamipsError("Could not create configs directory: {}".format(e))
#
# config_path = destination_config_path
# try:
# with open(config_path, "w") as f:
# log.info("saving startup-config to {}".format(config_path))
# f.write(config)
# except OSError as e:
# raise DynamipsError("Could not save the configuration {}: {}".format(config_path, e))
# return "configs" + os.sep + os.path.basename(config_path)
Whitespace-only changes.
@@ -0,0 +1,166 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
class Adapter(object):
"""
Base class for adapters.
:param interfaces: number of interfaces supported by this adapter.
:param wics: number of wics supported by this adapter.
"""
def __init__(self, interfaces=0, wics=0):
self._interfaces = interfaces
self._ports = {}
for port_id in range(0, interfaces):
self._ports[port_id] = None
self._wics = wics * [None]
def removable(self):
"""
Returns True if the adapter can be removed from a slot
and False if not.
:returns: boolean
"""
return True
def port_exists(self, port_id):
"""
Checks if a port exists on this adapter.
:returns: True is the port exists,
False otherwise.
"""
if port_id in self._ports:
return True
return False
def wic_slot_available(self, wic_slot_id):
"""
Checks if a WIC slot is available
:returns: True is the WIC slot is available,
False otherwise.
"""
if self._wics[wic_slot_id] is None:
return True
return False
def install_wic(self, wic_slot_id, wic):
"""
Installs a WIC on this adapter.
:param wic_slot_id: WIC slot ID (integer)
:param wic: WIC instance
"""
self._wics[wic_slot_id] = wic
# Dynamips WICs ports start on a multiple of 16 + port number
# WIC1 port 1 = 16, WIC1 port 2 = 17
# WIC2 port 1 = 32, WIC2 port 2 = 33
# WIC3 port 1 = 48, WIC3 port 2 = 49
base = 16 * (wic_slot_id + 1)
for wic_port in range(0, wic.interfaces):
port_id = base + wic_port
self._ports[port_id] = None
def uninstall_wic(self, wic_slot_id):
"""
Removes a WIC from this adapter.
:param wic_slot_id: WIC slot ID (integer)
"""
wic = self._wics[wic_slot_id]
# Dynamips WICs ports start on a multiple of 16 + port number
# WIC1 port 1 = 16, WIC1 port 2 = 17
# WIC2 port 1 = 32, WIC2 port 2 = 33
# WIC3 port 1 = 48, WIC3 port 2 = 49
base = 16 * (wic_slot_id + 1)
for wic_port in range(0, wic.interfaces):
port_id = base + wic_port
del self._ports[port_id]
self._wics[wic_slot_id] = None
def add_nio(self, port_id, nio):
"""
Adds a NIO to a port on this adapter.
:param port_id: port ID (integer)
:param nio: NIO instance
"""
self._ports[port_id] = nio
def remove_nio(self, port_id):
"""
Removes a NIO from a port on this adapter.
:param port_id: port ID (integer)
"""
self._ports[port_id] = None
def get_nio(self, port_id):
"""
Returns the NIO assigned to a port.
:params port_id: port ID (integer)
:returns: NIO instance
"""
return self._ports[port_id]
@property
def ports(self):
"""
Returns port to NIO mapping
:returns: dictionary port -> NIO
"""
return self._ports
@property
def interfaces(self):
"""
Returns the number of interfaces supported by this adapter.
:returns: number of interfaces
"""
return self._interfaces
@property
def wics(self):
"""
Returns the wics adapters inserted in this adapter.
:returns: list WIC instances
"""
return self._wics
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class C1700_MB_1FE(Adapter):
"""
Integrated 1 port FastEthernet adapter for c1700 platform.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1, wics=2)
def __str__(self):
return "C1700-MB-1FE"
def removable(self):
return False
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class C1700_MB_WIC1(Adapter):
"""
Fake module to provide a placeholder for slot 1 interfaces when WICs
are inserted into WIC slot 1.
"""
def __init__(self):
Adapter.__init__(self, interfaces=0, wics=2)
def __str__(self):
return "C1700-MB-WIC1"
def removable(self):
return False
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class C2600_MB_1E(Adapter):
"""
Integrated 1 port Ethernet adapter for the c2600 platform.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1, wics=3)
def __str__(self):
return "C2600-MB-1E"
def removable(self):
return False
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class C2600_MB_1FE(Adapter):
"""
Integrated 1 port FastEthernet adapter for the c2600 platform.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1, wics=3)
self._interfaces = 1
def __str__(self):
return "C2600-MB-1FE"
def removable(self):
return False
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class C2600_MB_2E(Adapter):
"""
Integrated 2 port Ethernet adapter for the c2600 platform.
"""
def __init__(self):
Adapter.__init__(self, interfaces=2, wics=3)
def __str__(self):
return "C2600-MB-2E"
def removable(self):
return False
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class C2600_MB_2FE(Adapter):
"""
Integrated 2 port FastEthernet adapter for the c2600 platform.
"""
def __init__(self):
Adapter.__init__(self, interfaces=2, wics=3)
def __str__(self):
return "C2600-MB-2FE"
def removable(self):
return False
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class C7200_IO_2FE(Adapter):
"""
C7200-IO-2FE FastEthernet Input/Ouput controller.
"""
def __init__(self):
Adapter.__init__(self, interfaces=2)
def __str__(self):
return "C7200-IO-2FE"
def removable(self):
return False
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class C7200_IO_FE(Adapter):
"""
C7200-IO-FE FastEthernet Input/Ouput controller.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1)
def __str__(self):
return "C7200-IO-FE"
def removable(self):
return False
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class C7200_IO_GE_E(Adapter):
"""
C7200-IO-GE-E GigabitEthernet Input/Ouput controller.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1)
def __str__(self):
return "C7200-IO-GE-E"
def removable(self):
return False
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class GT96100_FE(Adapter):
def __init__(self):
Adapter.__init__(self, interfaces=2, wics=3)
def __str__(self):
return "GT96100-FE"
def removable(self):
return False
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class Leopard_2FE(Adapter):
"""
Integrated 2 port FastEthernet adapter for c3660 router.
"""
def __init__(self):
Adapter.__init__(self, interfaces=2)
self._interfaces = 2
def __str__(self):
return "Leopard-2FE"
def removable(self):
return False
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class NM_16ESW(Adapter):
"""
NM-16ESW FastEthernet network module.
"""
def __init__(self):
Adapter.__init__(self, interfaces=16)
def __str__(self):
return "NM-16ESW"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class NM_1E(Adapter):
"""
NM-1E Ethernet network module.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1)
def __str__(self):
return "NM-1E"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class NM_1FE_TX(Adapter):
"""
NM-1FE-TX FastEthernet network module.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1)
def __str__(self):
return "NM-1FE-TX"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class NM_4E(Adapter):
"""
NM-4E Ethernet network module.
"""
def __init__(self):
Adapter.__init__(self, interfaces=4)
def __str__(self):
return "NM-4E"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class NM_4T(Adapter):
"""
NM-4T Serial network module.
"""
def __init__(self):
Adapter.__init__(self, interfaces=4)
def __str__(self):
return "NM-4T"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class PA_2FE_TX(Adapter):
"""
PA-2FE-TX FastEthernet port adapter.
"""
def __init__(self):
Adapter.__init__(self, interfaces=2)
def __str__(self):
return "PA-2FE-TX"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class PA_4E(Adapter):
"""
PA-4E Ethernet port adapter.
"""
def __init__(self):
Adapter.__init__(self, interfaces=4)
def __str__(self):
return "PA-4E"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class PA_4T(Adapter):
"""
PA-4T+ Serial port adapter.
"""
def __init__(self):
Adapter.__init__(self, interfaces=4)
def __str__(self):
return "PA-4T+"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class PA_8E(Adapter):
"""
PA-8E Ethernet port adapter.
"""
def __init__(self):
Adapter.__init__(self, interfaces=8)
def __str__(self):
return "PA-8E"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class PA_8T(Adapter):
"""
PA-8T Serial port adapter.
"""
def __init__(self):
Adapter.__init__(self, interfaces=8)
def __str__(self):
return "PA-8T"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class PA_A1(Adapter):
"""
PA-A1 ATM port adapter.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1)
def __str__(self):
return "PA-A1"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class PA_FE_TX(Adapter):
"""
PA-FE-TX FastEthernet port adapter.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1)
def __str__(self):
return "PA-FE-TX"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class PA_GE(Adapter):
"""
PA-GE GigabitEthernet port adapter.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1)
def __str__(self):
return "PA-GE"
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 .adapter import Adapter
class PA_POS_OC3(Adapter):
"""
PA-POS-OC3 port adapter.
"""
def __init__(self):
Adapter.__init__(self, interfaces=1)
def __str__(self):
return "PA-POS-OC3"
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
class WIC_1ENET(object):
"""
WIC-1ENET Ethernet
"""
def __init__(self):
self._interfaces = 2
def __str__(self):
return "WIC-1ENET"
@property
def interfaces(self):
"""
Returns the number of interfaces supported by this WIC.
:returns: number of interfaces
"""
return self._interfaces
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
class WIC_1T(object):
"""
WIC-1T Serial
"""
def __init__(self):
self._interfaces = 1
def __str__(self):
return "WIC-1T"
@property
def interfaces(self):
"""
Returns the number of interfaces supported by this WIC.
:returns: number of interfaces
"""
return self._interfaces
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
class WIC_2T(object):
"""
WIC-2T Serial
"""
def __init__(self):
self._interfaces = 2
def __str__(self):
return "WIC-2T"
@property
def interfaces(self):
"""
Returns the number of interfaces supported by this WIC.
:returns: number of interfaces
"""
return self._interfaces
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 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/>.
"""
Custom exceptions for Dynamips module.
"""
class DynamipsError(Exception):
def __init__(self, message, original_exception=None):
Exception.__init__(self, message)
if isinstance(message, Exception):
message = str(message)
self._message = message
self._original_exception = original_exception
def __repr__(self):
return self._message
def __str__(self):
return self._message
@@ -0,0 +1,502 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 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/>.
"""
Interface for Dynamips hypervisor management module ("hypervisor")
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L46
"""
import socket
import re
import logging
import asyncio
from .dynamips_error import DynamipsError
from .nios.nio_udp_auto import NIO_UDP_auto
log = logging.getLogger(__name__)
class DynamipsHypervisor:
"""
Creates a new connection to a Dynamips server (also called hypervisor)
:param working_dir: working directory
:param host: the hostname or ip address string of the Dynamips server
:param port: the tcp port integer (defaults to 7200)
:param timeout: timeout integer for how long to wait for a response to commands sent to the
hypervisor (defaults to 30 seconds)
"""
# Used to parse Dynamips response codes
error_re = re.compile(r"""^2[0-9]{2}-""")
success_re = re.compile(r"""^1[0-9]{2}\s{1}""")
def __init__(self, working_dir, host, port=7200, timeout=30.0):
self._host = host
self._port = port
self._devices = []
self._ghosts = {}
self._jitsharing_groups = {}
self._working_dir = working_dir
# self._console_start_port_range = 2001
# self._console_end_port_range = 2500
# self._aux_start_port_range = 2501
# self._aux_end_port_range = 3000
# self._udp_start_port_range = 10001
# self._udp_end_port_range = 20000
self._nio_udp_auto_instances = {}
self._version = "N/A"
self._timeout = timeout
self._uuid = None
self._reader = None
self._writer = None
@asyncio.coroutine
def connect(self):
"""
Connects to the hypervisor.
"""
# connect to a local address by default
# if listening to all addresses (IPv4 or IPv6)
if self._host == "0.0.0.0":
host = "127.0.0.1"
elif self._host == "::":
host = "::1"
else:
host = self._host
try:
self._reader, self._writer = yield from asyncio.wait_for(asyncio.open_connection(host, self._port), timeout=self._timeout)
except OSError as e:
raise DynamipsError("Could not connect to hypervisor {}:{} {}".format(host, self._port, e))
except asyncio.TimeoutError:
raise DynamipsError("Timeout error while connecting to hypervisor {}:{}".format(host, self._port))
try:
version = yield from self.send("hypervisor version")
self._version = version[0].split("-", 1)[0]
except IndexError:
self._version = "Unknown"
self._uuid = yield from self.send("hypervisor uuid")
# this forces to send the working dir to Dynamips
yield from self.set_working_dir(self._working_dir)
@property
def version(self):
"""
Returns Dynamips version.
:returns: version string
"""
return self._version
@asyncio.coroutine
def close(self):
"""
Closes the connection to this hypervisor (but leave it running).
"""
yield from self.send("hypervisor close")
self._writer.close()
self._reader, self._writer = None
@asyncio.coroutine
def stop(self):
"""
Stops this hypervisor (will no longer run).
"""
yield from self.send("hypervisor stop")
self._writer.close()
self._reader, self._writer = None
self._nio_udp_auto_instances.clear()
@asyncio.coroutine
def reset(self):
"""
Resets this hypervisor (used to get an empty configuration).
"""
yield from self.send("hypervisor reset")
self._nio_udp_auto_instances.clear()
@asyncio.coroutine
def set_working_dir(self, working_dir):
"""
Sets the working directory for this hypervisor.
:param working_dir: path to the working directory
"""
# encase working_dir in quotes to protect spaces in the path
yield from self.send("hypervisor working_dir {}".format('"' + working_dir + '"'))
self._working_dir = working_dir
log.debug("Working directory set to {}".format(self._working_dir))
@property
def working_dir(self):
"""
Returns current working directory
:returns: path to the working directory
"""
return self._working_dir
@property
def uuid(self):
"""
Returns this hypervisor UUID.
:Returns: uuid string
"""
return self._uuid
@property
def devices(self):
"""
Returns the list of devices managed by this hypervisor instance.
:returns: a list of device instances
"""
return self._devices
# @devices.setter
# def devices(self, devices):
# """
# Sets the list of devices managed by this hypervisor instance.
# This method is for internal use.
#
# :param devices: a list of device objects
# """
#
# self._devices = devices
# @property
# def console_start_port_range(self):
# """
# Returns the console start port range value
#
# :returns: console start port range value (integer)
# """
#
# return self._console_start_port_range
# @console_start_port_range.setter
# def console_start_port_range(self, console_start_port_range):
# """
# Set a new console start port range value
#
# :param console_start_port_range: console start port range value (integer)
# """
#
# self._console_start_port_range = console_start_port_range
#
# @property
# def console_end_port_range(self):
# """
# Returns the console end port range value
#
# :returns: console end port range value (integer)
# """
#
# return self._console_end_port_range
#
# @console_end_port_range.setter
# def console_end_port_range(self, console_end_port_range):
# """
# Set a new console end port range value
#
# :param console_end_port_range: console end port range value (integer)
# """
#
# self._console_end_port_range = console_end_port_range
# @property
# def aux_start_port_range(self):
# """
# Returns the auxiliary console start port range value
#
# :returns: auxiliary console start port range value (integer)
# """
#
# return self._aux_start_port_range
#
# @aux_start_port_range.setter
# def aux_start_port_range(self, aux_start_port_range):
# """
# Sets a new auxiliary console start port range value
#
# :param aux_start_port_range: auxiliary console start port range value (integer)
# """
#
# self._aux_start_port_range = aux_start_port_range
#
# @property
# def aux_end_port_range(self):
# """
# Returns the auxiliary console end port range value
#
# :returns: auxiliary console end port range value (integer)
# """
#
# return self._aux_end_port_range
#
# @aux_end_port_range.setter
# def aux_end_port_range(self, aux_end_port_range):
# """
# Sets a new auxiliary console end port range value
#
# :param aux_end_port_range: auxiliary console end port range value (integer)
# """
#
# self._aux_end_port_range = aux_end_port_range
# @property
# def udp_start_port_range(self):
# """
# Returns the UDP start port range value
#
# :returns: UDP start port range value (integer)
# """
#
# return self._udp_start_port_range
#
# @udp_start_port_range.setter
# def udp_start_port_range(self, udp_start_port_range):
# """
# Sets a new UDP start port range value
#
# :param udp_start_port_range: UDP start port range value (integer)
# """
#
# self._udp_start_port_range = udp_start_port_range
#
# @property
# def udp_end_port_range(self):
# """
# Returns the UDP end port range value
#
# :returns: UDP end port range value (integer)
# """
#
# return self._udp_end_port_range
#
# @udp_end_port_range.setter
# def udp_end_port_range(self, udp_end_port_range):
# """
# Sets an new UDP end port range value
#
# :param udp_end_port_range: UDP end port range value (integer)
# """
#
# self._udp_end_port_range = udp_end_port_range
@property
def ghosts(self):
"""
Returns a list of the ghosts hosted by this hypervisor.
:returns: Ghosts dict (image_name -> device)
"""
return self._ghosts
def add_ghost(self, image_name, router):
"""
Adds a ghost name to the list of ghosts created on this hypervisor.
:param image_name: name of the ghost image
:param router: Router instance
"""
self._ghosts[image_name] = router
@property
def jitsharing_groups(self):
"""
Returns a list of the JIT sharing groups hosted by this hypervisor.
:returns: JIT sharing groups dict (image_name -> group number)
"""
return self._jitsharing_groups
def add_jitsharing_group(self, image_name, group_number):
"""
Adds a JIT blocks sharing group name to the list of groups created on this hypervisor.
:param image_name: name of the ghost image
:param group_number: group (integer)
"""
self._jitsharing_groups[image_name] = group_number
@property
def port(self):
"""
Returns the port used to start the hypervisor.
:returns: port number (integer)
"""
return self._port
@port.setter
def port(self, port):
"""
Sets the port used to start the hypervisor.
:param port: port number (integer)
"""
self._port = port
@property
def host(self):
"""
Returns the host (binding) used to start the hypervisor.
:returns: host/address (string)
"""
return self._host
@host.setter
def host(self, host):
"""
Sets the host (binding) used to start the hypervisor.
:param host: host/address (string)
"""
self._host = host
def get_nio_udp_auto(self, port):
"""
Returns an allocated NIO UDP auto instance.
:returns: NIO UDP auto instance
"""
if port in self._nio_udp_auto_instances:
return self._nio_udp_auto_instances.pop(port)
else:
return None
def allocate_udp_port(self):
"""
Allocates a new UDP port for creating an UDP NIO Auto.
:returns: port number (integer)
"""
# use Dynamips's NIO UDP auto back-end.
nio = NIO_UDP_auto(self, self._host, self._udp_start_port_range, self._udp_end_port_range)
self._nio_udp_auto_instances[nio.lport] = nio
allocated_port = nio.lport
return allocated_port
@asyncio.coroutine
def send(self, command):
"""
Sends commands to this hypervisor.
:param command: a Dynamips hypervisor command
:returns: results as a list
"""
# Dynamips responses are of the form:
# 1xx yyyyyy\r\n
# 1xx yyyyyy\r\n
# ...
# 100-yyyy\r\n
# or
# 2xx-yyyy\r\n
#
# Where 1xx is a code from 100-199 for a success or 200-299 for an error
# The result might be multiple lines and might be less than the buffer size
# but still have more data. The only thing we know for sure is the last line
# will begin with '100-' or a '2xx-' and end with '\r\n'
if self._writer is None or self._reader is None:
raise DynamipsError("Not connected")
try:
command = command.strip() + '\n'
log.debug("sending {}".format(command))
self._writer.write(command.encode())
except OSError as e:
raise DynamipsError("Lost communication with {host}:{port} :{error}, Dynamips process running: {run}"
.format(host=self._host, port=self._port, error=e, run=self.is_running()))
# Now retrieve the result
data = []
buf = ''
while True:
try:
chunk = yield from self._reader.read(1024) # match to Dynamips' buffer size
buf += chunk.decode()
except OSError as e:
raise DynamipsError("Communication timed out with {host}:{port} :{error}, Dynamips process running: {run}"
.format(host=self._host, port=self._port, error=e, run=self.is_running()))
# If the buffer doesn't end in '\n' then we can't be done
try:
if buf[-1] != '\n':
continue
except IndexError:
raise DynamipsError("Could not communicate with {host}:{port}, Dynamips process running: {run}"
.format(host=self._host, port=self._port, run=self.is_running()))
data += buf.split('\r\n')
if data[-1] == '':
data.pop()
buf = ''
if len(data) == 0:
raise DynamipsError("no data returned from {host}:{port}, Dynamips process running: {run}"
.format(host=self._host, port=self._port, run=self.is_running()))
# Does it contain an error code?
if self.error_re.search(data[-1]):
raise DynamipsError(data[-1][4:])
# Or does the last line begin with '100-'? Then we are done!
if data[-1][:4] == '100-':
data[-1] = data[-1][4:]
if data[-1] == 'OK':
data.pop()
break
# Remove success responses codes
for index in range(len(data)):
if self.success_re.search(data[index]):
data[index] = data[index][4:]
log.debug("returned result {}".format(data))
return data
+188
View File
@@ -0,0 +1,188 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 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/>.
"""
Represents a Dynamips hypervisor and starts/stops the associated Dynamips process.
"""
import os
import subprocess
import tempfile
import asyncio
from .dynamips_hypervisor import DynamipsHypervisor
from .dynamips_error import DynamipsError
import logging
log = logging.getLogger(__name__)
class Hypervisor(DynamipsHypervisor):
"""
Hypervisor.
:param path: path to Dynamips executable
:param working_dir: working directory
:param port: port for this hypervisor
:param host: host/address for this hypervisor
"""
_instance_count = 0
def __init__(self, path, working_dir, host, port):
DynamipsHypervisor.__init__(self, working_dir, host, port)
# create an unique ID
self._id = Hypervisor._instance_count
Hypervisor._instance_count += 1
self._path = path
self._command = []
self._process = None
self._stdout_file = ""
self._started = False
@property
def id(self):
"""
Returns the unique ID for this hypervisor.
:returns: id (integer)
"""
return self._id
@property
def started(self):
"""
Returns either this hypervisor has been started or not.
:returns: boolean
"""
return self._started
@property
def path(self):
"""
Returns the path to the Dynamips executable.
:returns: path to Dynamips
"""
return self._path
@path.setter
def path(self, path):
"""
Sets the path to the Dynamips executable.
:param path: path to Dynamips
"""
self._path = path
@asyncio.coroutine
def start(self):
"""
Starts the Dynamips hypervisor process.
"""
self._command = self._build_command()
try:
log.info("Starting Dynamips: {}".format(self._command))
with tempfile.NamedTemporaryFile(delete=False) as fd:
self._stdout_file = fd.name
log.info("Dynamips process logging to {}".format(fd.name))
self._process = yield from asyncio.create_subprocess_exec(*self._command,
stdout=fd,
stderr=subprocess.STDOUT,
cwd=self._working_dir)
log.info("Dynamips process started PID={}".format(self._process.pid))
self._started = True
except (OSError, subprocess.SubprocessError) as e:
log.error("Could not start Dynamips: {}".format(e))
raise DynamipsError("Could not start Dynamips: {}".format(e))
@asyncio.coroutine
def stop(self):
"""
Stops the Dynamips hypervisor process.
"""
if self.is_running():
log.info("Stopping Dynamips process PID={}".format(self._process.pid))
DynamipsHypervisor.stop(self)
# give some time for the hypervisor to properly stop.
# time to delete UNIX NIOs for instance.
yield from asyncio.sleep(0.01)
try:
yield from asyncio.wait_for(self._process.wait(), timeout=3)
except asyncio.TimeoutError:
self._process.kill()
if self._process.returncode is None:
log.warn("Dynamips process {} is still running".format(self._process.pid))
if self._stdout_file and os.access(self._stdout_file, os.W_OK):
try:
os.remove(self._stdout_file)
except OSError as e:
log.warning("could not delete temporary Dynamips log file: {}".format(e))
self._started = False
def read_stdout(self):
"""
Reads the standard output of the Dynamips process.
Only use when the process has been stopped or has crashed.
"""
output = ""
if self._stdout_file and os.access(self._stdout_file, os.R_OK):
try:
with open(self._stdout_file, errors="replace") as file:
output = file.read()
except OSError as e:
log.warn("could not read {}: {}".format(self._stdout_file, e))
return output
def is_running(self):
"""
Checks if the process is running
:returns: True or False
"""
if self._process and self._process.returncode is None:
return True
return False
def _build_command(self):
"""
Command to start the Dynamips hypervisor process.
(to be passed to subprocess.Popen())
"""
command = [self._path]
command.extend(["-N1"]) # use instance IDs for filenames
command.extend(["-l", "dynamips_log_{}.txt".format(self._port)]) # log file
if self._host != "0.0.0.0" and self._host != "::":
command.extend(["-H", "{}:{}".format(self._host, self._port)])
else:
command.extend(["-H", str(self._port)])
return command
Whitespace-only changes.
+255
View File
@@ -0,0 +1,255 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Base interface for Dynamips Network Input/Output (NIO) module ("nio").
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L451
"""
import asyncio
from ..dynamips_error import DynamipsError
import logging
log = logging.getLogger(__name__)
class NIO:
"""
Base NIO class
:param hypervisor: Dynamips hypervisor instance
"""
def __init__(self, name, hypervisor):
self._hypervisor = hypervisor
self._name = None
self._bandwidth = None # no bandwidth constraint by default
self._input_filter = None # no input filter applied by default
self._output_filter = None # no output filter applied by default
self._input_filter_options = None # no input filter options by default
self._output_filter_options = None # no output filter options by default
self._dynamips_direction = {"in": 0, "out": 1, "both": 2}
@asyncio.coroutine
def list(self):
"""
Returns all NIOs.
:returns: NIO list
"""
nio_list = yield from self._hypervisor.send("nio list")
return nio_list
@asyncio.coroutine
def delete(self):
"""
Deletes this NIO.
"""
if self._input_filter or self._output_filter:
yield from self.unbind_filter("both")
yield from self._hypervisor.send("nio delete {}".format(self._name))
log.info("NIO {name} has been deleted".format(name=self._name))
@asyncio.coroutine
def rename(self, new_name):
"""
Renames this NIO
:param new_name: new NIO name
"""
yield from self._hypervisor.send("nio rename {name} {new_name}".format(name=self._name, new_name=new_name))
log.info("NIO {name} renamed to {new_name}".format(name=self._name, new_name=new_name))
self._name = new_name
@asyncio.coroutine
def debug(self, debug):
"""
Enables/Disables debugging for this NIO.
:param debug: debug value (0 = disable, enable = 1)
"""
yield from self._hypervisor.send("nio set_debug {name} {debug}".format(name=self._name, debug=debug))
@asyncio.coroutine
def bind_filter(self, direction, filter_name):
"""
Adds a packet filter to this NIO.
Filter "freq_drop" drops packets.
Filter "capture" captures packets.
:param direction: "in", "out" or "both"
:param filter_name: name of the filter to apply
"""
if direction not in self._dynamips_direction:
raise DynamipsError("Unknown direction {} to bind filter {}:".format(direction, filter_name))
dynamips_direction = self._dynamips_direction[direction]
yield from self._hypervisor.send("nio bind_filter {name} {direction} {filter}".format(name=self._name,
direction=dynamips_direction,
filter=filter_name))
if direction == "in":
self._input_filter = filter_name
elif direction == "out":
self._output_filter = filter_name
elif direction == "both":
self._input_filter = filter_name
self._output_filter = filter_name
@asyncio.coroutine
def unbind_filter(self, direction):
"""
Removes packet filter for this NIO.
:param direction: "in", "out" or "both"
"""
if direction not in self._dynamips_direction:
raise DynamipsError("Unknown direction {} to unbind filter:".format(direction))
dynamips_direction = self._dynamips_direction[direction]
yield from self._hypervisor.send("nio unbind_filter {name} {direction}".format(name=self._name,
direction=dynamips_direction))
if direction == "in":
self._input_filter = None
elif direction == "out":
self._output_filter = None
elif direction == "both":
self._input_filter = None
self._output_filter = None
@asyncio.coroutine
def setup_filter(self, direction, options):
"""
Setups a packet filter bound with this NIO.
Filter "freq_drop" has 1 argument "<frequency>". It will drop
everything with a -1 frequency, drop every Nth packet with a
positive frequency, or drop nothing.
Filter "capture" has 2 arguments "<link_type_name> <output_file>".
It will capture packets to the target output file. The link type
name is a case-insensitive DLT_ name from the PCAP library
constants with the DLT_ part removed.See http://www.tcpdump.org/linktypes.html
for a list of all available DLT values.
:param direction: "in", "out" or "both"
:param options: options for the packet filter (string)
"""
if direction not in self._dynamips_direction:
raise DynamipsError("Unknown direction {} to setup filter:".format(direction))
dynamips_direction = self._dynamips_direction[direction]
yield from self._hypervisor.send("nio setup_filter {name} {direction} {options}".format(name=self._name,
direction=dynamips_direction,
options=options))
if direction == "in":
self._input_filter_options = options
elif direction == "out":
self._output_filter_options = options
elif direction == "both":
self._input_filter_options = options
self._output_filter_options = options
@property
def input_filter(self):
"""
Returns the input packet filter for this NIO.
:returns: tuple (filter name, filter options)
"""
return self._input_filter, self._input_filter_options
@property
def output_filter(self):
"""
Returns the output packet filter for this NIO.
:returns: tuple (filter name, filter options)
"""
return self._output_filter, self._output_filter_options
@asyncio.coroutine
def get_stats(self):
"""
Gets statistics for this NIO.
:returns: NIO statistics (string with packets in, packets out, bytes in, bytes out)
"""
stats = yield from self._hypervisor.send("nio get_stats {}".format(self._name))
return stats[0]
@asyncio.coroutine
def reset_stats(self):
"""
Resets statistics for this NIO.
"""
yield from self._hypervisor.send("nio reset_stats {}".format(self._name))
@property
def bandwidth(self):
"""
Returns the bandwidth constraint for this NIO.
:returns: bandwidth integer value (in Kb/s)
"""
return self._bandwidth
@asyncio.coroutine
def set_bandwidth(self, bandwidth):
"""
Sets bandwidth constraint.
:param bandwidth: bandwidth integer value (in Kb/s)
"""
yield from self._hypervisor.send("nio set_bandwidth {name} {bandwidth}".format(name=self._name, bandwidth=bandwidth))
self._bandwidth = bandwidth
def __str__(self):
"""
NIO string representation.
:returns: NIO name
"""
return self._name
@property
def name(self):
"""
Returns the NIO name.
:returns: NIO name
"""
return self._name
@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for FIFO NIOs.
"""
import asyncio
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_FIFO(NIO):
"""
Dynamips FIFO NIO.
:param hypervisor: Dynamips hypervisor instance
"""
_instance_count = 0
def __init__(self, hypervisor):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_FIFO._instance_count
NIO_FIFO._instance_count += 1
self._name = 'nio_fifo' + str(self._id)
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@asyncio.coroutine
def create(self):
yield from self._hypervisor.send("nio create_fifo {}".format(self._name))
log.info("NIO FIFO {name} created.".format(name=self._name))
@asyncio.coroutine
def crossconnect(self, nio):
"""
Establishes a cross-connect between this FIFO NIO and another one.
:param nio: FIFO NIO instance
"""
yield from self._hypervisor.send("nio crossconnect_fifo {name} {nio}".format(name=self._name,
nio=nio))
log.info("NIO FIFO {name} crossconnected with {nio_name}.".format(name=self._name, nio_name=nio.name))
@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for generic Ethernet NIOs (PCAP library).
"""
import asyncio
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_GenericEthernet(NIO):
"""
Dynamips generic Ethernet NIO.
:param hypervisor: Dynamips hypervisor instance
:param ethernet_device: Ethernet device name (e.g. eth0)
"""
_instance_count = 0
def __init__(self, hypervisor, ethernet_device):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_GenericEthernet._instance_count
NIO_GenericEthernet._instance_count += 1
self._name = 'nio_gen_eth' + str(self._id)
self._ethernet_device = ethernet_device
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@asyncio.coroutine
def create(self):
yield from self._hypervisor.send("nio create_gen_eth {name} {eth_device}".format(name=self._name,
eth_device=self._ethernet_device))
log.info("NIO Generic Ethernet {name} created with device {device}".format(name=self._name,
device=self._ethernet_device))
@property
def ethernet_device(self):
"""
Returns the Ethernet device used by this NIO.
:returns: the Ethernet device name
"""
return self._ethernet_device
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for Linux Ethernet NIOs (Linux only).
"""
import asyncio
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_LinuxEthernet(NIO):
"""
Dynamips Linux Ethernet NIO.
:param hypervisor: Dynamips hypervisor instance
:param ethernet_device: Ethernet device name (e.g. eth0)
"""
_instance_count = 0
def __init__(self, hypervisor, ethernet_device):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_LinuxEthernet._instance_count
NIO_LinuxEthernet._instance_count += 1
self._name = 'nio_linux_eth' + str(self._id)
self._ethernet_device = ethernet_device
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@asyncio.coroutine
def create(self):
yield from self._hypervisor.send("nio create_linux_eth {name} {eth_device}".format(name=self._name,
eth_device=self._ethernet_device))
log.info("NIO Linux Ethernet {name} created with device {device}".format(name=self._name,
device=self._ethernet_device))
@property
def ethernet_device(self):
"""
Returns the Ethernet device used by this NIO.
:returns: the Ethernet device name
"""
return self._ethernet_device
@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for multicast NIOs.
"""
import asyncio
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_Mcast(NIO):
"""
Dynamips Linux Ethernet NIO.
:param hypervisor: Dynamips hypervisor instance
:param group: multicast group to bind
:param port: port for binding
"""
_instance_count = 0
def __init__(self, hypervisor, group, port):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_Mcast._instance_count
NIO_Mcast._instance_count += 1
self._name = 'nio_mcast' + str(self._id)
self._group = group
self._port = port
self._ttl = 1 # default TTL
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@asyncio.coroutine
def create(self):
yield from self._hypervisor.send("nio create_mcast {name} {mgroup} {mport}".format(name=self._name,
mgroup=self._group,
mport=self._port))
log.info("NIO Multicast {name} created with mgroup={group}, mport={port}".format(name=self._name,
group=self._group,
port=self._port))
@property
def group(self):
"""
Returns the multicast group
:returns: multicast group address
"""
return self._group
@property
def port(self):
"""
Returns the port
:returns: port number
"""
return self._port
@property
def ttl(self):
"""
Returns the TTL associated with the multicast address.
:returns: TTL value
"""
return self._ttl
def set_ttl(self, ttl):
"""
Sets the TTL for the multicast address
:param ttl: TTL value
"""
yield from self._hypervisor.send("nio set_mcast_ttl {name} {ttl}".format(name=self._name,
ttl=ttl))
self._ttl = ttl
@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for dummy NIOs (mostly for tests).
"""
import asyncio
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_Null(NIO):
"""
Dynamips NULL NIO.
:param hypervisor: Dynamips hypervisor instance
"""
_instance_count = 0
def __init__(self, hypervisor):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_Null._instance_count
NIO_Null._instance_count += 1
self._name = 'nio_null' + str(self._id)
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@asyncio.coroutine
def create(self):
yield from self._hypervisor.send("nio create_null {}".format(self._name))
log.info("NIO NULL {name} created.".format(name=self._name))
@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for TAP NIOs (UNIX based OSes only).
"""
import asyncio
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_TAP(NIO):
"""
Dynamips TAP NIO.
:param hypervisor: Dynamips hypervisor instance
:param tap_device: TAP device name (e.g. tap0)
"""
_instance_count = 0
def __init__(self, hypervisor, tap_device):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_TAP._instance_count
NIO_TAP._instance_count += 1
self._name = 'nio_tap' + str(self._id)
self._tap_device = tap_device
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@asyncio.coroutine
def create(self):
yield from self._hypervisor.send("nio create_tap {name} {tap}".format(name=self._name, tap=self._tap_device))
log.info("NIO TAP {name} created with device {device}".format(name=self._name, device=self._tap_device))
@property
def tap_device(self):
"""
Returns the TAP device used by this NIO.
:returns: the TAP device name
"""
return self._tap_device
+102
View File
@@ -0,0 +1,102 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for UDP NIOs.
"""
import asyncio
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_UDP(NIO):
"""
Dynamips UDP NIO.
:param hypervisor: Dynamips hypervisor instance
:param lport: local port number
:param rhost: remote address/host
:param rport: remote port number
"""
_instance_count = 0
def __init__(self, hypervisor, lport, rhost, rport):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_UDP._instance_count
NIO_UDP._instance_count += 1
self._name = 'nio_udp' + str(self._id)
self._lport = lport
self._rhost = rhost
self._rport = rport
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@asyncio.coroutine
def create(self):
yield from self._hypervisor.send("nio create_udp {name} {lport} {rhost} {rport}".format(name=self._name,
lport=self._lport,
rhost=self._rhost,
rport=self._rport))
log.info("NIO UDP {name} created with lport={lport}, rhost={rhost}, rport={rport}".format(name=self._name,
lport=self._lport,
rhost=self._rhost,
rport=self._rport))
@property
def lport(self):
"""
Returns the local port
:returns: local port number
"""
return self._lport
@property
def rhost(self):
"""
Returns the remote host
:returns: remote address/host
"""
return self._rhost
@property
def rport(self):
"""
Returns the remote port
:returns: remote port number
"""
return self._rport
@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for automatic UDP NIOs.
"""
import asyncio
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_UDP_auto(NIO):
"""
Dynamips auto UDP NIO.
:param hypervisor: Dynamips hypervisor instance
:param laddr: local address
:param lport_start: start local port range
:param lport_end: end local port range
"""
_instance_count = 0
def __init__(self, hypervisor, laddr, lport_start, lport_end):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_UDP_auto._instance_count
NIO_UDP_auto._instance_count += 1
self._name = 'nio_udp_auto' + str(self._id)
self._laddr = laddr
self._lport = None
self._raddr = None
self._rport = None
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@asyncio.coroutine
def create(self):
port = yield from self._hypervisor.send("nio create_udp_auto {name} {laddr} {lport_start} {lport_end}".format(name=self._name,
laddr=self._laddr,
lport_start=self._lport_start,
lport_end=self._lport_end))
self._lport = int(port[0])
log.info("NIO UDP AUTO {name} created with laddr={laddr}, lport_start={start}, lport_end={end}".format(name=self._name,
laddr=self._laddr,
start=self._lport_start,
end=self._lport_end))
@property
def laddr(self):
"""
Returns the local address
:returns: local address
"""
return self._laddr
@property
def lport(self):
"""
Returns the local port
:returns: local port number
"""
return self._lport
@property
def raddr(self):
"""
Returns the remote address
:returns: remote address
"""
return self._raddr
@property
def rport(self):
"""
Returns the remote port
:returns: remote port number
"""
return self._rport
@asyncio.coroutine
def connect(self, raddr, rport):
"""
Connects this NIO to a remote socket
:param raddr: remote address
:param rport: remote port number
"""
yield from self._hypervisor.send("nio connect_udp_auto {name} {raddr} {rport}".format(name=self._name,
raddr=raddr,
rport=rport))
self._raddr = raddr
self._rport = rport
log.info("NIO UDP AUTO {name} connected to {raddr}:{rport}".format(name=self._name,
raddr=raddr,
rport=rport))
@@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for UNIX NIOs (Unix based OSes only).
"""
import asyncio
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_UNIX(NIO):
"""
Dynamips UNIX NIO.
:param hypervisor: Dynamips hypervisor instance
:param local_file: local UNIX socket filename
:param remote_file: remote UNIX socket filename
"""
_instance_count = 0
def __init__(self, hypervisor, local_file, remote_file):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_UNIX._instance_count
NIO_UNIX._instance_count += 1
self._name = 'nio_unix' + str(self._id)
self._local_file = local_file
self._remote_file = remote_file
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@asyncio.coroutine
def create(self):
yield from self._hypervisor.send("nio create_unix {name} {local} {remote}".format(name=self._name,
local=self._local_file,
remote=self._remote_file))
log.info("NIO UNIX {name} created with local file {local} and remote file {remote}".format(name=self._name,
local=self._local_file,
remote=self._remote_file))
@property
def local_file(self):
"""
Returns the local UNIX socket.
:returns: local UNIX socket filename
"""
return self._local_file
@property
def remote_file(self):
"""
Returns the remote UNIX socket.
:returns: remote UNIX socket filename
"""
return self._remote_file
@@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for VDE (Virtual Distributed Ethernet) NIOs (Unix based OSes only).
"""
from .nio import NIO
import logging
log = logging.getLogger(__name__)
class NIO_VDE(NIO):
"""
Dynamips VDE NIO.
:param hypervisor: Dynamips hypervisor instance
:param control_file: VDE control filename
:param local_file: VDE local filename
"""
_instance_count = 0
def __init__(self, hypervisor, control_file, local_file):
NIO.__init__(self, hypervisor)
# create an unique ID
self._id = NIO_VDE._instance_count
NIO_VDE._instance_count += 1
self._name = 'nio_vde' + str(self._id)
self._control_file = control_file
self._local_file = local_file
self._hypervisor.send("nio create_vde {name} {control} {local}".format(name=self._name,
control=control_file,
local=local_file))
log.info("NIO VDE {name} created with control={control}, local={local}".format(name=self._name,
control=control_file,
local=local_file))
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 0
@property
def control_file(self):
"""
Returns the VDE control file.
:returns: VDE control filename
"""
return self._control_file
@property
def local_file(self):
"""
Returns the VDE local file.
:returns: VDE local filename
"""
return self._local_file
Whitespace-only changes.
+161
View File
@@ -0,0 +1,161 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for Dynamips virtual Cisco 1700 instances module ("c1700")
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L428
"""
from .router import Router
from ..adapters.c1700_mb_1fe import C1700_MB_1FE
from ..adapters.c1700_mb_wic1 import C1700_MB_WIC1
import logging
log = logging.getLogger(__name__)
class C1700(Router):
"""
Dynamips c1700 router.
:param hypervisor: Dynamips hypervisor instance
:param name: name for this router
:param router_id: router instance ID
:param chassis: chassis for this router:
1720, 1721, 1750, 1751 or 1760 (default = 1720).
1710 is not supported.
"""
def __init__(self, hypervisor, name, router_id=None, chassis="1720"):
Router.__init__(self, hypervisor, name, router_id, platform="c1700")
# Set default values for this platform
self._ram = 128
self._nvram = 32
self._disk0 = 0
self._disk1 = 0
self._chassis = chassis
self._iomem = 15 # percentage
self._clock_divisor = 8
self._sparsemem = False
if chassis != "1720":
self.chassis = chassis
self._setup_chassis()
def defaults(self):
"""
Returns all the default attribute values for this platform.
:returns: default values (dictionary)
"""
router_defaults = Router.defaults(self)
platform_defaults = {"ram": self._ram,
"nvram": self._nvram,
"disk0": self._disk0,
"disk1": self._disk1,
"chassis": self._chassis,
"iomem": self._iomem,
"clock_divisor": self._clock_divisor,
"sparsemem": self._sparsemem}
# update the router defaults with the platform specific defaults
router_defaults.update(platform_defaults)
return router_defaults
def list(self):
"""
Returns all c1700 instances
:returns: c1700 instance list
"""
return self._hypervisor.send("c1700 list")
def _setup_chassis(self):
"""
Sets up the router with the corresponding chassis
(create slots and insert default adapters).
"""
# With 1751 and 1760, WICs in WIC slot 1 show up as in slot 1, not 0
# e.g. s1/0 not s0/2
if self._chassis in ['1751', '1760']:
self._create_slots(2)
self._slots[1] = C1700_MB_WIC1()
else:
self._create_slots(1)
self._slots[0] = C1700_MB_1FE()
@property
def chassis(self):
"""
Returns the chassis.
:returns: chassis string
"""
return self._chassis
@chassis.setter
def chassis(self, chassis):
"""
Sets the chassis.
:param: chassis string:
1720, 1721, 1750, 1751 or 1760
"""
self._hypervisor.send("c1700 set_chassis {name} {chassis}".format(name=self._name,
chassis=chassis))
log.info("router {name} [id={id}]: chassis set to {chassis}".format(name=self._name,
id=self._id,
chassis=chassis))
self._chassis = chassis
self._setup_chassis()
@property
def iomem(self):
"""
Returns I/O memory size for this router.
:returns: I/O memory size (integer)
"""
return self._iomem
@iomem.setter
def iomem(self, iomem):
"""
Sets I/O memory size for this router.
:param iomem: I/O memory size
"""
self._hypervisor.send("c1700 set_iomem {name} {size}".format(name=self._name,
size=iomem))
log.info("router {name} [id={id}]: I/O memory updated from {old_iomem}% to {new_iomem}%".format(name=self._name,
id=self._id,
old_iomem=self._iomem,
new_iomem=iomem))
self._iomem = iomem
+170
View File
@@ -0,0 +1,170 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for Dynamips virtual Cisco 2600 instances module ("c2600")
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L404
"""
from .router import Router
from ..adapters.c2600_mb_1e import C2600_MB_1E
from ..adapters.c2600_mb_2e import C2600_MB_2E
from ..adapters.c2600_mb_1fe import C2600_MB_1FE
from ..adapters.c2600_mb_2fe import C2600_MB_2FE
import logging
log = logging.getLogger(__name__)
class C2600(Router):
"""
Dynamips c2600 router.
:param hypervisor: Dynamips hypervisor instance
:param name: name for this router
:param router_id: router instance ID
:param chassis: chassis for this router:
2610, 2611, 2620, 2621, 2610XM, 2611XM
2620XM, 2621XM, 2650XM or 2651XM (default = 2610).
"""
# adapters to insert by default corresponding the
# chosen chassis.
integrated_adapters = {"2610": C2600_MB_1E,
"2611": C2600_MB_2E,
"2620": C2600_MB_1FE,
"2621": C2600_MB_2FE,
"2610XM": C2600_MB_1FE,
"2611XM": C2600_MB_2FE,
"2620XM": C2600_MB_1FE,
"2621XM": C2600_MB_2FE,
"2650XM": C2600_MB_1FE,
"2651XM": C2600_MB_2FE}
def __init__(self, hypervisor, name, router_id=None, chassis="2610"):
Router.__init__(self, hypervisor, name, router_id, platform="c2600")
# Set default values for this platform
self._ram = 128
self._nvram = 128
self._disk0 = 0
self._disk1 = 0
self._chassis = chassis
self._iomem = 15 # percentage
self._clock_divisor = 8
self._sparsemem = False
if chassis != "2610":
self.chassis = chassis
self._setup_chassis()
def defaults(self):
"""
Returns all the default attribute values for this platform.
:returns: default values (dictionary)
"""
router_defaults = Router.defaults(self)
platform_defaults = {"ram": self._ram,
"nvram": self._nvram,
"disk0": self._disk0,
"disk1": self._disk1,
"iomem": self._iomem,
"chassis": self._chassis,
"clock_divisor": self._clock_divisor,
"sparsemem": self._sparsemem}
# update the router defaults with the platform specific defaults
router_defaults.update(platform_defaults)
return router_defaults
def list(self):
"""
Returns all c2600 instances
:returns: c2600 instance list
"""
return self._hypervisor.send("c2600 list")
def _setup_chassis(self):
"""
Sets up the router with the corresponding chassis
(create slots and insert default adapters).
"""
self._create_slots(2)
self._slots[0] = self.integrated_adapters[self._chassis]()
@property
def chassis(self):
"""
Returns the chassis.
:returns: chassis string
"""
return self._chassis
@chassis.setter
def chassis(self, chassis):
"""
Sets the chassis.
:param: chassis string:
2610, 2611, 2620, 2621, 2610XM, 2611XM
2620XM, 2621XM, 2650XM or 2651XM
"""
self._hypervisor.send("c2600 set_chassis {name} {chassis}".format(name=self._name,
chassis=chassis))
log.info("router {name} [id={id}]: chassis set to {chassis}".format(name=self._name,
id=self._id,
chassis=chassis))
self._chassis = chassis
self._setup_chassis()
@property
def iomem(self):
"""
Returns I/O memory size for this router.
:returns: I/O memory size (integer)
"""
return self._iomem
@iomem.setter
def iomem(self, iomem):
"""
Sets I/O memory size for this router.
:param iomem: I/O memory size
"""
self._hypervisor.send("c2600 set_iomem {name} {size}".format(name=self._name,
size=iomem))
log.info("router {name} [id={id}]: I/O memory updated from {old_iomem}% to {new_iomem}%".format(name=self._name,
id=self._id,
old_iomem=self._iomem,
new_iomem=iomem))
self._iomem = iomem
+107
View File
@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for Dynamips virtual Cisco 2691 instances module ("c2691")
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L387
"""
from .router import Router
from ..adapters.gt96100_fe import GT96100_FE
import logging
log = logging.getLogger(__name__)
class C2691(Router):
"""
Dynamips c2691 router.
:param hypervisor: Dynamips hypervisor instance
:param name: name for this router
:param router_id: router instance ID
"""
def __init__(self, hypervisor, name, router_id=None):
Router.__init__(self, hypervisor, name, router_id, platform="c2691")
# Set default values for this platform
self._ram = 192
self._nvram = 112
self._disk0 = 16
self._disk1 = 0
self._iomem = 5 # percentage
self._clock_divisor = 8
self._create_slots(2)
self._slots[0] = GT96100_FE()
def defaults(self):
"""
Returns all the default attribute values for this platform.
:returns: default values (dictionary)
"""
router_defaults = Router.defaults(self)
platform_defaults = {"ram": self._ram,
"nvram": self._nvram,
"disk0": self._disk0,
"disk1": self._disk1,
"iomem": self._iomem,
"clock_divisor": self._clock_divisor}
# update the router defaults with the platform specific defaults
router_defaults.update(platform_defaults)
return router_defaults
def list(self):
"""
Returns all c2691 instances
:returns: c2691 instance list
"""
return self._hypervisor.send("c2691 list")
@property
def iomem(self):
"""
Returns I/O memory size for this router.
:returns: I/O memory size (integer)
"""
return self._iomem
@iomem.setter
def iomem(self, iomem):
"""
Sets I/O memory size for this router.
:param iomem: I/O memory size
"""
self._hypervisor.send("c2691 set_iomem {name} {size}".format(name=self._name,
size=iomem))
log.info("router {name} [id={id}]: I/O memory updated from {old_iomem}% to {new_iomem}%".format(name=self._name,
id=self._id,
old_iomem=self._iomem,
new_iomem=iomem))
self._iomem = iomem
+155
View File
@@ -0,0 +1,155 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for Dynamips virtual Cisco 3600 instances module ("c3600")
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L366
"""
from .router import Router
from ..adapters.leopard_2fe import Leopard_2FE
import logging
log = logging.getLogger(__name__)
class C3600(Router):
"""
Dynamips c3600 router.
:param hypervisor: Dynamips hypervisor instance
:param name: name for this router
:param router_id: router instance ID
:param chassis: chassis for this router:
3620, 3640 or 3660 (default = 3640).
"""
def __init__(self, hypervisor, name, router_id=None, chassis="3640"):
Router.__init__(self, hypervisor, name, router_id, platform="c3600")
# Set default values for this platform
self._ram = 192
self._nvram = 128
self._disk0 = 0
self._disk1 = 0
self._iomem = 5 # percentage
self._chassis = chassis
self._clock_divisor = 4
if chassis != "3640":
self.chassis = chassis
self._setup_chassis()
def defaults(self):
"""
Returns all the default attribute values for this platform.
:returns: default values (dictionary)
"""
router_defaults = Router.defaults(self)
platform_defaults = {"ram": self._ram,
"nvram": self._nvram,
"disk0": self._disk0,
"disk1": self._disk1,
"iomem": self._iomem,
"chassis": self._chassis,
"clock_divisor": self._clock_divisor}
# update the router defaults with the platform specific defaults
router_defaults.update(platform_defaults)
return router_defaults
def list(self):
"""
Returns all c3600 instances
:returns: c3600 instance list
"""
return self._hypervisor.send("c3600 list")
def _setup_chassis(self):
"""
Sets up the router with the corresponding chassis
(create slots and insert default adapters).
"""
if self._chassis == "3620":
self._create_slots(2)
elif self._chassis == "3640":
self._create_slots(4)
elif self._chassis == "3660":
self._create_slots(7)
self._slots[0] = Leopard_2FE()
@property
def chassis(self):
"""
Returns the chassis.
:returns: chassis string
"""
return self._chassis
@chassis.setter
def chassis(self, chassis):
"""
Sets the chassis.
:param: chassis string: 3620, 3640 or 3660
"""
self._hypervisor.send("c3600 set_chassis {name} {chassis}".format(name=self._name,
chassis=chassis))
log.info("router {name} [id={id}]: chassis set to {chassis}".format(name=self._name,
id=self._id,
chassis=chassis))
self._chassis = chassis
self._setup_chassis()
@property
def iomem(self):
"""
Returns I/O memory size for this router.
:returns: I/O memory size (integer)
"""
return self._iomem
@iomem.setter
def iomem(self, iomem):
"""
Set I/O memory size for this router.
:param iomem: I/O memory size
"""
self._hypervisor.send("c3600 set_iomem {name} {size}".format(name=self._name,
size=iomem))
log.info("router {name} [id={id}]: I/O memory updated from {old_iomem}% to {new_iomem}%".format(name=self._name,
id=self._id,
old_iomem=self._iomem,
new_iomem=iomem))
self._iomem = iomem
+107
View File
@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for Dynamips virtual Cisco 3725 instances module ("c3725")
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L346
"""
from .router import Router
from ..adapters.gt96100_fe import GT96100_FE
import logging
log = logging.getLogger(__name__)
class C3725(Router):
"""
Dynamips c3725 router.
:param hypervisor: Dynamips hypervisor instance
:param name: name for this router
:param router_id: router instance ID
"""
def __init__(self, hypervisor, name, router_id=None):
Router.__init__(self, hypervisor, name, router_id, platform="c3725")
# Set default values for this platform
self._ram = 128
self._nvram = 112
self._disk0 = 16
self._disk1 = 0
self._iomem = 5 # percentage
self._clock_divisor = 8
self._create_slots(3)
self._slots[0] = GT96100_FE()
def defaults(self):
"""
Returns all the default attribute values for this platform.
:returns: default values (dictionary)
"""
router_defaults = Router.defaults(self)
platform_defaults = {"ram": self._ram,
"nvram": self._nvram,
"disk0": self._disk0,
"disk1": self._disk1,
"iomem": self._iomem,
"clock_divisor": self._clock_divisor}
# update the router defaults with the platform specific defaults
router_defaults.update(platform_defaults)
return router_defaults
def list(self):
"""
Returns all c3725 instances.
:returns: c3725 instance list
"""
return self._hypervisor.send("c3725 list")
@property
def iomem(self):
"""
Returns I/O memory size for this router.
:returns: I/O memory size (integer)
"""
return self._iomem
@iomem.setter
def iomem(self, iomem):
"""
Sets I/O memory size for this router.
:param iomem: I/O memory size
"""
self._hypervisor.send("c3725 set_iomem {name} {size}".format(name=self._name,
size=iomem))
log.info("router {name} [id={id}]: I/O memory updated from {old_iomem}% to {new_iomem}%".format(name=self._name,
id=self._id,
old_iomem=self._iomem,
new_iomem=iomem))
self._iomem = iomem
+107
View File
@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for Dynamips virtual Cisco 3745 instances module ("c3745")
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L326
"""
from .router import Router
from ..adapters.gt96100_fe import GT96100_FE
import logging
log = logging.getLogger(__name__)
class C3745(Router):
"""
Dynamips c3745 router.
:param hypervisor: Dynamips hypervisor instance
:param name: name for this router
:param router_id: router instance ID
"""
def __init__(self, hypervisor, name, router_id=None):
Router.__init__(self, hypervisor, name, router_id, platform="c3745")
# Set default values for this platform
self._ram = 256
self._nvram = 304
self._disk0 = 16
self._disk1 = 0
self._iomem = 5 # percentage
self._clock_divisor = 8
self._create_slots(5)
self._slots[0] = GT96100_FE()
def defaults(self):
"""
Returns all the default attribute values for this platform.
:returns: default values (dictionary)
"""
router_defaults = Router.defaults(self)
platform_defaults = {"ram": self._ram,
"nvram": self._nvram,
"disk0": self._disk0,
"disk1": self._disk1,
"iomem": self._iomem,
"clock_divisor": self._clock_divisor}
# update the router defaults with the platform specific defaults
router_defaults.update(platform_defaults)
return router_defaults
def list(self):
"""
Returns all c3745 instances.
:returns: c3745 instance list
"""
return self._hypervisor.send("c3745 list")
@property
def iomem(self):
"""
Returns I/O memory size for this router.
:returns: I/O memory size (integer)
"""
return self._iomem
@iomem.setter
def iomem(self, iomem):
"""
Sets I/O memory size for this router.
:param iomem: I/O memory size
"""
self._hypervisor.send("c3745 set_iomem {name} {size}".format(name=self._name,
size=iomem))
log.info("router {name} [id={id}]: I/O memory updated from {old_iomem}% to {new_iomem}%".format(name=self._name,
id=self._id,
old_iomem=self._iomem,
new_iomem=iomem))
self._iomem = iomem
+249
View File
@@ -0,0 +1,249 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
Interface for Dynamips virtual Cisco 7200 instances module ("c7200")
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L294
"""
from ..dynamips_error import DynamipsError
from .router import Router
from ..adapters.c7200_io_fe import C7200_IO_FE
from ..adapters.c7200_io_ge_e import C7200_IO_GE_E
import logging
log = logging.getLogger(__name__)
class C7200(Router):
"""
Dynamips c7200 router (model is 7206).
:param hypervisor: Dynamips hypervisor instance
:param name: name for this router
:param router_id: router instance ID
:param npe: default NPE
"""
def __init__(self, hypervisor, name, router_id=None, npe="npe-400"):
Router.__init__(self, hypervisor, name, router_id, platform="c7200")
# Set default values for this platform
self._ram = 512
self._nvram = 128
self._disk0 = 64
self._disk1 = 0
self._npe = npe
self._midplane = "vxr"
self._clock_divisor = 4
if npe != "npe-400":
self.npe = npe
# 4 sensors with a default temperature of 22C:
# sensor 1 = I/0 controller inlet
# sensor 2 = I/0 controller outlet
# sensor 3 = NPE inlet
# sensor 4 = NPE outlet
self._sensors = [22, 22, 22, 22]
# 2 power supplies powered on
self._power_supplies = [1, 1]
self._create_slots(7)
# first slot is a mandatory Input/Output controller (based on NPE type)
if npe == "npe-g2":
self.slot_add_binding(0, C7200_IO_GE_E())
else:
self.slot_add_binding(0, C7200_IO_FE())
def defaults(self):
"""
Returns all the default attribute values for this platform.
:returns: default values (dictionary)
"""
router_defaults = Router.defaults(self)
platform_defaults = {"ram": self._ram,
"nvram": self._nvram,
"disk0": self._disk0,
"disk1": self._disk1,
"npe": self._npe,
"midplane": self._midplane,
"clock_divisor": self._clock_divisor,
"sensors": self._sensors,
"power_supplies": self._power_supplies}
# update the router defaults with the platform specific defaults
router_defaults.update(platform_defaults)
return router_defaults
def list(self):
"""
Returns all c7200 instances.
:returns: c7200 instance list
"""
return self._hypervisor.send("c7200 list")
@property
def npe(self):
"""
Returns the NPE model.
:returns: NPE model string (e.g. "npe-200")
"""
return self._npe
@npe.setter
def npe(self, npe):
"""
Sets the NPE model.
:params npe: NPE model string (e.g. "npe-200")
NPE models are npe-100, npe-150, npe-175, npe-200,
npe-225, npe-300, npe-400 and npe-g2 (PowerPC c7200 only)
"""
if self.is_running():
raise DynamipsError("Cannot change NPE on running router")
self._hypervisor.send("c7200 set_npe {name} {npe}".format(name=self._name,
npe=npe))
log.info("router {name} [id={id}]: NPE updated from {old_npe} to {new_npe}".format(name=self._name,
id=self._id,
old_npe=self._npe,
new_npe=npe))
self._npe = npe
@property
def midplane(self):
"""
Returns the midplane model.
:returns: midplane model string (e.g. "vxr" or "std")
"""
return self._midplane
@midplane.setter
def midplane(self, midplane):
"""
Sets the midplane model.
:returns: midplane model string (e.g. "vxr" or "std")
"""
self._hypervisor.send("c7200 set_midplane {name} {midplane}".format(name=self._name,
midplane=midplane))
log.info("router {name} [id={id}]: midplane updated from {old_midplane} to {new_midplane}".format(name=self._name,
id=self._id,
old_midplane=self._midplane,
new_midplane=midplane))
self._midplane = midplane
@property
def sensors(self):
"""
Returns the 4 sensors with temperature in degree Celcius.
:returns: list of 4 sensor temperatures
"""
return self._sensors
@sensors.setter
def sensors(self, sensors):
"""
Sets the 4 sensors with temperature in degree Celcius.
:param sensors: list of 4 sensor temperatures corresponding to
sensor 1 = I/0 controller inlet
sensor 2 = I/0 controller outlet
sensor 3 = NPE inlet
sensor 4 = NPE outlet
Example: [22, 22, 22, 22]
"""
sensor_id = 0
for sensor in sensors:
self._hypervisor.send("c7200 set_temp_sensor {name} {sensor_id} {temp}".format(name=self._name,
sensor_id=sensor_id,
temp=sensor))
log.info("router {name} [id={id}]: sensor {sensor_id} temperature updated from {old_temp}C to {new_temp}C".format(name=self._name,
id=self._id,
sensor_id=sensor_id,
old_temp=self._sensors[sensor_id],
new_temp=sensors[sensor_id]))
sensor_id += 1
self._sensors = sensors
@property
def power_supplies(self):
"""
Returns the 2 power supplies with 0 = off, 1 = on.
:returns: list of 2 power supplies.
"""
return self._power_supplies
@power_supplies.setter
def power_supplies(self, power_supplies):
"""
Sets the 2 power supplies with 0 = off, 1 = on.
:param power_supplies: list of 2 power supplies.
Example: [1, 0] = first power supply is on, second is off.
"""
power_supply_id = 0
for power_supply in power_supplies:
self._hypervisor.send("c7200 set_power_supply {name} {power_supply_id} {powered_on}".format(name=self._name,
power_supply_id=power_supply_id,
powered_on=power_supply))
log.info("router {name} [id={id}]: power supply {power_supply_id} state updated to {powered_on}".format(name=self._name,
id=self._id,
power_supply_id=power_supply_id,
powered_on=power_supply))
power_supply_id += 1
self._power_supplies = power_supplies
def start(self):
"""
Starts this router.
At least the IOS image must be set before starting it.
"""
# trick: we must send sensors and power supplies info after starting the router
# otherwise they are not taken into account (Dynamips bug?)
Router.start(self)
if self._sensors != [22, 22, 22, 22]:
self.sensors = self._sensors
if self._power_supplies != [1, 1]:
self.power_supplies = self._power_supplies
File diff suppressed because it is too large. Load diff