mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 22:11:14 +02:00
New Dynamips integration part 3
This commit is contained in:
1 parent
37945585b9
commit
79a57ca420
51 files changed
+1257
-2386
No files matched your search
@@ -19,81 +19,18 @@
|
||||
Dynamips server module.
|
||||
"""
|
||||
|
||||
import aiohttp
|
||||
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 gns3server.utils.interfaces import get_windows_interfaces
|
||||
from pkg_resources import parse_version
|
||||
from ..base_manager import BaseManager
|
||||
from .dynamips_error import DynamipsError
|
||||
@@ -101,6 +38,18 @@ from .hypervisor import Hypervisor
|
||||
from .nodes.router import Router
|
||||
from .dynamips_vm import DynamipsVM
|
||||
|
||||
# NIOs
|
||||
from .nios.nio_udp import NIOUDP
|
||||
from .nios.nio_udp_auto import NIOUDPAuto
|
||||
from .nios.nio_unix import NIOUNIX
|
||||
from .nios.nio_vde import NIOVDE
|
||||
from .nios.nio_tap import NIOTAP
|
||||
from .nios.nio_generic_ethernet import NIOGenericEthernet
|
||||
from .nios.nio_linux_ethernet import NIOLinuxEthernet
|
||||
from .nios.nio_fifo import NIOFIFO
|
||||
from .nios.nio_mcast import NIOMcast
|
||||
from .nios.nio_null import NIONull
|
||||
|
||||
|
||||
class Dynamips(BaseManager):
|
||||
|
||||
@@ -113,7 +62,35 @@ class Dynamips(BaseManager):
|
||||
|
||||
# FIXME: temporary
|
||||
self._working_dir = "/tmp"
|
||||
self._dynamips_path = "/usr/bin/dynamips"
|
||||
|
||||
@asyncio.coroutine
|
||||
def unload(self):
|
||||
|
||||
yield from BaseManager.unload(self)
|
||||
Router.reset()
|
||||
|
||||
# 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
|
||||
|
||||
@property
|
||||
def dynamips_path(self):
|
||||
"""
|
||||
Returns the path to Dynamips.
|
||||
|
||||
:returns: path
|
||||
"""
|
||||
|
||||
return self._dynamips_path
|
||||
|
||||
def find_dynamips(self):
|
||||
|
||||
@@ -168,6 +145,9 @@ class Dynamips(BaseManager):
|
||||
:returns: the new hypervisor instance
|
||||
"""
|
||||
|
||||
if not self._dynamips_path:
|
||||
self.find_dynamips()
|
||||
|
||||
try:
|
||||
# let the OS find an unused port for the Dynamips hypervisor
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
@@ -190,323 +170,97 @@ class Dynamips(BaseManager):
|
||||
|
||||
return hypervisor
|
||||
|
||||
def create_nio(self, executable, nio_settings):
|
||||
"""
|
||||
Creates a new NIO.
|
||||
|
||||
:param nio_settings: information to create the NIO
|
||||
|
||||
:returns: a NIO object
|
||||
"""
|
||||
|
||||
nio = None
|
||||
if nio_settings["type"] == "nio_udp":
|
||||
lport = nio_settings["lport"]
|
||||
rhost = nio_settings["rhost"]
|
||||
rport = nio_settings["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 aiohttp.web.HTTPInternalServerError(text="Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
|
||||
nio = NIOUDP(lport, rhost, rport)
|
||||
elif nio_settings["type"] == "nio_tap":
|
||||
tap_device = nio_settings["tap_device"]
|
||||
if not self._has_privileged_access(executable):
|
||||
raise aiohttp.web.HTTPForbidden(text="{} has no privileged access to {}.".format(executable, tap_device))
|
||||
nio = NIOTAP(tap_device)
|
||||
assert nio is not None
|
||||
return nio
|
||||
|
||||
def create_nio(self, node, nio_settings):
|
||||
"""
|
||||
Creates a new NIO.
|
||||
|
||||
:param node: Dynamips node instance
|
||||
:param nio_settings: information to create the NIO
|
||||
|
||||
:returns: a NIO object
|
||||
"""
|
||||
|
||||
nio = None
|
||||
if nio_settings["type"] == "nio_udp":
|
||||
lport = nio_settings["lport"]
|
||||
rhost = nio_settings["rhost"]
|
||||
rport = nio_settings["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 = NIOUDP(node.hypervisor, lport, rhost, rport)
|
||||
else:
|
||||
nio.connect(rhost, rport)
|
||||
elif nio_settings["type"] == "nio_generic_ethernet":
|
||||
ethernet_device = nio_settings["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 = NIOGenericEthernet(node.hypervisor, ethernet_device)
|
||||
elif nio_settings["type"] == "nio_linux_ethernet":
|
||||
if sys.platform.startswith("win"):
|
||||
raise DynamipsError("This NIO type is not supported on Windows")
|
||||
ethernet_device = nio_settings["ethernet_device"]
|
||||
nio = NIOLinuxEthernet(node.hypervisor, ethernet_device)
|
||||
elif nio_settings["type"] == "nio_tap":
|
||||
tap_device = nio_settings["tap_device"]
|
||||
nio = NIOTAP(node.hypervisor, tap_device)
|
||||
elif nio_settings["type"] == "nio_unix":
|
||||
local_file = nio_settings["local_file"]
|
||||
remote_file = nio_settings["remote_file"]
|
||||
nio = NIOUNIX(node.hypervisor, local_file, remote_file)
|
||||
elif nio_settings["type"] == "nio_vde":
|
||||
control_file = nio_settings["control_file"]
|
||||
local_file = nio_settings["local_file"]
|
||||
nio = NIOVDE(node.hypervisor, control_file, local_file)
|
||||
elif nio_settings["type"] == "nio_null":
|
||||
nio = NIONull(node.hypervisor)
|
||||
return nio
|
||||
|
||||
# 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.
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
import asyncio
|
||||
|
||||
from .dynamips_error import DynamipsError
|
||||
from .nios.nio_udp_auto import NIO_UDP_auto
|
||||
from .nios.nio_udp_auto import NIOUDPAuto
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -415,7 +415,7 @@ class DynamipsHypervisor:
|
||||
"""
|
||||
|
||||
# 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)
|
||||
nio = NIOUDPAuto(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
|
||||
|
||||
@@ -42,9 +42,9 @@ class DynamipsVM:
|
||||
Factory to create an Router object based on the correct platform.
|
||||
"""
|
||||
|
||||
def __new__(cls, name, vm_id, project, manager, platform, **kwargs):
|
||||
def __new__(cls, name, vm_id, project, manager, dynamips_id, platform, **kwargs):
|
||||
|
||||
if platform not in PLATFORMS:
|
||||
raise DynamipsError("Unknown router platform: {}".format(platform))
|
||||
|
||||
return PLATFORMS[platform](name, vm_id, project, manager, **kwargs)
|
||||
return PLATFORMS[platform](name, vm_id, project, manager, dynamips_id, **kwargs)
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_FIFO(NIO):
|
||||
class NIOFIFO(NIO):
|
||||
"""
|
||||
Dynamips FIFO NIO.
|
||||
|
||||
@@ -40,8 +40,8 @@ class NIO_FIFO(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_FIFO._instance_count
|
||||
NIO_FIFO._instance_count += 1
|
||||
self._id = NIOFIFO._instance_count
|
||||
NIOFIFO._instance_count += 1
|
||||
self._name = 'nio_fifo' + str(self._id)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_GenericEthernet(NIO):
|
||||
class NIOGenericEthernet(NIO):
|
||||
"""
|
||||
Dynamips generic Ethernet NIO.
|
||||
|
||||
@@ -41,8 +41,8 @@ class NIO_GenericEthernet(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_GenericEthernet._instance_count
|
||||
NIO_GenericEthernet._instance_count += 1
|
||||
self._id = NIOGenericEthernet._instance_count
|
||||
NIOGenericEthernet._instance_count += 1
|
||||
self._name = 'nio_gen_eth' + str(self._id)
|
||||
self._ethernet_device = ethernet_device
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_LinuxEthernet(NIO):
|
||||
class NIOLinuxEthernet(NIO):
|
||||
"""
|
||||
Dynamips Linux Ethernet NIO.
|
||||
|
||||
@@ -41,8 +41,8 @@ class NIO_LinuxEthernet(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_LinuxEthernet._instance_count
|
||||
NIO_LinuxEthernet._instance_count += 1
|
||||
self._id = NIOLinuxEthernet._instance_count
|
||||
NIOLinuxEthernet._instance_count += 1
|
||||
self._name = 'nio_linux_eth' + str(self._id)
|
||||
self._ethernet_device = ethernet_device
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_Mcast(NIO):
|
||||
class NIOMcast(NIO):
|
||||
"""
|
||||
Dynamips Linux Ethernet NIO.
|
||||
|
||||
@@ -42,8 +42,8 @@ class NIO_Mcast(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_Mcast._instance_count
|
||||
NIO_Mcast._instance_count += 1
|
||||
self._id = NIOMcast._instance_count
|
||||
NIOMcast._instance_count += 1
|
||||
self._name = 'nio_mcast' + str(self._id)
|
||||
self._group = group
|
||||
self._port = port
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_Null(NIO):
|
||||
class NIONull(NIO):
|
||||
"""
|
||||
Dynamips NULL NIO.
|
||||
|
||||
@@ -40,8 +40,8 @@ class NIO_Null(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_Null._instance_count
|
||||
NIO_Null._instance_count += 1
|
||||
self._id = NIONull._instance_count
|
||||
NIONull._instance_count += 1
|
||||
self._name = 'nio_null' + str(self._id)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_TAP(NIO):
|
||||
class NIOTAP(NIO):
|
||||
"""
|
||||
Dynamips TAP NIO.
|
||||
|
||||
@@ -41,8 +41,8 @@ class NIO_TAP(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_TAP._instance_count
|
||||
NIO_TAP._instance_count += 1
|
||||
self._id = NIOTAP._instance_count
|
||||
NIOTAP._instance_count += 1
|
||||
self._name = 'nio_tap' + str(self._id)
|
||||
self._tap_device = tap_device
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_UDP(NIO):
|
||||
class NIOUDP(NIO):
|
||||
"""
|
||||
Dynamips UDP NIO.
|
||||
|
||||
@@ -43,8 +43,8 @@ class NIO_UDP(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_UDP._instance_count
|
||||
NIO_UDP._instance_count += 1
|
||||
self._id = NIOUDP._instance_count
|
||||
NIOUDP._instance_count += 1
|
||||
self._name = 'nio_udp' + str(self._id)
|
||||
self._lport = lport
|
||||
self._rhost = rhost
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_UDP_auto(NIO):
|
||||
class NIOUDPAuto(NIO):
|
||||
"""
|
||||
Dynamips auto UDP NIO.
|
||||
|
||||
@@ -43,8 +43,8 @@ class NIO_UDP_auto(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_UDP_auto._instance_count
|
||||
NIO_UDP_auto._instance_count += 1
|
||||
self._id = NIOUDPAuto._instance_count
|
||||
NIOUDPAuto._instance_count += 1
|
||||
self._name = 'nio_udp_auto' + str(self._id)
|
||||
|
||||
self._laddr = laddr
|
||||
|
||||
@@ -26,7 +26,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_UNIX(NIO):
|
||||
class NIOUNIX(NIO):
|
||||
"""
|
||||
Dynamips UNIX NIO.
|
||||
|
||||
@@ -42,8 +42,8 @@ class NIO_UNIX(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_UNIX._instance_count
|
||||
NIO_UNIX._instance_count += 1
|
||||
self._id = NIOUNIX._instance_count
|
||||
NIOUNIX._instance_count += 1
|
||||
self._name = 'nio_unix' + str(self._id)
|
||||
self._local_file = local_file
|
||||
self._remote_file = remote_file
|
||||
|
||||
@@ -25,7 +25,7 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_VDE(NIO):
|
||||
class NIOVDE(NIO):
|
||||
"""
|
||||
Dynamips VDE NIO.
|
||||
|
||||
@@ -41,8 +41,8 @@ class NIO_VDE(NIO):
|
||||
NIO.__init__(self, hypervisor)
|
||||
|
||||
# create an unique ID
|
||||
self._id = NIO_VDE._instance_count
|
||||
NIO_VDE._instance_count += 1
|
||||
self._id = NIOVDE._instance_count
|
||||
NIOVDE._instance_count += 1
|
||||
self._name = 'nio_vde' + str(self._id)
|
||||
self._control_file = control_file
|
||||
self._local_file = local_file
|
||||
|
||||
@@ -37,13 +37,14 @@ class C1700(Router):
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param chassis: chassis for this router:
|
||||
1720, 1721, 1750, 1751 or 1760 (default = 1720).
|
||||
1710 is not supported.
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, chassis="1720"):
|
||||
Router.__init__(self, name, vm_id, project, manager, platform="c1700")
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, chassis="1720"):
|
||||
Router.__init__(self, name, vm_id, project, manager, dynamips_id, platform="c1700")
|
||||
|
||||
# Set default values for this platform
|
||||
self._ram = 128
|
||||
|
||||
@@ -39,6 +39,7 @@ class C2600(Router):
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param chassis: chassis for this router:
|
||||
2610, 2611, 2620, 2621, 2610XM, 2611XM
|
||||
2620XM, 2621XM, 2650XM or 2651XM (default = 2610).
|
||||
@@ -57,8 +58,8 @@ class C2600(Router):
|
||||
"2650XM": C2600_MB_1FE,
|
||||
"2651XM": C2600_MB_2FE}
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, chassis="2610"):
|
||||
Router.__init__(self, name, vm_id, project, manager, platform="c2600")
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, chassis="2610"):
|
||||
Router.__init__(self, name, vm_id, project, manager, dynamips_id, platform="c2600")
|
||||
|
||||
# Set default values for this platform
|
||||
self._ram = 128
|
||||
|
||||
@@ -36,10 +36,11 @@ class C2691(Router):
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager):
|
||||
Router.__init__(self, name, vm_id, project, manager, platform="c2691")
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id):
|
||||
Router.__init__(self, name, vm_id, project, manager, dynamips_id, platform="c2691")
|
||||
|
||||
# Set default values for this platform
|
||||
self._ram = 192
|
||||
|
||||
@@ -36,12 +36,13 @@ class C3600(Router):
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param chassis: chassis for this router:
|
||||
3620, 3640 or 3660 (default = 3640).
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, chassis="3640"):
|
||||
Router.__init__(self, name, vm_id, project, manager, platform="c3600")
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, chassis="3640"):
|
||||
Router.__init__(self, name, vm_id, project, manager, dynamips_id, platform="c3600")
|
||||
|
||||
# Set default values for this platform
|
||||
self._ram = 192
|
||||
|
||||
@@ -36,10 +36,11 @@ class C3725(Router):
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager):
|
||||
Router.__init__(self, name, vm_id, project, manager, platform="c3725")
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id):
|
||||
Router.__init__(self, name, vm_id, project, manager, dynamips_id, platform="c3725")
|
||||
|
||||
# Set default values for this platform
|
||||
self._ram = 128
|
||||
|
||||
@@ -36,10 +36,11 @@ class C3745(Router):
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager):
|
||||
Router.__init__(self, name, vm_id, project, manager, platform="c3745")
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id):
|
||||
Router.__init__(self, name, vm_id, project, manager, dynamips_id, platform="c3745")
|
||||
|
||||
# Set default values for this platform
|
||||
self._ram = 256
|
||||
|
||||
@@ -39,11 +39,12 @@ class C7200(Router):
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param npe: Default NPE
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, npe="npe-400"):
|
||||
Router.__init__(self, name, vm_id, project, manager, platform="c7200")
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, npe="npe-400"):
|
||||
Router.__init__(self, name, vm_id, project, manager, dynamips_id, platform="c7200")
|
||||
|
||||
# Set default values for this platform
|
||||
self._ram = 512
|
||||
|
||||
@@ -42,20 +42,22 @@ class Router(BaseVM):
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param platform: Platform of this router
|
||||
"""
|
||||
|
||||
_instances = []
|
||||
_dynamips_ids = {}
|
||||
_status = {0: "inactive",
|
||||
1: "shutting down",
|
||||
2: "running",
|
||||
3: "suspended"}
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, platform="c7200", ghost_flag=False):
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id=None, platform="c7200", ghost_flag=False):
|
||||
|
||||
super().__init__(name, vm_id, project, manager)
|
||||
|
||||
self._hypervisor = None
|
||||
self._dynamips_id = dynamips_id
|
||||
self._closed = False
|
||||
self._name = name
|
||||
self._platform = platform
|
||||
@@ -81,12 +83,26 @@ class Router(BaseVM):
|
||||
self._confreg = "0x2102"
|
||||
self._console = None
|
||||
self._aux = None
|
||||
self._mac_addr = None
|
||||
self._mac_addr = ""
|
||||
self._system_id = "FTX0945W0MY" # processor board ID in IOS
|
||||
self._slots = []
|
||||
self._ghost_flag = ghost_flag
|
||||
|
||||
if not ghost_flag:
|
||||
self._dynamips_ids.setdefault(project.id, list())
|
||||
if not dynamips_id:
|
||||
# find a Dynamips ID if none is provided (0 < id <= 4096)
|
||||
self._dynamips_id = 0
|
||||
for identifier in range(1, 4097):
|
||||
if identifier not in self._dynamips_ids[project.id]:
|
||||
self._dynamips_id = identifier
|
||||
break
|
||||
if self._dynamips_id == 0:
|
||||
raise DynamipsError("Maximum number of Dynamips instances reached")
|
||||
else:
|
||||
if dynamips_id in self._dynamips_ids[project.id]:
|
||||
raise DynamipsError("Dynamips identifier {} is already used by another router".format(dynamips_id))
|
||||
self._dynamips_ids[project.id].append(self._dynamips_id)
|
||||
|
||||
if self._console is not None:
|
||||
self._console = self._manager.port_manager.reserve_console_port(self._console)
|
||||
@@ -97,12 +113,17 @@ class Router(BaseVM):
|
||||
self._aux = self._manager.port_manager.reserve_console_port(self._aux)
|
||||
else:
|
||||
self._aux = self._manager.port_manager.get_free_console_port()
|
||||
else:
|
||||
log.info("creating a new ghost IOS file")
|
||||
self._dynamips_id = 0
|
||||
self._name = "Ghost"
|
||||
|
||||
def __json__(self):
|
||||
|
||||
router_info = {"name": self.name,
|
||||
"vm_id": self.id,
|
||||
"project_id": self.project.id,
|
||||
"dynamips_id": self._dynamips_id,
|
||||
"platform": self._platform,
|
||||
"image": self._image,
|
||||
"startup_config": self._startup_config,
|
||||
@@ -138,14 +159,21 @@ class Router(BaseVM):
|
||||
|
||||
return router_info
|
||||
|
||||
@classmethod
|
||||
def reset(cls):
|
||||
"""
|
||||
Resets the instance count and the allocated instances list.
|
||||
"""
|
||||
|
||||
cls._dynamips_ids.clear()
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
self._hypervisor = yield from self.manager.start_new_hypervisor()
|
||||
|
||||
print("{} {} {}".format(self._name, self._id, self._platform))
|
||||
yield from self._hypervisor.send('vm create "{name}" {id} {platform}'.format(name=self._name,
|
||||
id=1, #FIXME: instance ID!
|
||||
id=self._dynamips_id,
|
||||
platform=self._platform))
|
||||
|
||||
if not self._ghost_flag:
|
||||
@@ -270,6 +298,9 @@ class Router(BaseVM):
|
||||
self._manager.port_manager.release_console_port(self._aux)
|
||||
self._aux = None
|
||||
|
||||
if self._dynamips_id in self._dynamips_ids[self._project.id]:
|
||||
self._dynamips_ids[self._project.id].remove(self._dynamips_id)
|
||||
|
||||
self._closed = True
|
||||
|
||||
@asyncio.coroutine
|
||||
|
||||
Reference in new issue
Block a user